Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Ingeniería de Telecomunicación
Autor:
Javier Arcenegui Almenara
Tutor:
Dr. Antonio Luque Estepa
Profesor titular de Ingeniería Electrónica
El tribunal nombrado para juzgar el Proyecto arriba indicado, compuesto por los siguientes miembros:
Presidente:
Vocales:
Secretario:
Sevilla, 2016
Agradezco especialmente a Dr. Antonio Luque su ayuda, consejos y esfuerzo en este proyecto. Y por los
conocimientos que me ha enseñado durante la carrera. También quiero agradecer a los demás profesores de la
carrera que he tenido el honor de que me dieran clase. Y a mis profesores y maestros de mis estudios
anteriores a la carrera. Que todos ellos han hecho que sepa todo lo que sé hoy.
Quiero agradecer también a mi familia por ayudarme y apoyarme. Principalmente a la primera persona que me
recomendó estudiar esta ingeniería, mi tío Antonio, que en paz descanse. Además de a mis padres, por su gran
apoyo, por educarme, por su cariño y por creer en mí. Ya que gracias a ellos soy la persona que soy.
A mis amigos, por su paciencia ante las muchas horas de estudio durante la carrera. Por que sin ellos la vida
hubiera sido muy aburrida.
A Gemma, por su apoyo, su ayuda y por su motivación. Y por convencerme de hacer aquel viaje que aún
perdura.
X
Resumen
Este sistema pretende crear una red de sensores autoinstalables que permite conocer desde cualquier lugar la
temperatura, humedad y luminosidad de las diferentes habitaciones de una vivienda. Información que influye
directamente sobre el estado de bienestar. Incluyendo seguridad mediante un sistema de alarma con control de
presencia. Para ello se crean dos tipos de nodos, una serie de nodos periféricos que recogen los datos medidos
por los sensores y los envían al nodo central mediante un protocolo de comunicaciones inalámbricas. Y un
único nodo central cuya función, además de recibir los datos obtenidos por los nodos periféricos y mandarlos a
internet, es recolectar los datos de sus propios sensores, así como leer las tarjetas de identificación de los
huéspedes autorizados en la vivienda.
El proyecto engloba la interfaz web donde se puede acceder a los datos proporcionados por la lectura del
hardware. Y para ello será necesario el uso de un servidor, de un bróker, de una base de datos y de servicios
que estarán corriendo constantemente desde el servidor.
XII
Abstract
This system aims to create a network of self-installing sensors that allows to know temperature, humidity and
light of the different rooms of our house from anywhere. Including information that directly affects the well-
being of the guest.
The system has two-node types, some peripheral nodes read data measured by the sensors, temperature,
humidity, luminosity and presense, and sent to the central node via a wireless communication. A single central
node whose function, in addition to receiving the data from the peripheral nodes and send them to the server, is
to collect data from their own sensors to send it to the server and read the ID cards of authorized guests at
home.
In addition, the project also includes the web interface where there can access the data provided by reading
hardware. And this will require also the use a server, a broker, a database and services that will be constantly
running in the server.
XIV
Índice
1 Introducción 1
1.1 Objetivos 1
2 Estado del arte 3
2.1 Domótica 3
2.1.1 Aplicaciones generales de la domótica 3
2.1.2 Arquitectura 4
2.2 Hardware Open-source 5
2.2.1 Arduino 5
2.2.2 Microchip 14
2.2.3 Libelium waspmote 16
2.2.4 Texas Instrument 16
2.3 Comunicaciones inalámbricas 18
2.3.1 Wi-Fi 18
2.3.2 Bluetooth 18
2.3.3 XBee 19
2.3.4 Telefonía Móvil 20
2.3.5 Sigfox 20
2.4 Webservice 20
2.4.1 PHP 20
2.4.2 NodeJS 21
2.5 Protocolos de la capa de aplicación 21
2.6 Interfaz gráfica 21
2.6.1 Aplicación de escritorio 21
2.6.2 Aplicación móvil 21
2.6.3 Aplicación web 21
2.7 Estado del arte 22
2.7.1 OpenDomo 22
2.7.2 Casa Jasmina 22
2.7.3 OpenHab 23
2.7.4 Domoticz 23
2.7.5 PiDome 23
3 Desarrollo del Hardware 26
3.1 Descripción de necesidades Hardware 26
3.1.1 Nodo central 27
3.1.2 Nodo periférico 28
3.2 Nodo periférico 28
3.2.1 Microcontrolador 28
3.2.2 Módulo de comunicación 28
3.2.3 Shield de sensores 30
3.3 Nodo Central 33
3.3.1 Microcontrolador 33
3.3.2 Módulos de comunicación 34
3.3.3 Shield de sensores 35
XVI
3.4 Servidor web, base de datos, Bróker MQTT y Node.js 37
3.4.1 Servidor web y base de datos 37
3.4.2 Bróker MQTT 38
3.4.3 Node.js 39
4 Desarrollo del Firmware 42
4.1 Nodo periférico 43
4.1.1 Sensores 43
4.1.2 Módulo de comunicación 44
4.1.3 Gestión Energética 46
4.2 Nodo Central 50
4.2.1 Sensores 50
4.2.2 Módulos de comunicaciones. 51
5 Desarrollo Software 56
5.1 Descripción de necesidades software 56
5.2 Backend 56
5.2.1 Base de datos en mySQL 56
5.2.2 Servicios web 58
5.2.3 Panel de administración 60
5.3 Middleware 64
5.3.1 Servicio NodeJS 64
5.4 Frontend 65
5.4.1 HTML y CSS 66
5.4.2 JavaScript 68
6 Pruebas y validación 72
6.1 Pruebas de conexión 72
6.1.1 Conexión del nodo central con la red WiFi 72
6.1.2 Conexión de nodo central con el bróker MQTT 73
6.1.3 Conexión de los nodos periféricos con el nodo central 74
6.1.4 Conexión del servicio con la base de datos 74
6.1.5 Conexión del servicio con el bróker MQTT 74
6.1.6 Conexión de la web con la base de datos 75
6.2 Pruebas y calibración de los sensores 75
6.2.1 Sensor DHT11 75
6.2.2 Sensor PIR 75
6.2.3 Sensor LDR 76
6.2.4 Pruebas RC-522 76
6.3 Pruebas del sistema completo 76
7 Conclusiones y desarrollos futuros 80
7.1 Desarrollos futuros 81
7.1.1 GSM 81
7.1.2 Actuación 81
7.1.3 App Movil 81
8 Referencias bibliográficas 82
9 Anexos 86
9.1 Anexo I - Código del nodo central 86
9.2 Anexo II - Código del nodo periférico 100
9.3 Anexo III - Código del servicio NodeJS 108
9.4 Anexo IV - Código Index.hml 118
9.5 Anexo V - Código estilos.css 124
9.6 Anexo VI - Código javascript.js 130
9.7 Anexo VII - Código SuperConsulta.php 132
9.8 Anexo VIII - Código get_sensor.php 134
9.9 Anexo IX - Código get_data.php 136
9.10 Anexo X - Código setup.html 138
9.11 Anexo XI - Código estilosAdmin.css 140
9.12 Anexo XII - Código admin.php 144
9.13 Anexo XIII - Código mRegistro.php 150
9.14 Anexo XIV - Datasheet Atmel ATmega328P 158
9.15 Anexo XV - Datasheet GL55 160
9.16 Anexo XVI - Datasheet DHT11 162
XVIII
ÍNDICE DE FIGURAS
Figura 2-1 – Arquitectura de redes (A) centralizada, (B) mixta y (C) distribuida 4
Figura 2-2 - Logo de la comunidad de arduino 5
Figura 2-3 - Arduino UNO 6
Figura 2-4 - Arduino Leonardo 7
Figura 2-5 - Arduino Mega 2560 8
Figura 2-6 - Arduino PRO mini 8
Figura 2-7 Arduino PRO 8
Figura 2-8 - Arduino Nano 9
Figura 2-9 - Arduino y Genuino Micro 9
Figura 2-10 - Arduino FIO en vista Frontal y trasera 9
Figura 2-11 - Arduino DUE 10
Figura 2-12 Arduino y Genuino ZERO 11
Figura 2-13 - Arduino M0 PRO 11
Figura 2-14 - Arduino M0 12
Figura 2-15 - Genuino 101 12
Figura 2-16- Genuino MKR1000 13
Figura 2-17 - Arduino YUN 13
Figura 2-18 - Arduino TIÄN 14
Figura 2-19 - Arduino Industrial 101 14
Figura 2-20 - Pinguino 18F2550, Primera versión de las placa de desarrollo pinguino 15
Figura 2-21 - ChipKit UNO32 15
Figura 2-22 – ChipKit MAX32 16
Figura 2-23 – IDE Energía 17
Figura 2-24 – Texas Instruments MSP-EXP430G2 LaunchPads 17
Figura 3-1 – Nodo periférico 28
Figura 3-2 – XCTU (A) Descubrimiento un xBee, (B) Configurando un xBee 29
Figura 3-3 – Conexión del sensor DHT11 30
Figura 3-4 – Vista inferior de un sensor PIR 30
Figura 3-5 – Montaje LDR 31
Figura 3-6 – Gráfica Lux en función de la resistencia LDR 31
Figura 3-7 – PCB de la shield del nodo periférico 32
Figura 3-8 – Esquemático de la shield del nodo periférico 32
Figura 3-9 – Nodo central 33
Figura 3-10 – Arduino Wireless SD Shield 34
Figura 3-11 – Arduino WiFi Shield 34
XX
Figura 3-12 - Módulo RC-522 35
Figura 3-14 Esquemático de la shield del nodo central 36
Figura 3-13 – PCB de shield del nodo central 36
Figura 4-1 – Posibles estados de ahorro de energía del Atmel ATmega328p 46
Figura 4-2 – Registro de estado del microcontrolador Atmel ATmega328p 48
Figura 4-3 – Registro de control del temporizador watchdog del microcontrolador Atmel ATmega328p 48
Figura 4-5 – Tiempo de preescalado del watchdog del microcontrolador Atmel ATmega328p 49
Figura 5-1 – Panel de login de la interfaz de administración. 60
Figura 5-3 – Panel de administración 61
Figura 5-2 – Panel de login con usuario o contraseña erróneo 61
Figura 5-5 – Solo se actualiza un elemento 62
Figura 5-4 – Cambio de dos elementos simultáneos en la interfaz de administración 62
Figura 5-6 – No se actualiza ningún campo 63
Figura 5-7 – Panel de login tras caducar la sesión 63
Figura 5-8 – Sección introducción de la interfaz de usuario 66
Figura 5-9 – Sección sensores de la interfaz de usuario 66
Figura 5-10- Popup con las gráficas de los nodos. 67
Figura 5-11 – Sección Acerca de de la interfaz de usuario 68
Figura 5-12 – Formulario con los nodos y sensores disponibles 70
Figura 5-13 – Calendario para seleccionar el rango de fechas a mostrar. 71
Figura 6-1 – Conexión a la red wifi y al bróker MQTT 72
Figura 6-2 – Reconexión del nodo central al modem wifi 73
Figura 6-3 – Reconexión del nodo central al bróker MQTT 73
Figura 6-4 – (A) Recepción de datos en el nodo central, (B) Envío de datos desde el nodo periférico 74
Figura 6-5 – Aviso de nuevo dispositivo 76
Figura 6-6 – Histórico del nodo central 77
Figura 6-7 – Aviso de entrada, salida y armado de la alarma 77
Figura 6-8 – Vista final y verificando el correcto funcionamiento del sistema 78
Notación
ºC
Grado centígrado
A Amperios
AC Corriente alterna
AC/DC Conversor corriente alterna a corriente continua
ADC Conversor analógico a digital
API Application Programing Interface o Interfaz de programación de aplicaciones
ARC Arquitectura RISC de microprocesadores
ARM Arquitectura RISC de microprocesadores
AT Comando de comunicación entre hombre y módem.
AVR Arquitectura RISC de microprocesadores
B Offset de la señal logarítmica
BLE Bluetooth Low Energy
CC Conector común
CPU Central Processor Unit o unidad central de procesamiento
CSS Cascading Style Sheets u hojas de estilo en cascada
DAC Conversor digital a analógico
DC Corriente continua
DC/DC Conversor de corriente continua a corriente continua
DDR2 Memoria RAM de doble tasa de datos versión 2
DHCP Dynamic Host Configuration Protocol
DiY Do it Yourself o Hazlo tu mismo
DSP Digital Signal Processor o procesador digital de señales
DMA Acceso directo a memoria
EDGB Debugeador integrado
EEPROM Memoria de solo lectura borrarle eléctricamente
eMMC Lector integrado de tarjetas multimedias
FTDI Driver de conexión TTL a USB
HTML HyperText Markup Language o lenguaje de marcas de hipertexto
HTTP HyperText Transfer Protocol o protocolo de transferencia de hipertexto
GND Tierra
GPIO Entradas salidas de propósito general
GPS Sistema de posicionamiento global
I2C Protocolo de transferencia de datos, circuito inter integrado
I/O Entrada/salida
ID Identificador
IDE Entorno de programación
IEEE Instituto de ingenieros electrónicos y eléctricos
IoT Internet of Things o Internet de las cosas
IP Protocolo de Internet
XXII
ISP Programación en el sistema
JS JavaScript
LDO Regulador de corriente continua
LDR Resistencia sensible a la luz
LGA Formato de componentes para soldadura superficial
M Pendiente de la señal logarítmica
MAC Dirección física o control del acceso al medio
MISO Entrada en maestro y salida en esclavo
MOSI Salida en maestro y entrada en esclavo
MQTT Sistema de mensajes telemétricos en cola
NC (pin out) No conectado
NC (Relé) Normalmente cerrado
NO Normalmente abierto
PCB Placa de circuito impreso
PHP Pre Procesador de Hipertexto
PIR Sensor de presencia por infrarrojos
PWM Modulación de ancho de pulso
RAM Memoria de acceso aleatorio
RFID Identificador por Radio Frecuencia
RISC Arquitectura de microprocesador basados en pocas instrucciones
ROM Memoria de solo lectura
RST Reset
RTC Reloj de tiempo real
SCK Señal de reloj
SRAM Memoria de acceso aleatorio estático
SSH Secure Shell, acceso remoto mediante consola comandos
SSID Identificador del servicio de red inalámbrica
SWD Debugeador del puerto serie
TCP Protocolo de control de transmisión
TWI Interfaz de comunicación por dos cables "I2C"
UART Transmisor/Receptor universal asínconcrono
USART UART
USB Bus serie universal
1 INTRODUCCIÓN
a tecnología avanza a un ritmo vertiginoso. Durante los últimos años se ha experimentado una
L importante evolución tecnológica que ha permitido no solo mejorar la calidad de vida, sino también la
percepción de lo que nos rodea. Dicho avance ha ocasionado que a través de la tecnología de internet,
las tareas cotidianas sean más fáciles, rápidas y asequibles, sin la necesidad de salir de la vivienda.
Queda en el recuerdo las películas de ciencia ficción donde los personajes son capaces de interactuar con su
hogar. Apagar o encender las luces con el sonido de una palmada o interactuar con una casa inteligente ya no
es ciencia ficción, y esto se debe a la domótica. Actualmente en la era del internet de las cosas (IoT) es
impensable que estas tareas no sean posibles. Existen relojes que dicen las pulsaciones, los pasos registrados o
hablar con amigos y familiares. Teléfonos móviles que no solo permiten la comunicación entre personas, sino
también trabajar a distancia desde el propio terminal, con cámaras de gran calidad y con juegos de gráficos de
alta resolución. Gracias a estos avances en telefonía inteligente y al llamado internet de las cosas se puede
conectar todo tipo de objetos a internet para controlarlos desde un Smartphone o Smartwatch.
En contraposición todos estos artículos conectados suponen un gran desembolso económico, en algunos
aspectos con precios prohibitivos. Por la fuerza adquirida tanto a conceptos de Software Libre o Hardware
Libre los entusiastas del DiY (hazlo tu mismo) tienden a fabricar sus propios sistemas domóticos. Usando en
su mayoría arduinos o raspberry pi, debido a su simplicidad a la hora de programación y de uso.
Arduino está íntimamente ligado a conceptos como IoT o DiY, esto se debe a la existencia de una gran
comunidad detrás de esta plataforma. Se pueden encontrar módulos de comunicación, de sensórica y de
control entre otros, además de sus correspondientes librerías que permiten programar todo el sistema, sin la
necesidad de conocer que es un registro o su función.
Una estimación del coste de un sistema domótico basado en hardware libre es de 50€ por nodo, dependiendo
de las dimensiones y del alcance del mismo.
1.1 Objetivos
Medir las principales variables relacionadas con la eficiencia energética, como son la humedad, la temperatura
y la luminosidad, mediante una red de sensores. También debe funcionar como una alarma de seguridad que
avise al administrador cuando se detecte una persona no autorizada. Por esta razón los nodos deben incorporar
un detector de presencia y al menos uno de los nodos debe tener un sistema de identificación. La red debe ser
escalable, se debe poder agregar tantos nodos como sean necesarios.
1
2 Introducción
Los datos obtenidos por estos sensores deben ser mostrados mediante una interfaz sencilla tanto en
ordenadores como en dispositivos móviles. Debe permitir la administración de los diferentes elementos de la
red mediante una interfaz específica para esta función, que debe estar protegida con usuario y contraseña ya
que solo el administrador de la red debe tener acceso a esta.
Para el desarrollo del sistema completo se ha de desarrollar todas las partes del mismo. Selección y
programación del hardware, configuración del servidor y programación de la interfaz web, tanto la de usuario
como la de administración.
2 ESTADO DEL ARTE
l proyecto está diseñado con placas de desarrollo open-source interconectadas entre ellas mediante una
E comunicación inalámbrica. La información obtenida por los sensores se almacena en una base de datos
mediante el uso de un middleware y se puede gestionar mediante una interfaz web.
2.1 Domótica
Conjunto de sistemas y subsistemas que permiten automatizar una vivienda generando valor añadido en
cuanto a comunicación, bienestar, eficiencia energética y seguridad. Surge en Estados Unidos en la época de
los años 70 con el objetivo de reducir el consumo energético [1], el cual aparece debido a la crisis energética
mundial que se produjo durante esta década. Es exactamente en 1978 cuando aparece el sistema X-10,
considerado el primer sistema domótico. En sus inicios solo fue usado en lugares donde el consumo energético
era elevado como hoteles y hospitales hasta llegar a los hogares, en la actualidad es común encontrarlo en
casas y oficinas de todo el mundo.
El origen de la automatización del hogar viene derivado de la necesidad del ahorro energético y sigue siendo el
principal objetivo de la domótica. Se produce al gestionar de forma eficiente la temperatura, luminosidad y el
sistema eléctrico.
2.1.1.1.1 Temperatura
Los sistemas de climatización consiguen un ahorro energético evitando el uso excesivo de sistemas de frío o
calor estableciendo un rango de temperatura óptima.
2.1.1.1.2 Luminosidad
Teniendo control sobre las persianas y el sistema de iluminación se puede establecer una luminosidad
adecuada minimizando el consumo eléctrico.
2.1.1.1.3 Gestión eléctrica
Permite desconectar los equipos prescindibles cuando no estén en uso o no sea necesario su utilización,
además usa de forma inteligente ciertos equipos en los horarios de tarifa reducida. Por otro lado, se puede
3
4 Estado del arte
controlar la gestión de la energía renovable. Estas últimas gestiones afectan al ahorro económico del uso
energético, más que al ahorro energético propiamente dicho.
Los factores mencionados en el punto 2.1.1.1 están íntimamente ligados a la mejora de la calidad de vida. La
integración de servicios de valor añadido mediante IoT permite la utilización de electrodomésticos de forma
remota. Para que sea posible debe existir una interfaz de usuario fácil e intuitiva.
2.1.1.3 Seguridad
Los diferentes sensores utilizados en domótica permiten conocer el estado de la vivienda a tiempo real. Esta
información hace que se pueda detectar cualquier anomalía, tales como temperatura extrema que alertaría de
fuego, o una presencia no esperada que alertaría de robo.
A nivel preventivo se puede hacer uso de simulación de presencia para disuadir al ladrón, controlando la
apertura de las persianas, el sistema de iluminación, televisor, etc.
2.1.1.4 Comunicaciones
Es el medio o canal que posibilita conectarse al sistema domótico, ya sea por bluetooth, WiFi o cualquier otro
protocolo de comunicación. Permite no solo controlar el hogar sino avisos de alarma, tele mantenimiento, tele
asistencia, generar informes de consumo a tiempo real, etc.
2.1.2 Arquitectura
Bajo el pretexto de control sobre el
sistema existen diferentes arquitecturas
en función de la topología entre los
sensores, actuadores y controladores.
2.1.2.1 Centralizada
2.1.2.2 Distribuida
Toda la inteligencia está distribuida entre los nodos del sistema, ya sean actuadores o sensores. Están
conectados con un sistema cableado en bus o sistemas inalámbricos. Tiene la ventaja de ser un sistema robusto
al funcionar en bus. Su implementación es más difícil ya que necesita de una programación más compleja en
cada uno de los nodos puesto que cada uno tiene sus propios sensores y actuadores, por lo tanto podrían
funcionar de manera autónoma al resto.
Cada nodo del sistema tiene su propia inteligencia, y pueden gestionar las tareas de forma independiente al
resto de nodos. Informará al resto de dispositivos tanto de los datos adquiridos como de las actuaciones
pertinentes. Tiene la ventaja de que al ser descentralizado se trata de un sistema mucho más robusto, y el
Red de sensores para monitorización inteligente de vivienda 5
2.2.1 Arduino
Es una placa de desarrollo de hardware open-source basada en un microcontrolador de uso general. Permite
desarrollar un prototipo rápido sin tener que diseñar una placa propia. En función del funcionamiento y
requerimientos mínimos que han utilizado en este, se selecciona un nuevo microcontrolador de uso específico,
reduciendo así el coste de fabricación y desarrollo.
Está diseñado para que pueda ser usado por personas que no tengan conocimientos de electrónica, o de
programación si utilizan scratch. Aunque el conocimiento de estas materias aumenta notablemente el potencial
de estas placas. La simplicidad del uso de programing permite utilizar un microcontrolador sin tener
conocimiento de su funcionamiento interno. Existe una extensa comunidad que permite tener librerías pre
programadas de casi todos los componentes, así como shields para cualquier uso. Siendo una shield una placa
con una electrónica específica que se acopla a arduino.
Arduino [4] nació por la necesidad de crear placas de desarrollo por un bajo precio. En 2005 las placas de
desarrollo tenían un precio medio de unos 100€ y no ofrecían un soporte adecuado. Massimo Banzi era
estudiante de computación y electrónica e inició un proyecto DiY para conseguir que su instituto no entrara en
quiebra. Pretendía que el instituto pudiese vender sus placas desde un euro la unidad. Por esta razón el primer
prototipo de arduino fue fabricado por este instituto, IVRAE. Era una placa con todo lo necesario para que se
pudiera programar un microcontrolador (cristal, resistencias, condensadores y un puerto serie para
programarla).
Unos años más tarde Hernando Barragán, un estudiante de la Universidad de Colombia, al enterarse de este
proyecto contribuyó con el desarrollo de un entorno de programación para esta placa junto con David Mellis,
6 Estado del arte
también del instituto IVRAE, quien mejorará la interfaz gráfica. Este entorno recibe el nombre de Wiring.
Poco después aparece el estudiante español David Cuartielles quien diseña junto a Banzi una nueva placa que
mejora la interfaz hardware. Con la integración de Tom Igoe se agregan los puertos USB para programar
arduino.
Gianluca Martino fue el publicitario encargado de promocionar arduino, que empezó a desarrollarse de forma
masiva gracias a la ayuda de Natan Sadle para distribuirse por Italia, y tras ver su aceptación empiezan a
exportar las placas a nivel europeo para posteriormente empezar a distribuirlos a nivel mundial.
Como G. Martino fue el encargado de la distribución de estas placas, registró el nombre “arduino” a su
persona en lugar de hacerlo al equipo fundador, debido a la fuerte amistad contraída con M. Banzi, este no le
dio importancia. Aunque a la hora de registrarlo en EEUU fue M. Banzi el que formaliza el registro en nombre
de todo el equipo.
Durante finales de 2014 y principio de 2015 el equipo de arduino se ve divido y aparecen dos líneas de
desarrollo, una liderada por Massimo Banzi y otra liderada por Gianluca Martino, quien se apodera de los
derechos del nombre arduino en todo el mundo a excepción de los EEUU [5], que pertenece al equipo de
Banzi. Para poder vender placas por el resto del mundo Banzi se ve obligado a utilizar el nombre Genuino,
aunque sigue conservando el nombre arduino en sus placas de EEUU.
Pese a que algunas placas a nivel europeo reciben el nombre de Genuino, al ser también Arduino en los
EEUU, este documento se referirá a todas las placas con el nombre de arduino.
microcontrolador auxiliar o con otros módulos de comunicación que utilicen este sistema como xBee o los
módulos SIM entre otros muchos.
Dispone de una memoria de programa de 32Kbytes que puede ser programado mediante instrucciones RISC,
aunque es más cómodo usar el propio IDE de arduino. Dispone también de una memoria EEPROM de 1Kbyte
que permite almacenar datos incluso cuando el arduino no está alimentado. Y de una memoria interna para
variables del tipo SRAM de 2 Kbytes.
Dispone de la posibilidad de utilización de watchdog y de modo hibernación, aunque ambas configuraciones
son necesariamente programadas mediante el uso de las instrucciones RISC o de su código C alternativo
facilitado por el fabricante. Ya que será necesario la programación con uso de registros.
Por último comentar que dispone de dos pines de interrupción externa configurable como nivel alto, nivel bajo
o cambio de nivel de la señal de entrada. Estos pines están asignados a los pines digitales 2 y 3.
Se trata de una versión con mejores características que la placa de arduino UNO. Dispone de un
microcontrolador auxiliar, que coincide con el que utiliza el arduino UNO, que se utiliza exclusivamente para
la comunicación USB del arduino con el ordenador. Por lo que tampoco será necesario ocupar el bootloader en
la memoria de programa ni será posible sacar provecho del mismo. Al ser un microcontrolador con cien pines
[13], cincuenta y cuatro pines se utilizan como entrada/salida digital, de los cuales quince pueden ser utilizados
como PWM. Dispone de dieciséis entradas analógicas, cuatro puertos serie UART, un puerto SPI y un puerto
I2C.
Al ser un microcontrolador con mayores características tiene un mayor número de contadores, en este caso
dispone de dos contadores de 8 bits y cuatro de 16 bits. Así como un de un watchdog. Dispone de seis pines de
interrupciones para poder despertar el microcontrolador cuando este entre en modo Sleep, o para cualquier otra
función con prioridad.
Al igual que las dos placas descritas anteriormente dispone de alimentación mediante USB y mediante un Jack
para adaptadores AC/DC o DC/DC cuya salida estén comprendidas entre 7 y 12V.
Se trata de una versión para breadboard del arduino Leonardo [17], la única diferencia entre este y el arduino
Leonardo es el pin out. Al igual que ocurre con el arduino Nano, esta placa no dispone de un socket para Jack
de alimentación, por lo que para alimentar la placa entre 7 y 12V se debe conectar entre los pines Vin y GND.
El puerto nativo permite su programación, aunque como ocurre con el arduino Due, su uso no está
recomendado para la programación, sino para ser usado como USB Host.
Dispone de veinte pines digitales de entrada/salida. Seis pueden utilizarse como entradas analógicas de 12 bits,
dieciocho pueden utilizarse como PWM. Uno como conversor digital a analógico de 10 bits y todos los pines
que se describen como digitales en la PCB pueden ser empleados para interrupciones externas, a excepción del
pin 4.
Tiene cinco contadores de hasta 16 bits, de los cuales uno se puede configurar como 8 bits, otro de 32 bits con
dos comparadores [20] y tres contadores de 24 bits para control. Dispone de un contador exclusivo para el
watchdog.
Tiene una memoria Flash de 256 Kbytes y 32 Kbytes de SRAM. No dispone de EEPROM, no obstante, han
ideado una forma para poder escribir los datos que se quieran modificar en la memoria de programa como si
fuese EEPROM. Estos valores se perderán al subir un nuevo sketch ya que se borra toda la memoria de
programa en el proceso.
Otros beneficios de usar un núcleo ARM son el uso de DMA de doce canales, que dedica 32 bits al RTC, tiene
un generador de código de errores CRC de 32 bits y un control de periféricos táctiles (PTC). Todas estas
características deben de programarse con el uso de registros ya que no están disponibles en wiring.
Puede ser alimentado entre 7 y 12 V mediante el Jack o bien mediante el puerto USB. El microcontrolador
funciona a 3V3, meter una tensión mayor en sus entradas podría dañar el arduino.
2.2.1.2.4 Arduino M0
Se trata de una versión reducida y de bajo coste del arduino M0 pro,
Se elimina el microcontrolador EDBG [23], por lo que solo podrá ser
programado mediante su USB nativo. Esto produce un ahorro de casi
un 50% del precio de la M0 pro, pero pierde la capacidad de
depuración y de programación cuando se produzca un fallo en el
microcontrolador, solo podrá ser reprogramada mediante el puerto
JTAG o SWD.
Si se busca crear un sistema simple o bien se requiere que tenga un
consumo especialmente bajo, el uso de esta placa es idóneo. Aunque la
Figura 2-14 - Arduino M0 ausencia de depurador hace que no sea del todo interesante para la
creación de prototipos rápidos.
Dispone de un socket para batería, lo cual permite cargar una batería hasta 4.2V con un máximo de 1400 mAh,
y se recomienda el uso de una batería de al menos 700 mAh.
Esta placa no se puede alimentar con más de 6V, ya que no dispone de un LDO para transformar mayores
tensiones.
Figura 2-18 - Arduino TIÄN En cuanto a la programación del M0, en lugar de utilizar directamente
el USB del microcontrolador, se utiliza un chip de silicon labs, el
CP2105, que permite la conexión con el DSP y la programación mediante el IDE de arduino.
2.2.2 Microchip
La compañía microchip ha intentado formar parte del mundo arduino. A nivel académico los
microcontroladores PICs se han convertido en un estándar dado que el lenguaje RISC permite que sea
fácilmente programable a bajo nivel. Su principal ventaja es que los estudiantes no necesitan realizar
desembolso económico para utilizar su software y que dispone de un sistema de samples para adquirir varios
microcontroladores sin costo. En enero de 2016 Microchip compra Atmel [29], lo que permite que los
microcontroladores Atmel se puedan adquirir en un programa de samples de una forma mucho más
controlada.
La empresa intenta hacer que los PICs estén presentes en las placas de desarrollo con una programación
basada en wiring. Fue la comunidad que hay detrás de estos microcontroladores quienen empezaron esta
visión, diseñando unas placas de desarrollo bautizadas con el nombre “pinguino” [30]. No se dirigen a nivel
comercial y se pueden fabricar en casa por apenas un euro.
RTC, unas resistencias para proteger los pines entrada/salida por error humano, y la conexión USB para poder
subir los sketch por USB.
Era necesario programar el micro mediante un programador para poder quemar el bootloader al pinguino, una
vez hecho esto, se puede programar utilizando un IDE similar al de arduino. Su IDE era más limitado ya que la
comunidad que estaba detrás de pingüino era mucho más pequeña.
Está compuesto por dieciocho pines de entrada/salida digitales, que están definidos ocho como salidas
digitales, cinco como entradas digitales y cinco como entradas analógicas. Se puede cambiar las funciones de
estos pines durante la ejecución y tan solo se puede cambiar en el setup. Solo dos de los pines digitales se
pueden utilizar como salidas PWM.
Dispone de dos modos de ahorro energético, el modo idle y el modo Sleep y también de un timer de 8 Bits y
tres de 16 bits.
Tiene una memoria de programa de 32 Kbytes, 2 Kbyte de SRAM y 256 bytes de EEPROM.
16 bits, aunque permite unificar dos de ellos para formar uno de 32bits y también dispone de watchdog.
LaunchPads como si fuesen un arduino, adaptando las librerías desarrolladas para arduino.
Se describen las diferentes familias de LaunchPads. En cada una de ellas existen placas según las necesidades
de los proyectos que se vayan a realizar . Texas Instruments proporciona de la forma más presisa posible sus
placas de desarrollo [35].
Son las placas de desarrollo más básicas de Texas instruments y su precio está entre los 10 y 18 dólares. Sus
características son similares a la de un arduino y cuanto más aumentemos el precio más prestaciones tiene,
como pantalla LCD o RTC. Están pensadas para uso de propósito general y aplicaciones de bajo consumo.
Usan microcontrtoladores de 8 bits.
Estas placas están diseñadas para aplicaciones de control de motores a tiempo real. Funcionan con
microcontroladores de 32 bits y tienen al menos 8 PWM y cuatro salidas PWM de alta resolución (HRPWM).
En función de la placa se pueden manejar diferentes tipos de motores, desde motores DC de baja tensión hasta
18 Estado del arte
Placas de desarrollo pensadas para el uso de comunicación. Contienen módulos tanto para comunicaciones
cableadas (Ethernet, USB o CAN) como inalámbricas (WiFi o Bluetooth) y su precio varía dependiendo del
sistema de comunicación integrado en la placa. En función de las necesidades del sistema de comunicación las
placas intengran un microcontrolador de 8 o 32 bits.
Son placas con componente de alta seguridad para aplicaciones que requieren unas normas de seguridad
exigentes. En campos como el transporte, medicina o industrial. Funcionan con controladores ARM Cortex,
por lo que sus especificaciones son de alta velocidad y está destinadas a un uso muy concreto.
2.3.1 Wi-Fi
Es un protocolo de comunicación Ethernet inalámbrica (IEEE 802.11) [36], que permite interconectar equipos
de manera remota. Este estándar nace de la necesidad de crear una red inalámbrica que sea totalmente
universal. Está diseñado para distancias reducidas con un uso doméstico, evitando posibles interferencias.
Trabaja a 2.4 GHz, al igual que otros protocolos como bluetooth o xBee. No hace interferencia debido al
diseño de los protocolos, por lo tamto no son compatibles entre sí.
El valor añadido de wifi con respecto a otras redes, es el uso de diferentes posibles tipologías, así como la
seguridad contando con un nombre o SSID y un cifrado de seguridad. Existen otros métodos que permiten
reforzar la seguridad realizando filtrados por MACs por ejemplo.
2.3.2 Bluetooth
Es un protocolo para redes inalámbricas que posibilita la transmisión de datos entre dos dispositivos. Buscando
una comunicación directa entre dispositivos y la posibilidad de crear redes de datos inalámbricos. Por ello se
busca que tenga un alcance corto basado en transceptores de bajo costo. Existen diferentes versiones de
bluetooth íntimamente ligados con la capacidad del canal. Sigue el estándar del IEEE 802.15.1 [37].
Así se denominan a las versiones 1, 2 [38] y 3 [39]. Tienen un ancho de banda de 1 Mbps, 3 Mbps y 24Mbps
respectivamente. Las versiones 1 y 2 de bluetooth son compatibles en todas sus versiones, no obstante con la
aparición de Bluetooth v3.0 no se cumple en todos sus dispositivos. Son versiones unicast y no necesita un
pareado completo para el intercambio de datos.
Red de sensores para monitorización inteligente de vivienda 19
Conocido como bluetooth de bajo consumo y alta velocidad (32 Mbps) [40]. Está dirigido a aplicaciones de
baja potencia. Supone un avance permitiendo la conexión punto a multipunto, así como la posibilidad del
aumento de la distancia. Aunque no es directamente compatible con sus versiones anteriores existe la
posibilidad de que lo sean, quedando esta desición a disposición del fabricante tal y como ocurre con la versión
3.0.
2.3.3 XBee
Es un protocolo de comunicación muy similar a bluetooth, pero orientado a redes ac hoc, lo cual permite
obtener una red completa y totalmente conectada sin necesidad de cablear toda la vivienda [41]. La principal
diferencia entre este protocolo y bluetooth es la posibilidad de comunicarse con otros dispositivos, ya sea
punto a multipunto o punto a punto. Con este tipo de módem se tiene la posibilidad de crear una red, teniendo
tres tipos de configuraciones “Coordinador”, “Router” y “Nodo final”. Las cuales son seleccionadas en
función de las necesidades.
Diseñado para tener un mayor alcance de red ad hoc. Con configuraciones en router se puede ampliar el
alcance, no obstante, la velocidad de transmisión se ve reducida en comparación con bluetooth [42]. Existen
dos tipos de xBee, el basado en la norma 802.15.4 y el creado por la zigbee Alliance.
2.3.3.1 Configuraciones
Existen tres tipos de configuraciones, que permitirán crear una red específica en función de las necesidades del
usuario.
2.3.3.2 Tipos
2.3.3.2.1 802.11.4
La Serie 1 de xBee [43] no requiere de configuración, lo cual permite un uso más fácil. Su funcionamiento es
muy similar a los de la serie 2 (ZigBee) evitándo la configuración necesaria para establecer una comunicación
punto a punto. La carencia de esta configuración solo permite que sea coordinator (coordinador) o end device
(dispositivo final). Lo que dificulta la conexión al establecer una red punto a multipunto.
2.3.3.2.2 ZigBee
Zigbee [44] surge como una alianza de varias empresas para poder crear redes MESH basada en tecnología
xBee para mejorar la eficiencia energética y abaratar precios. Son más difíciles de utilizar porque es necesaria
una compleja configuración previa. Se obtendrá una red MESH fuerte que permitirá su uso no solo en redes
domóticas dentro del hogar, sino en redes externas para Smartcities.
2.3.5 Sigfox
Aparece como la primera solución de conectividad mundial especializada en IoT. La principal ventaja de estos
sistemas frente a la telefonía móvil es el ahorro energético [46]. Los sistemas GPRS actuales cumplen
notablemente con los requisistos de velocidad para el IoT, no obtante, cuando se intentan reproducir estos
sistemas el consumo es excesivamente elevado, como por ejemplo a wearables (ropa inteligente). De media un
módulo GSM tiene picos de consumo de hasta 2 A, frente a los 61 mA de Sigfox [47].
Se sirve de una infraestructura diferente a la utilizada en GSM, lo que se desvincula del “apagón GSM” que se
avecina [48], las operadoras estiman este apagón entre 2017 y 2025.
2.4 Webservice
El uso de Webservice o servicios web permite gestionar datos o la conexión del hardware con la base de datos.
En función de la sensibilidad a la seguridad de los datos, se realiza una llamada GET o POST. IoT está ligado
al uso de bases de datos, gestión de contenido y a la existencia de una interfaz, lo que produce que se lleven a
cabo estas gestiones mediante el uso de webservice.
Dentro su desarrollo existen diversas posibilidades, pero este proyecto se centrará en las que se basan en el uso
de tecnología web.
2.4.1 PHP
Permite el envío de peticiones GET o POST de forma simple y rápida, pero debido a la falta de encriptación es
Red de sensores para monitorización inteligente de vivienda 21
fácil relicar sus mensajes. Su principal ventaja es la facilidad de programación y que cualquier sistema de
hosting que acepte PHP permite realizar el servicio.
2.4.2 NodeJS
NodeJS es un entorno de programación basado en el motor V8 de JavaScript[49], permite realizar desde
cualquier cometido sencillo hasta la creación de un hosting completo. Su uso es exclusivo para un servidor
propio o virtual (VPS) ya que necesita la instalación del entorno en el mismo. Su principal ventaja es la
posibilidad de construir un sistema seguro a partir de la creación de un rest, el cual permite generar un token de
seguridad.
El lenguaje HTML se utiliza para maquetar una página web. CSS son hojas de estilo donde se pueden crear
diseños que pueden ser escalables a cualquier resolución de pantalla. En conjunto HTML y CSS sirve para
diseñar una interfaz web, desde HTML se maqueta una estructura básica, se genera el contenido, los enlaces
etc. Mientras que desde las hojas de estilos CSS, se les da color y forma a la maquetación.
2.6.3.2 PHP
Al igual que ocurre con los webservices, desde PHP se podrá acceder a la base de datos para ofrecer la
información que generan los sensores. Permite generar nuevos contenidos y estructuras compatible con el
código HTML y CSS.
2.6.3.3 JAVASCRIPT
Para integrar PHP dentro de HTML es necesario el uso de JavaScript, el cual mediante llamadas AJAX puede
acceder a PHP y obtener los datos requeridos y mostralos en formato en HTML o para generar gráficas.
Disponiendo de un servidor NodeJS se puede eliminar el paso intermedio de PHP para acceder a la base de
datos al ser un lenguaje del lado del servidor, ahorrando tiempo en el acceso y aumentando la seguridad.
2.7.1 OpenDomo
Nace en 2006 con el objetivo de crear una comunidad para el control de instalaciones, basadas en sistemas
open-source. Que forma parte del desarrollo de diferentes proyectos hardware/software en este ámbito. Bajo
estos proyectos se pueden encontrar una serie de productos y software tanto en ámbito profesional como no
comercial. Su principal gama de productos son medidores de corriente (monofásica y trifásica), así como
dispositivo de controles autómatas para iluminación, riego y domótica en general.
La ventaja es que es un sistema totalmente desarrollado y en continuo avance debido a su comunidad. Se trata
de un sistema modular, por lo que se necesitará varios de estos dispositivos para generar un sistema final,
implementando pasarelas y autómatas en cada uno de los nodos, lo cual en ciertas circunstancias es excesivo
cuando se tienen pocos dispositivos que controlar y pocos sensores.
2.7.3 OpenHab
Se trata de una interfaz para gestionar los dispositivos conectados a una casa automatizada, no se dedica ni se
relaciona con el hardware. Es una aplicación pensada para instalarse en un ordenador, Smartphone, o raspberry
PI/ Beaglebone, aunque siempre como gestor de contenidos. Es una aplicacion open-source compatible con
otros sistemas como Xively. Es un sistema visual o “front-end”, por lo que no se tiene que adaptar todo el
software y el sistema de comunicación de acuerdo a sus estándares para su correcto funcionamiento, sino que
solo se tendría que adaptar el hardware utilizado.
2.7.4 Domoticz
Es un sistema similar a OpenHab, un sistema open-source multidispositivo que está preparado para todas las
plataformas donde gestionar y almacenar los datos generados con el hardware. Está dirigido a personas con un
alto conocimiento en programación ya que está orientado a que sea el usuario el que compile el sistema en
función de las necesidades del mismo. Tiene una versión instalable que se puede configurar mediante un
sistema de programación en bloque del estilo de scratch.
2.7.5 PiDome
Sistema open-source que busca la domotización completa del hogar a partir del uso de Raspberry Pi en todo el
sistema. Dispone de servidores donde almacenar los datos proporcionados por los clientes y ofrecerlos
mediante un entorno gráfico al acceder al servidor HTTP que contiene la misma. Aunque existe una versión
estable, se encuentra en desarrollo para completar el sistema con nuevos sistemas de comunicaciónes o nuevas
shields de sensores. El principal problema de este sistema es que está basado únicamente en rapsberry PI, por
lo que será difícil personalizar el Hardware para obtener un dispositivo pequeño y discreto.
25
26 Desarrollo del Hardware
l objetivo del proyecto es crear una red de sensores para domótica, completándose con un sistema de
E alarma. Este pretende ser un sistema completo, desde la creación de los nodos físicos hasta el
desarrollo de la interfaz con el objeto de tener un sistema personalizado. Los componentes que se van
a utilizar se basan en elementos y placas de origen open-sourse. Se pretende dar uso a esta red en una casa de
cuatro habitaciones, donde se tendrá un único nodo central y tres nodos periféricos. Por lo que se creará un
sistema centralizado, aunque cada nodo podrá tener inteligencia propia de actuación si se implementase. Se
podrá conectar tantos nodos periféricos como el módulo de comunicación que utilizamos lo permita.
Los nodos periféricos estarán exclusivamente destinados a tomar datos de medida y comunicarlos al nodo
central. Mientras que el nodo central se encargará de recabar toda esta información, generar la información de
los sensores y la comunicación con internet. Debido a que el sistema incluye alarma, desde el nodo central se
podrán identificar los habitantes mediante tarjetas RFID Mifare.
Se pretende utilizar una “Raspberry Pi 3 Model B” como servidor, para simular el uso de un servidor
comercial real o virtual.
Como valor añadido, sin ser un elemento indispensable del sistema, puede avisar por e-mail de las entradas y
salidas de las personas con acceso, así como informar si la alarma está armada, desarmada o sonando.
Teniendo en cuenta las necesidades descritas, la mejor opción es realizar una red centralizada compuesta por
dos tipos de nodos, el nodo periférico y el nodo central. La finalidad del nodo periférico sería la lectura de
datos del sensor y el envío de esta información al nodo central. Tendría una función adicional de enviar todos
los datos recibidos al webservice así como los producidos por el propio nodo central y activar la alarma si
fuera necesario con un control de accesos.
Se utilizará un sensor PIR genérico. Este sensor se trata de un sensor digital con microcontrolador integrado, se
configura la sensibilidad del sensor mediante un potenciómetro. Está basado en la detección de movimiento.
Por lo general, siempre que se produzca un movimiento significa que algo o alguien realiza ese movimiento. Si
existe movimiento de algún objeto significa que alguien realiza ese movimiento, aunque un movimiento de la
tierra o del edificio (por ejemplo un fuerte choque con alguna de sus paredes) puede genera un movimiento,
por ello, cuando se detecte se realiza una segunda lectura transcurrido un tiempo, si este sigue dando positivo
mandará una trama al nodo central.
Se trata de un módelo de sensórica tanto para temperatura como para humedad. Tiene la ventaja de ser fácil de
utilizar debido a la comunidad de arduino y un precio muy bajo. En cambio tiene mala resolución tanto en
temperatura como en humedad. Pero como se trata de un proyecto de lectura de datos sin actuación este error
queda dentro del alcance del proyecto.
En este caso se utiliza una resistencia sensible a la luz (LDR), de esta forma, en función de la luz incidente se
podrá estimar la iluminación de la habitación. Apenas necesita electrónica adicional para su uso, pero necesita
unos cálculos así como una calibración para hallar la lectura en unidades Lux.
28 Desarrollo del Hardware
3.1.1.4 RFID
Se dispondrá de un módulo cuya única función es detectar las tarjetas RFID y mandar la información al
webservice, donde estará la lógica de activación de la alarma.
3.1.1.5 Relé
Se trata de un actuador necesario para poder encender la sirena. Un relé es un actuador que sirve de interruptor
controlado mediante una señal eléctrica, dispone de dos conectores como entrada de señal y de tres conectores
para su salida (CC o conector común, NO o normalmente abierto y NC o normalmente cerrado).
En reposo el CC se encontrará conectado a NC, al introducir una señal de 5V CC pasará a conectarse a NO.
cable FTDI para conectarlo con el ordenador. Por lo tanto se debe configurar el módulo xBee mediante el
arduino UNO con la Wireless SD Shield. Para que el arduino no interfiera con el puerto serie, es necesario
instalar un firmware vacío. Es necesario conectar el pin DTR con GND para configurar que el módulo pueda
hibernar en modo router.
Una vez abierto XCTU el programa debe reconocer el módulo de comunicación, para ello se establece el
baudrate configurado en el módulo, generalmente 9600 bauds, sin embargo, al haber sido utilizado este
módulo previamente se utilizará 115200 bauds.
Se seleccionará el puerto serie tal como se puede observar en la figura 3-2 se seleciona el puerto COM 4. Y se
pulsa sobre el botón “test/query modem”. Habrá que esperar hasta que aparezca un mensaje similar al
mostrado en la figura 3-2 (A). Una vez XCTU haya reconocido el módem, en la pestaña “modem
configuration” se definirá las características del módem. En este caso no hace falta modificar ninguna
característica ya que como se observa en la figura 3-2 (B), este está configurado. Para configurarlo desde cero
sería necesario buscar en function set “ZIGBEE ROUTER API” y pulsar sobre el botón Restore.
A partir de este momento se puede configurar el módem xBee. En primer lugar el “PAN ID” funciona mejor
cuando es definido por lo que se utilizará el “PAN ID = 0x1AAA”. Aunque es posible dejar esta configuración
libre. Para identidicar el módem se puede utilizar una etiqueta llamada Node Identifier, en este caso este recibe
el nombre de “XBEEARDU3” aunque se puede nombrar como se desee. Una de las partes más importantes
dentro de la configuración es la selección del baud rate, que será de 115200 bauds. En este caso esta velocidad
esta definida con el numero 7 “BD = 7 - 115200”.
Para utilizarse mediante el uso de librerías es necesario que esten en modo API en lugar de Comandos AT. Por
ello además de configurar el function set como modo API es necesario establecer el registro “AP=2” como
requisito adicional de la librería. Para hibernar el módem el registro SM se debe de seleccionar como “SM = 1
PIN HIBERNATE”.
Tras esta configuración se seleccionará el tick “Always Update Firmware” para actualizarlo si fuera necesario
y sobre el botón write para escribirlo en el módem. Si se ha cambiado el baudrate no podrá comprobar si se
realizó el cambio correctamente ya que no está sincronizado, por ello es necesario realizar el primer paso para
leer los datos de configuración del módem con el nuevo baudrate y comprobar que no existe ningún problema.
Adicionalmente para amplificar la señal se utilizará una antena de 5 dB, lo que permite establecer una
comunicación desde cualquier parte del edificio sin interferencias.
3.2.3.1 DHT11
3.2.3.2 PIR
Para la detección de presencia se utiliza un sensor infrarrojos o PIR genérico. Se basa en la emisión de luz
infrarroja producida por el calor corporal de los seres vivos, por ello este sensor puede detectar presencia,
aunque no será capaz de saber diferenciar si se trata de personas o animales. Estos sensores tienen dos tipos de
funcionamiento, el primer tipo emite un único pulso con una duración que se puede controlar con un
potenciómetro y el segundo se pone a un nivel alto cuando detecta presencia y no baja hasta que esta no haya
desaparecido. En la realización de este proyecto se utiliza este último modo.
Este tipo de sensores están compuestos por una cúpula
de plástico, que funciona como lente y filtro. En la
figura 3-4 se puede apreciar la vista inferior del sensor
PIR que se utiliza en este proyecto. El jumper permitirá
seleccionar el modo de funcionamiento, si se usa el
modo High (pin central con el pin superior) funcionará
en modo pulso y si se usa en modo Low (pin central
con pin inferior) el sensor funcionará en modo
continuo, si detecta presencia se pondrá a uno.
Existen dos potenciómetros el de la izquierda que
permite establecer el tamaño del pulso, que no se tendrá
en cuenta ya que el sensor está configurado en modo
continuo. Mientras que el de la derecha permite Figura 3-4 – Vista inferior de un sensor PIR
controlar la sensibilidad, que se debe ajustar para no
Red de sensores para monitorización inteligente de vivienda 31
3.2.3.3 LDR
𝑉𝑟𝑒𝑓 × 𝐿𝑒𝑐𝑡𝑢𝑟𝑎
𝑉𝐿 =
1023
Donde VL es el voltaje que hemos leído, Vref es el voltaje de referencia y Lectura es el valor leído,
comprendido entre 1 y 1023. Mediante el uso de la figura 3-5, el divisor de tensión y conociendo el valor de la
resistencia R1 y del voltaje de alimentación VS, se puede saber el valor de la resistecia RLDR del LDR.
𝑉𝑆 − 𝑉𝐿
𝑅𝐿𝐷𝑅 = × 𝑅1
𝑉𝐿
Una vez se tiene el valor de la resistencia hay que linealizar la gráfica en una función para obtener la
luminosidad en Lux en función del valor leído. Debido a que se trata de una gráfica logarítmica se tendrá que
trabajar con potencias y logarítmos.
𝐿
log 10 𝐿𝐷𝑅 −𝐵
1000
𝐿𝑢𝑚𝑖𝑛𝑜𝑠𝑖𝑑𝑎𝑑 𝐿𝑢𝑥 = 10 𝑀
Siendo M el valor de la pendiente y B el valor del offset necesario para la linealización de la figura 3-6. Como
se puede observar existe un error importante, por lo que se trata de un valor aproximado calculado por el punto
medio, el cual no tiene porque ser el valor típico.
Los valores M y B para este LDR son M = -0.715335279 y B = 1.817398, en esta placa VS=Vref=3.3 V . Por
último para maximizar el rango de este LDR se utiliza una resitencia R1 = 22 KΩ.
Se ha optado por diseñar una shield en el programa Eagle, por ser uno de los programas de diseño de PCB más
extendidos y por su licencia gratuita a estudiantes. Existen otros programas, también con licencia gratuita y
algunos con mejores prestaciones que Eagle, como kicad, pero en Eagle existen una gran cantidad de librerías,
lo que permite en muchos casos no tener que crearlas.
Esta shield tiene un diseño simple con dos elementos soldados y sockets para DHT11 y PIR. Por lo tanto no se
requiere de ningún tipo de librería externa de Eagle. En las figuras 3-8 se muestra el esquemático y en la
figura 3-7 la PCB en su parte inferior, ya que tan solo se necesita de una cara de cobre.
Para ello se ha optado por el método de la transferencia por calor. Al tratarse de una única capa este método es
adecuado. Se trata de un método económico que permite la fabricación de PCB con una calidad óptima,
siempre que no se requiera de varias capas o vías entre las mismas.
Este método consiste en transferir la tinta de una impresora láser al cobre. La tinta funcionará como protector
del cobre frente al ataque químico. Para entender como ocurre esta transferencia es necesario conocer como
funciona una impresora láser.
En primer lugar, la impresora láser calienta el papel sobre la zona donde se quiere que quede pintado,
posteriormente pasa por un rodillo precalentado con tinta (realmente es una fina capa homogénea de un polvo
muy fino). Esta tinta quedará adherida en la zona previamente calentada. Esta impresión de la PCB debe
realizarse sin modo espejo ya que al tratarse de la capa botton (o inferior) se invetirá en el siguiente paso.
Para realizar la transferencia se enfrenta la capa impresa del papel con la cara de cobre de la PCB virgen con
cuidado para que no quede ningún tipo de arruga ni burbuja. En este proyecto se ha utilizado pegamento en
una zona externa a la PCB para no dañar el diseño, de esta forma no quedan arrugas en cada pasada por la
máquina.
Al pasar por el rodillo se calentará todo el cobre, quedándose la tinta adherida al punto más caluroso, es decir
en el cobre. En condiciones normales se tendría que pasar la PCB al menos tres veces por la máquina, ya que
menos veces podría significar que no se adhiera toda la tinta al cobre. Pero no es recomendable hacer este paso
más de seis veces, esto podría producir un aplastamiento de la tinta produciéndose cortocircuitos no deseados.
Con un poco de agua sin utilizar ningún tipo de jabón se retirará el papel de la PCB, que habrá quedado
pegado al mismo por el calor recibido. Este proceso hay que realizarlo con cuidado para que no se las pistas.
Se utilizará una máquina plastificadora modificada para tener una temperatura estable, en torno a los 200º
grados. Y para facilitar la transferencia se utilizará papel satinado.
Para la realización del ataque se utilizará, en proporciones iguales, agua, peróxido de hidrógeno, ácido
clorhídrico 110%. Este último es el responsable de eliminar el cobre, no obstante, para que se produzca este
ataque es necesario el peróxido de hidrógeno como principio activo. El agua se utiliza para rebajar la fórmula y
hacer que el ataque sea más lento y con mayor control.
Una vez finalizado el ataque, con jabón neutro y estropajo metálico se limpiará la placa hasta tener todo el
cobre visible y libre de tinta. En este momento estará todo preparado para taladrar la placa mediante una
herramienta tipo Dremel o taladro de mano y por último se soldarán los componentes.
3.3.2.1 xBee
La placa de desarrollo arduino UNO no dispone de zócalo para los módulos xBee, por lo que será necesario
una shield para esta función, la “Arduino Wireless SD shield”. Esta además de cumplir estos requisitos
gestiona una tarjeta microSD, aunque no será necesaria para este proyecto. Para poder realizar una correcta
comunicación con los nodos periféricos el módulo xBee debe de ser del mismo tipo. En este nodo será xBee
PRO serie 2, configurado como “Coordinator” por asumir funciones de coordinador de la red.
El nodo central es el encargado de generar una
dirección de red, la cual será trasmitida al resto de los
nodos mediante el protocolo de conexión de xBee.
Este nodo está destinado a estar a la espera de recibir
todos los mensajes por parte de los nodos periféricos,
por este motivo no pueden hibernar.
Para su configuración se realizan las mismas acciones
que en el apartado homónimo del nodo periférico a
excepción de dos claras diferencias además del NI
(identificador del módem). En primer lugar que si
utilizará el firmware “ZIGBEE COORDINATOR
API” en lugar del “ZIGBEE ROUTER API” en el
funtion set, se ignorará el registro correspondiente a la
Figura 3-10 – Arduino Wireless SD Shield hibernación de módem, ya que ni siquiera está
disponible al seleccionar el nuevo firmware.
3.3.2.2 WiFi
Se optó por un sistema de subscripcion mediante el protocolo MQTT ya que era necesario un enlace
bidireccional. Esto conlleva una complejidad dentro de la programación del firmware del arduino UNO. La
librería “pubsubsclient.h” permite utilizar este protocolo de una manera sencilla utilizando la librería integrada
desde el IDE de arduino para la gestión de las conexiones WiFi.
3.3.3.1 RC-522
Es un módulo que permite leer y escribir tarjetas RFID del tipo Mifare.
Este permite comunicarse con la placa arduino mediante el protocolo SPI,
UART o I2C e incluye una antena RF. Para identificar de forma única una
tarjeta Mifare se lee el número de serie de la tarjeta. En este proyecto se
realiza la comunicación mediante SPI. Tiene una transferencia de hasta 10
Mbit/s y funciona a 3.3V por lo que no habría problemas para
comunicarla con arduino. La conexión de los pines SCK, MOSI, MISO,
3V3 y GND deben coincidir con sus homónimos en la placa arduino. El
Figura 3-12 - Módulo RC-522
pin de señal de datos o SS está conectado al pin D6 del arduino mientras
que el pin de reset o RST lo está al pin D8.
Las tarjetas Mifare tienen la capacidad de almacenar entre 1 KB y 4 KB de información. Pero solo se
necesitará leer el identificador único de la tarjeta.
3.3.3.2 Alarma
En este proyecto se utilizará un relé que activará una sirena. El esquema para conectar el relé está basado en un
transistor MOS tipo n, que incluye un diodo de protección de corriente inversa que podría producir un bucle,
algo muy negativo para el circuito y el relé. A nivel de programación, utilizar un relé sería un actuador con
pull-down, el controlador debe ponerse en nivel alto para funcionar. El relé es instalado en la shield mediante
el uso de cables de conexión macho-hembra soldados a la PCB a modo de extensión de los propios pines con
la finalidad de facilitar la instación de la sirena.
Para su diseño se usará Eagle, utilizando como base de la PCB los pines de la placa arduino UNO. A
continuación se muestra un esquemático de los componentes y de la capa bottom de la PCB. Está compuesto
por módulos preconstruidos a excepción del detector de luminosidad.
36 Desarrollo del Hardware
$sudo su
Hay que crear un grupo determinado www-data para instalar el servidor. En esta distribución de raspbian
(jessy lite) viene creada y configurada, por lo que se puede proceder directamente a la instalación del servidor.
Para obtener la última versión de todos los componentes y servicios a instalar se actualizan las listas y los
servicios mediente los comandos.
$apt-get update
$apt-get upgrade
Como base de todo lo que se pretende instalar para obtener los servicios necesarios en el proyecto hay que
instalar apache2. Este es el servicio web que permitirá mostrar una página web básica en HTML5 con hojas de
estilos CSS3 y javascript.
Como es necesario utilizar php hay que instalar php5, con esto ya se tendría un servidor web con páginas
dinámicas mediante el uso de PHP en su última versión. Se pretende utilizar junto con apache y mySQL, por
lo que se instalan los componentes necesarios para que puedan interactuar.
Para que se haga efectiva la instalación de estos complementos se ejecuta el comando “reboot”, que reniniciará
el servidor.
$reboot
38 Desarrollo del Hardware
Una vez reiniciado el servidor se instalará la base de datos mySQL y el cliente mySQL
Durante la instalación del servidor se pedirá el nombre de usuario administrador de la base de datos, root por
defecto y la contraseña deseada. Una vez finalizada la instalación será necesario volver a reiniciar el servidor,
en adelante ejecutar el comando reboot será mencionado como reiniciar el servidor.
Tras reiniciarlo solo queda instalar phpmyadmin para gestionar la base de datos mediante el uso de una página
web. Durante la instación pedirá que se introduzca el usuario y contraseña de la base de datos mysql.
Para poder configurarlo y acceder desde una página web se debe modificar el archivo de configuración de php.
$nano /etc/php5/apache2/php.ini
Una vez abierto, al final del código se añade una línea con lo siguiente:
extensión=mysql.so
Se guarda el archivo pulsando la tecla control y la tecla "x" simultáneamente, se aceptan los cambios y no se
debe modificar el nombre del archivo. Finalmente se realiza una operación muy parecida a la anterior, en este
caso se accede al archivo de configuración de apache2.
$nano /etc/apache2/apache2.conf
Y de la misma forma que ocurre con el archivo anterior, al final del archivo se crea una nueva línea:
Include /etc/phpmyadmin/apache.conf
Por último se reinicia el servidor y ya se tiene el servidor web y la base de datos mySQL instalados. En cuanto
al uso de las tablas necesarias para el funcionamiento del proyecto será detallado en el sub-apartado backend
del capitulo 5 (Desarrollo Software).
curl -O http://repo.mosquitto.org/debian/mosquitto-repo.gpg.key
Red de sensores para monitorización inteligente de vivienda 39
Tras la instalación se reinicia el servidor y el bróker se ejecutará adecuadamente. Este bróker no está
configurado para que sea necesario utilizar un usuario y una contraseña. Para poder instalar una nueva
contraseña será necesario utilizar un recurso que incluye Mosquitto para crear y codificar una pareja
usuario/contraseña.
En este caso mosquito_passwd es el recurso que proporciona Mosquitto, -b permite poner usuario y contraseña
en la misma línea de comando, lo que simplifica su configuración, /etc/mosquitto/passwd.pw es la dirección
completa del archivo donde se almacena el usuario y la contraseña para acceder al bróker y por ultimo admin y
password son el usuario y la contraseña respectivamente.
Con esto se obtiene un archivo que almacena un usuario con su contraseña codificada, posteriormenete hay
que especificar al bróker que solo permita el acceso a los usuarios que existan dentro de este archivo y para
ello es necesario acceder al archivo de configuración.
$nano /etc/mosquitto/mosquito.conf
allow_anonymous false
password_file /etc/mosquitto/passwd.pw
3.4.3 Node.js
Para poder utilizar los servicios o daemons en Node.js es necesario la instalación de node y npm mediante apt-
get.
$sudo su
$apt-get install node
$apt-get install npm
Con estas instalaciones el servidor está preparado para ejecutar servicios programados en node. Y con npm se
pueden descargar librerías para utilizar entre otros mysql o mqtt.
40 Desarrollo del Hardware
Será necesario que el node se ejecute como un daemon, para simplificar este cometido se instala en el servidor
la aplicación forever para node. No obstante, será necesaria una instalación compatible con raspberry pi y por
ello se debe ejecutar el siguiente comando.
E hardware. Es programado en bajo nivel, generalmente en lenguaje Ensablador, C o como en este caso
Programing.
El firmware que está programado tanto en los nodos periféricos como en el nodo central se ha desarrollado con
el IDE de Arduino. Este IDE permite programar el microcontrolador de una forma muy sencilla ya que
permite una programacion a nivel relativamente alto, permitiendo abstraerse del uso de registros. El IDE de
arduino permite alternar la programación en programing, en C++ orientada a objetos y en C con programación
estructurada. De esta forma se pueden modificar los registros siempre que sea necesario o la programación lo
requiera, sin perder las ventajas de la programación con programing.
Debido a la extensa comunidad y a los propios desarrolladores de arduino existen cientos de librerías para
facilitar la programación de las placas arduino. Además se dispone de las librerías que facilita el fabricante de
estos microcontroladores, Atmel, que permiten usar funciones avanzadas tales como operaciones matemáticas
complejas, el uso del wachtdog o poner a hibernar el microcontrolador.
Se pueden distinguir tres tipos de librerías:
Librerías internas: son las que vienen preinstaladas en el IDE de arduino, no necesitan instalación y
se puede acceder desde el IDE de arduino. Estas librerías están realizadas por los desarrolladores de
arduino. Por lo general están diseñadas para utilizar elementos muy comunes, como SPI o I2C por
ejemplo, o para utilizar Shields propias, como la shield wifi o la shield Ethernet.
Librerías externas: son las desarrolladas por la comunidad, es necesaria su instalación, aunque una
vez instalada se puede acceder a ellas desde el IDE de arduino. Al estar desarrolladas por la
comunidad y tratarse de un recurso open-source, si lleva mucho tiempo en la red es difícil que tengan
algún error, ya que la propia comunidad está mejorando continuamente estas librerías. Es la principal
ventaja del IDE de arduino ya que casi todos los componentes o módulos genéricos disponen ya de su
propia librería para ahorrar tiempo y esfuerzo en la programación del firmware.
Librerías AVR: las que facilitan el fabricante del microcontrolador. No necesitan instalación, pero no
se puede acceder a ellas desde el IDE, sino que es necesario visitar la web del fabricante y ver que
librerías están disponibles para el microcontrolador que se está utilizando e invocarla de forma manual
al principio del código siguiendo el siguiente ejemplo.
Red de sensores para monitorización inteligente de vivienda 43
#include <avr/librería.h>
Este IDE se puede descargar de forma gratuita de la web oficial de arduino y está disponible para los tres
sistemas opertativos más importantes: Windows, Linux y MacOS.
4.1.1 Sensores
El nodo periférico dispone de tres sensores, que generarán cuatro datos. Estos tres sensores son el sensor
digital, el sensor analógico y el sensor digital booleano.
Para la lectura del sensor de luminosidad, tan solo se leerá el pin de entrada analógico A0. Debido a la
dificultad de transmitir un dato con coma flotante, se ha decidido mandar el dato de la lectura correspondiente
a los valores entre 0 y 1023 que corresponden a 0 y 5 V respectivamente. Y será más adelante cuando estos
datos sean transformados a un valor de luminosidad en Lux.
Es un sensor booleano por lo tanto su lectura corresponde al sistema binario „detecta‟ o „no detecta‟ algún tipo
de presencia. Cuando se recibe un nivel alto se considera que existe algún tipo de presencia.
Debido a que este sensor se utiliza en primera medida para el sistema de alarma, al detectar todo tipo de
movimiento de un cuerpo que genere temperatura propia (principio de funcionamiento del sensor de presencia)
deberá de saltar la alarma siempre que esta este activa.
Sin embargo debido a que un ladrón, en casos generales, no tarda menos de 30 segundos dentro del hogar, para
conseguir una mayor autonomía, se realizará esta lectura solo cuando el nodo sea despertado por el watchdog,
que como se verá a continuación será cada ocho segundos.
Para evitar algunas falsas alarmas producidas por movimientos indeseados o fallos en la lectura, se realiza una
nueva lectura cuando el módem este operativo después del tiempo de time up, si es positiva, la presencia es
real.
Debido a que el nodo periférico no tiene forma de detectar si está o no la alarma armada, el sensor volverá a
funcionar con normalidad. Este funcionamiento aislado solo se dará cuando se pasa a leer un nivel alto siendo
el último dato leído en un nivel bajo.
La lectura del sensor DHT11 proporciona datos acerca de la temperatura y la humedad, para ello se recurre a
una librería externa. Esta incluye un objeto que permite generar una lectura de ambos sensores, evitando tener
que controlar el pin D2 como entrada o salida según dicta el protocolo. Esta instancia del objeto se creará
mediante el siguiente código:
44 Desarrollo del Firmware
dht11 DHT11;
La función que se utiliza en este proyecto es int read(int pin) que devuelve un valor 0 cuando no ocurre
ningún error y -1 o -2 si ocurre un error de checksum o de tiempo de espera respectivamente. Como variable
de entrada se le dará el valor numérico del pin digital al que está conectado físicamente el sensor DHT11 a la
placa arduino. Esta función tal como se puede intuir por el nombre realiza una lectura de temperatura y
humedad, estas lecturas se almacenan dentro de las variables temperature y humidity respectivamente. Para
acceder a la función de lectura y las variables de la instancia se realizará del siguiente modo:
Los métodos del objeto XBee que se van a utilizar son send(ZBTxRequest zbTx), que permite el envío de
paquetes de datos al nodo central siguiendo una estructura propia de la librería, readPacket(tiempo), que leen
los datos recibidos durante el tiempo definido como variable de entrada, getResponse() que se utiliza para
conocer el resultado de la transmisión, y setSerial(UART), que sirve para establecer una conexión entre el
módulo xBee y el puerto UART indicado.
La estructura de la librería xBee que se va a necesitar a lo largo del programa es XBeeAddress64. Está
compuesta por dos enteros de 32 bits cada uno. Almacena una dirección mac de xBee pudiendo diferenciar
dos variables correspondientes a los 32 bits más significativos y los menos.
Como se observa, para enviar datos se necesita una estructura especial que almacene la dirección del envío y la
trama de datos útiles que se desea enviar. Esta estructura es ZBTxRequest.
Y por último para conocer si se ha recibido o no el paquete en el nodo central se utiliza la estructura
ZBTxStatusResponse.
Durante el envío se puede controlar si los datos se han emitido correctamente, en contadas ocaciones, es
posible que este sea erróneo y se reitere constantemente, es por ello que sea necesario resetear la placa. Se
establece un máximo de cincuenta errores para producir este reseteo de software, que salta a la primera
posición de ejecución del programa.
void softReset()
{
asm volatile (" jmp 0");
}
Para que el servidor pueda parsear los datos de forma correcta se debe montar la trama formando parejas
“tipo=valor” separados por el carácter „&‟. Este tipo de trama es comúnmente utilizado en llamadas GET de
HTML. De hecho, debido a que al principio la idea era transmitir la trama a un webservice en PHP, se pensó
en montar la trama de tal forma que no hiciese falta el parseo desde el nodo central sino que se enviase
directamente al webservice.
Finalmente el envío se realiza por MQTT, por lo que el parseo podría realizarse de diversas formas entre ellas
esta misma. El nodo periférico es transparente al método de comunicación del nodo central con el servidor.
Un ejemplo de trama enviada:
TEM=25&HUM=41&LUZ=386&PIR=1
En el envío hay que especificar cual es la MAC destino en la que está almacenada la variable de tipo estructura
XBeeAddress64 llamada addr64.
Lanzando el mensaje send del objeto xBee se envía la trama. Como detalle importante acerca del
funcionamiento de xBee, el módem tarda hasta treinta segundos en su proceso de wake up desde que envía o
recibe una trama en modo sleep. Por ello, es necesario realizar un envío de una trama, la cual se sabe que no va
a llegar, treinta segundos antes de mandar la trama real. Tras despertar el microcontrolador del estado de
hibernación se manda la trama, durante esa espera se realiza la lectura y el maquetado de la trama. Pasado este
tiempo se envía la trama y se comprueba que ha llegado.
xbee.send(zbTx);
xbee.readPacket(1500);
err = xbee.getResponse().getErrorCode();
stat = xbee.getResponse().getApiId();
if (stat == 0 && err == 0) {
Serial.println("ERROR");
} else if (stat == 117) {
Serial.println("ERROR");
} else {
Serial.println("OK");
}
46 Desarrollo del Firmware
En la gestión de la hibernación se necesitará la librería sleep.h. Esta permite varios modos de ahorro energético
en función de las necesidades del programa ejecutado. En la figura 4-1 se muestra una tabla obtenida del
datasheet del microcontrolador, en ella se puede observar marcada con una “X” los componentes activos con
cada uno de los modos de ahorro energético.
El modo de hibernación escogido para ahorrar energía es el modo “Power-Down”. Se recurre a la librería
power.h que proporciona el fabricante para apagar TWI elemento antes de poner el disposivo a dormir,
ahorrando de esta forma una mayor cantidad de energía. Si se apaga mediante este método los timers 0, 1 y 2 y
el SPI y ADC se consigue disminuir a la mitad el consumo energético.
En la hibernación del dispositivo es indispensable cambiar los registros necesarios para su preparación. El
fabricante da la opción de preparar el dispositvo con la función.
sleep_enable();
Red de sensores para monitorización inteligente de vivienda 47
Para que el dispositivo no se duerma por error hay que desactivar este modo mediante:
sleep_disable();
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
Antes de dormir el dispositivo es necesario apagar los componentes mencionados, para ello se ejecutan los
siguientes comandos:
power_timer0_disable();
power_timer1_disable();
power_timer2_disable();
power_adc_disable();
power_twi_disable();
power_spi_disable();
Sin embargo, activar todos los componentes simultáneamente es más rápido mediante el comando:
power_all_enable();
sleep_mode();
Al despertar, el dispositivo volverá a la siguiente línea, donde será necesario activar todos los componentes del
dispositivo y deshabilitar el modo sleep.
Todo este proceso se realiza con la función duerme(), para facilitar y agilitar la puesta del dispositivo a
hibernar.
4.1.3.2 WachtDog
Es un timer que sirve para liberar la ejecución cuando está por alguna razón, generalmente no deseada,
bloqueada o ha entrado en un bucle infinito. Su funcionamiento es bastante simple, cuando este contador
desborda reinicia el sistema y de esta forma la ejecución sale del bloqueo o del bucle infinito. Para evitar que
este contador desborde, durante la ejecución normal del programa este se restaura a cero en cada interacción
del bucle principal.
La función del wachtdog en este sistema es despertar al microcontrador cuando este se encuentre en modo
sleep, produciendo a su vez una interrupción en la ejecución del programa principal ejecutando una rutina de
interrupción, la cual, se ha definido para evitar que el microcontrolador apage o reinicie el sistema de forma no
deseada cada ocho segundos.
Esta configuración se realiza mediante la escritura de forma directa de los registros. Es recomendable tener
cuidado de no cambiar de forma accidental el estado del resto de bits pertenecientes al registro que deseamos
modificar. Para ello se utilizará los operando “AND” para poner a cero un bit de un registro concreto, y “OR”
para ponerlo a uno.
Lo primero que hay que hacer es dar la orden al microcontrolador de que al saltar la interrupción generada por
48 Desarrollo del Firmware
el wacthdog no se reinicie, sino que se llame a la función ISR (función por defecto de interrupciones). Para
ello es necesario modificar el registro MCUSR.
En la figura 4-2 se puede ver como está formado el registro MCUSR, sin embargo, el único bit de este registro
que interesa para el proyecto es el bit 3, WatchDog system Reset Flag (WDRF). Si este bit está en nivel alto, al
ocurrir una interrupción provocada por el watchdog se reiniciará el microcontrolador, sin embargo, si este bit
se encontrase en nivel bajo, se llamaría a la función ISR. Por lo tanto se tendrá que poner este bit a cero
mediante la siguiente instrucción.
En cuanto a la configuración del watchdog hay que recurrir al registro WDTCSR que se muestra en la figura
4-3. En este caso, si es necesario explicar la función de todos los bits.
Figura 4-3 – Registro de control del temporizador watchdog del microcontrolador Atmel ATmega328p
Bit 7 – WDIF: Indica que se produce una interrupción del watchdog. Esta generalmente se actualiza
directamente cuando desborda el timer del watchdog, no obstante, si se requiere se puede poner este bit a uno
obteniendo el mismo efecto. Durante la ejecución de la configuración inicial no será necesario su modifiación,
pero al llamar a la rutina de interrupción es necesario cambiar este bit a nivel bajo.
Bit 6 - WDIE: Este bit activa el watchdog a nivel alto y lo desativa a nivel bajo. Para evitar problemas durante
la configuración del registro es necesario ponerlo a cero antes de empezarla mediante el siguiente comando:
Bits 5, 2, 1 y 0 – WDP3, 2 1, 0: Preescalador del timer, estos bits permiten aumentar el tiempo que tarda el
timer en desbordar. En la figura 4-3 se muestra una tabla con las diferentes posibilidades. Como se puede
apreciar tan solo se dispone de un tiempo máximo de ocho segundos. Aunque utilizando una variable a modo
de contador se controla si se quiere volver a colocar el dispositivo en modo hibernación, o bien se quiere que el
dispositivo ejecute una lectura y envío de datos.
Red de sensores para monitorización inteligente de vivienda 49
Figura 4-4 – Tiempo de preescalado del watchdog del microcontrolador Atmel ATmega328p
Bit 4 – WDCE: Este bit es necesario para realizar los cambios tanto en el WDE como en el preescalador del
registro. Es importante ponerlo en nivel alto para realizar los cambios. Una vez actualizado el preescalador este
bit será reiniciado tras cuatro ciclos de reloj.
Bit 3 - WDE: Este bit tiene la misma función que el bit WDRF del registro MCUSR. Por lo que si se pone a
uno el bit WDRF automáticamente se registrará a uno el bit WDE. Y si se desea cambiar el bit WDE a cero, es
necesario poner a cero el bit MCUSR previamente. Si este bit se encuentra en nivel alto la placa se reiniciará
cuando desborde el watchdog.
A continuación, se muestra el código para la configuración del registro WDRF:
Una vez producida la interrupción del watchdog se despertará el microcontrolador, esto no tiene porque ser la
función deseada, ya que se requiere que el dispositivo esté en estado de hibernación todo el tiempo que no este
realizando una lectura o emitiendo. Es por ello que se establece una variable a modo de contador que permite
comprobar cuanto tiempo lleva el dispositivo en hibernación. Una vez despertado el dispositivo, este hibernará
en la siguiente ejecución de la rutina principal.
Ya que es necesario tener un control para saber si se detecta alguien en casa cuando la alarma está activa, se
realizará una lectura del sensor de presencia durante la ejecución de esta rutina. Teniendo en cuenta el último
valor leído, se interrumpirá el estado de hibernación o continuará con normalidad.
Esta comprobación basada en la última lectura es debida a que no se puede saber si está armada o desarmada
la alarma, ya que la comunicación está solo disponible desde el nodo periférico al nodo central.
50 Desarrollo del Firmware
4.2.1 Sensores
El nodo central generará una lectura de temperatura, humedad, luminosidad y presencia igual a la generada en
el nodo periférico, por lo que se acudirá al apartado 4.1.1 para conocer su programación.
4.2.1.1 RFID
Se dispone de un lector de tarjetas RFID RC522 que se conecta mediante I2C al arduino UNO. Para
simplificar su programación se recurre a una librería. En este proyecto solo será necesaria la parte en la que se
detecta una nueva tarjeta Mifare y en la que se lee su identificador.
En primer lugar hay que instanciar o crear el objeto de clase MFRC522 en el cual hay que especificar los pines
SS y RST.
Para conocer si hay una nueva tarjeta RFID se llama al metodo PICC_IsNewCardPresent(). Este devuelve
true cuando se detecta una nueva tarjeta. Sin embargo, no es capaz de diferenciar si esta tarjeta ha sido leída
antes, por lo que es propenso a dar muchos errores por el efecto rebote. Por ello se debe conpaginar con una
variable booleana que haga las veces de bandera. De tal forma que si esta bandera está a false significa que no
hay ninguna tarjeta y true que ya ha sido leída.
·
·
·
Mientras la tarjeta está estabilizada el método devolverá false por como está construido. Por ello la bandera
Tpresente permanecerá activa mientras ocurrá esto. Falta detectar cuando se retira la tarjeta. Esta librería no
recoje ningún método para esta función, no obstante, al retirar la tarjeta se produce el efecto rebote por lo que
en este proceso el método emite true. Por lo que colocando el siguiente if se detecta cuando deja de estar
presente la tarjeta.
Red de sensores para monitorización inteligente de vivienda 51
Una vez se ha detectado la tarjeta hay que leer su identificador, que será utilizado para comprobar en el
servidor si está registrado y en tal caso si entra o sale de casa el individuo.
El método PICC_ReadCardSerial() permite hacer una lectura estructurada de la tarjeta RFID, almacenando el
dato de interés para este proyecto en una variable publica uid como un array de tipo byte.
Para evitar cualquier error en la transformación de tipo a uint8_t en el envío por MQTT, se realiza una copia
de estos datos convertidos a char en un nuevo array y posteriormente se manda la trama MQTT.
if ( mfrc522.PICC_ReadCardSerial()) {
for (byte i = 0; i < mfrc522.uid.size; i++) {
RFID_ID[i] =(char) mfrc522.uid.uidByte[i];
}
clientmqtt.publish("pfc/rfid", (uint8_t*)RFID_ID, strlen(RFID_ID),
true);
Tpresente = true;
}
De esta forma se recupera la información que se necesita de la tarjeta RFID, siendo necesario esperar a que se
retire para bajar la bandera Tpresente.
En este caso será necesario el uso de dos clases, cuyas instancias o creaciones de objetos se reflejan en el
código como:
La clase xBee es la clase principal, que va permitir el uso de los métodos begin() para inicializar el objeto con
el puerto serie deseado.
Serial.begin(115200);
xbee.begin(Serial);
52 Desarrollo del Firmware
Y el método readPacket() para obtener el paquete almacenado en el buffer del módem, guardando el socket en
una subclase pública de tipo estructura entre los que se destaca un método para copiar la trama leída a un
objeto del tipo ZBRxResponse.
xbee.readPacket();
Para poder copiar los datos al objeto “rx” será necesario utilizar la subclase mencionada en el párrafo anterior.
if (xbee.getResponse().getApiId() == ZB_RX_RESPONSE) {
xbee.getResponse().getZBRxResponse(rx);
·
·
·
El método getApiId() de la subclase permite conocer cual es el tipo de socket leído, mientras el método
getZBRxResponse() permite copiar el socket al objeto “rx”. Una vez que el socket está dentro de este objeto se
puede obtener el tamaño del mismo mediante el método getDataLength().
tam=rx.getDataLength();
for(int aux=0;aux<55;aux++){
Trama[aux]=(char)rx.getData(aux);
}
Y obtener la dirección Mac del nodo periférico que emitió la trama para informar al servidor del lugar desde
procedía.
macLsb = rx.getRemoteAddress64().getLsb();
Se utiliza una librería interna haciendo que su programación sea más intuitiva. No hace falta instanciar la clase
WiFiclass, sino que se llamarán a sus métodos utilizando el objeto WiFi. Este objeto es instanciado de forma
automática en el mismo momento en el que se utiliza la librería, generalmente al instanciar el cliente WiFi.
WiFiClient client;
Los métodos utilizados con el objeto WiFi son: Status(), permiten saber si está conectada o no la shield;
begin(ssid,pass) permite la conexión al punto de acceso wifi; LocalIP() devuelve la dirección IP que establece
mediante DHCP el punto de acceso para el módem; RSSI() devuelve la calidad de la conexión o cobertura en
dBm.
Red de sensores para monitorización inteligente de vivienda 53
En cuanto al cliente, no se usa directamente ningún método, sino que es la librería pubSubClient.h la que
utiliza este cliente de forma interna.
El objeto WiFiClient hereda la clase Client. Esta define los métodos necesarios para la conexión y envío de
sockets mediante WiFi, por lo que utilizando la librería pubSubClient se consigue un alto nivel de abstracción
ya que no es necesario en ningún momento llamar a los métodos del cliente WiFi.
Se utiliza el protocolo MQTT para crear un sistema de publicación y subscripición. De tal forma que un
dispositivo que emita un socket en un determinado topic hará que cualquier otro dispositivo subscrito a este
pueda recibir la trama.
La librería pubsubclien.h se usa para la conexión, subscripción y publicación con el bróker MQTT. Está
compuesta por una única clase con sus respectivos métodos.
Hay que instanciar la clase PubSubClient, para ello el constructor requiere un objeto del tipo client, un array de
char para almacenar la dirección del servidor donde se aloja el bróker, un int con el puerto del mismo y la
dirección de una función que se ejecutará cuando se publique en un topic al que se está subscrito.
PubSubClient clientmqtt(MQTT_SVR_IP,MQTT_SVR_PORT,callback,client);
Mediante el método connect se realiza la conexión al bróker MQTT. Este método va a necesitar un
identificador único, el usuario y la contraseña para registrarse en el bróker, un topic para enviar una trama que
ayude a mantener la conexión y el mensaje que se desea enviar y si se desea que se retenga esta información
en el bróker.
Debido a que no se puede repetir el ID del dispositivo, se genera un ID de forma aleatoria mediante la función
random generando una semilla randomSeed aleatoria leyendo un dato de algún pin analógico no usado.
Para comprobar si se ha desconectado del bróker en cada interación se revisa si se mantiene conectado
mediante el método conected().
if (!clientmqtt.connected()) {
char clientID_buffer[22];
for (int i = 0; i < 22; i++){
clientID_buffer[i] = random('a', 'z');
}
if (clientmqtt.connect(clientID_buffer, MQTT_USER, MQTT_PASS,
"pfc/estado", 0, 1, "0")) {
·
·
·
}
}
54 Desarrollo del Firmware
Y al final de cada bucle se manda una trama de control al bróker, esta es necesaria ya que renueva la conexión
con el bróker. Este envío está recogido en el método loop del objeto.
clientmqtt.loop();
Cada vez que se conecta, al tener un nuevo ID, es necesario volver a subscribirse a los topics donde estaba
subscrito. Para realizarla se utiliza el método subscribe().
clientmqtt.subscribe("pfc/alarma");
Cuando algún dispositivo mande una trama con este topic se llamará a la función callback, como si de una
rutina de interrupcción se tratase. Esta comprobación es posible por el método loop(), que adicionalmente a la
comunicación de mantenimiento de la conexión comprueba si se han enviado datos a los topics en los que está
subscrito el dispositivo.
El nodo central tiene la necesidad de crear dos tramas, la primera de ellas es la vista en el apartado 4.2.1.1
donde se manda un socket MQTT con el topic pfc/rfid y el contenido del mensaje es el ID de la tarjeta RDIF
presentada.
Por otro lado, está la trama de los sensores. Debido a que debe seguir el mismo formato que la trama enviada
por los nodos periféricos estará compuesta por pares “tipo=valor” separados con el carácter „&‟. Sin embargo,
a diferencia de lo que ocurre con los nodos periféricos será necesario especificar la MAC, ya que es el nodo
central es el encargado de escribirla en los periféricos. La MAC del propio nodo no es posible de hallar, ya que
se utiliza el propio socket xBee para leerla. Por esta razón es necesario especificar manualmente la MAC del
nodo central.
Para simplificar la creación de la trama y poder reutilizar el código escrito en el nodo periférico la MAC se
suministra como una pareja “tipo=valor” seguido del separador „&‟, tal que lo siguiente sea introducir los
datos leídos por los sensores.
char mac[]="MAC=1085975315&";
Una vez escrita la MAC, reutilizando el mismo código que en el nodo periférico pero sin iniciar la variable que
sirve de índice, se genera la trama que quedaría:
MAC=1085975315&TEM=35&HUM=51&LUZ=561&PIR=0
Una vez generada, el mensaje se envía al socket MQTT con el topic pfc/lectura
clientmqtt.publish("pfc/lectura",(uint8_t*)texto,strlen(texto),true);
Siendo el array de char texto el que almacena la trama que se desea enviar.
Red de sensores para monitorización inteligente de vivienda 55
Para recibir la trama xBee es necesario ejecutar el código utilizando las clases y los métodos explicados en el
apartado 4.2.2.1. Una vez leída la trama es necesario leer la MAC del socket y montar una trama que debe
quedar exactamente igual que el del apartado anterior. La función monta trama simplemente crea una trama
con el siguiente formato:
MAC=1085975325&TEM=25&HUM=41&LUZ=386&PIR=1
Una vez montada la trama el proceso de envío del socket por MQTT es exactamente igual al que se realiza en
el apartado anterior.
Este nodo debe subscribirse a un topic que le avise si debe activar o desactivar la alarma. En el caso de que se
tuviera más de un topic, por la variable topic de la función callback se puede conocer cual es el origen del
mismo.
A partir del mensaje recibido se puede saber si la alarma está desactivada, armada o sonando. Para conocer el
estado de la alarma, se comprobará el mensaje y se actuará conforme al resultado del mensaje.
En el caso de que el resultado de alarma sea dos se activará el relé para que la alarma empiece a sonar.
56 Desarrollo Software
5 DESARROLLO SOFTWARE
entro del diseño software se diferencian varios elementos, la programación de los servicios, la lectura
D de datos desde la base de datos y todo aquello que se ejecuta desde el lado del servidor (backend); el
bróker MQTT para comunicar el hardware con el servidor (middleware) y por último el diseño de una
interfaz web, donde el usuario final pueda tener acceso a estos datos y gestionarlos abstrayéndose de la forma
en que los datos son mostrados en pantalla (frontend).
5.2 Backend
5.2.1 Base de datos en mySQL
La programación del backend da soporte a la interfaz de usuario. Por ello es necesario el uso de un servidor
web con base de datos en mySQL. Para entender el uso de los diferentes servicios y recogida de datos es
importante conocer la organización de las tablas del servidor. En este proyecto serán necesarias cinco tablas:
una para almacenar los datos de los sensores, que recibe el nombre de “Sensores”, una segunda tabla orientada
Red de sensores para monitorización inteligente de vivienda 57
a los sensores, pero que establece parejas de nodo con el nombre asignado con el nombre “Registro”; otra para
gestionar el control de acceso, que recibe el nombre de “rfid”; otra pseudo asociada a la anterior para conocer
el estado de la alarma, si está o no armada, que tiene el nombre de “Alarma”; y por último una tabla que
almacena pares de usuarios/contraseña con acceso al panel de administración.
En cada fila de esta tabla se almacena el tipo de sensor y su valor. Realizar una tabla para cada nodo sin poder
estimar el número que hay es tedioso e ineficiente. Si se le agregase un valor que indique la mac del nodo de
donde procede la lectura sería necesaria solo una tabla. Como se van a almacenar varios datos
correspondientes a la misma lectura se debe saber la fecha en la que fue escrita y por último obtener un
identificador único de la lectura.
Por lo tanto la estructura en código mySQL será la siguiente:
Sensores` (
`id` int(32) NOT NULL,
`mac` int(32) NOT NULL,
`sensor` varchar(3) COLLATE utf8_spanish_ci NOT NULL,
`valor` float DEFAULT NULL,
`fecha` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8
COLLATE=utf8_spanish_ci;
Se almacenan las direcciones MACs activas con sus respetivas etiquetas. El daemon es el servicio que recoge
las tramas MQTT emitidas por el nodo central. Cuando este detecta una nueva trama, realiza un registro en
esta tabla con la etiqueta “SinAsignar”. De esta forma se mantienen por separados las lecturas de los nodos
disponibles. Una vez eliminado un nodo de esta base de datos, no se mostrará por la interfaz pero si se
mantendrán almacenados los valores leídos. Por ello, si se elimina un nodo por error, será fácil volver a
recuperar todos los datos.
La estructura en código mySQL será la siguiente:
`Registro` (
`mac` int(32) NOT NULL,
`room` varchar(32) COLLATE utf8mb4_spanish_ci NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_spanish_ci;
Está basada en la tabla anterior, por un lado tiene el identificador de la tarjeta RFID y por otro el nombre
asignado por el usuario. No tiene un histórico de cuanto tiempo pasa alguien en casa porque no es necesario
para esta aplicación, ya que solo se requiere conocer si queda alguna persona con permiso en la vivienda, y en
función de esto armar o desarmar la alarma. En este caso, cuando el daemon detecta una nueva ID la registra
con el nombre “SinRegistrar”.
Finalmente la estructura en código mySQL será la siguiente:
`rfid` (
`id` int(11) DEFAULT NULL,
`usuario` varchar(12) DEFAULT NULL,
58 Desarrollo Software
En esta tabla solo será necesario utilizar una única fila. Esta servirá para conocer desde el servidor el estado de
la alarma. Como solo se quiere utilizar una fila se pondrá una columna “Alarma", cuyo contenido no puede ser
repetido. Es decir si la fila en esta columna recibe el nombre también de “Alarma”, y la base de datos recibe
una orden de almacenar unos datos cuyo valor en “Alarma” es “Alarma” los datos recibidos sustituirán a los
que ya existen y no se añadirá un nuevo elemento llamado “Alarma". Lo que sería muy confuso.
`Alarma` (
`Alarma` varchar(6) NOT NULL,
`Armado` tinyint(1) NOT NULL,
`Sonando` tinyint(1) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Esta tabla almacena parejas de usuario y contraseñas con acceso a la base de datos, de tal forma que cada
usuario está registrado a un ID para aplicaciones futuras propuestas en el capítulo 7. Cuando se realiza la
comprobación de esta tabla, si ambos elementos no coinciden no se permitirá el acceso al panel de
administración como se verá más adelante.
La estructura en código mySQL será la siguiente:
`users` (
`id` int(11) NOT NULL,
`usuario` varchar(11) NOT NULL,
`contrasena` varchar(11) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1;
5.2.2.1 get_sensor.php
Sirve para identificar cada MAC física con su etiqueta asociada, haciendo una consulta a la tabla de registro
para conocer todos los datos de la tabla cuya etiqueta es diferente a “SinAsignar”. Para ello se establece una
conexión a la base de datos y se genera una consulta del tipo
Posteriormente se monta un JSON, que es un formato para pasar una serie de datos legibles por JavaScript.
Para formar el JSON se crea un array de datos formado por ““mac”=“MAC del nodo”, “room”=“Nombre del
nodo””.
$array= array();
while ($fila = mysqli_fetch_array($consulta)){
$dato = array(
"mac"=>$fila['mac'],
"room"=>$fila['room']
);
array_push($array, $dato);
}
Mediante la función json_encode() se pasa la trama al formato JSON, un ejemplo de este formato es:
[{"mac":"1085975339","room":"SALON"},{"mac":"1085975325","room":"COCI
NA"},{"mac":"1235496865","room":"CONTADORES"},{"mac":"2147483647","roo
m":"DORMITORIO"}]
5.2.2.2 get_data.php
Es un archivo que devuelve todos los datos de un único tipo leído por un nodo en concreto en un rango de
fechas dado. El servicio necesita cuatro parámetros para saber que parámetros debe devolver: la mac del nodo,
el tipo de sensor que se desea leer, la fecha mínima y la fecha máxima.
Al igual que se ocurre con get_sensor.php, se almacenan la información en un array de datos para
posteriormente montar un JSON que será devuelto. Un ejemplo de salida de datos de este servicio es:
Como se puede comprobar en este ejemplo, esta información corresponde a datos leídos entre el día
14/09/2015 a las 00:00 y el día el 14/09/2015 a las 12:00. Aunque el uso que se le dará a este archivo está
orientado a leer por días, se pueden especificar las horas, minutos y segundos en los límites máxímos y
mínimos.
5.2.2.3 SuperConsulta.php
Este servicio devuelve una lista de las últimas lecturas de los sensores de todos los nodos, además genera un
enlace para poder visualizar las gráficas los nodos. No necesita ningún parámetro y su devolución incluye el
código HTML con el formato especificado en la sección de frontend. Se trata de la consulta que se puede
visualizar en la página principal del proyecto final de carrera.
La principal ventaja de este servicio es que con una única conexión a la base de datos se puede acceder a todo
el contenido, aunque se realicen varias consultas. Genera un enlace para poder visualizar el histórico de los
sensores en gráficas.
Adicionalmente devolverá la información de quienes están en la vivienda y si se detecta algún nodo o tarjeta
sin etiqueta generará un enlace al panel de administración.
60 Desarrollo Software
SALON
PIR : 1 en 2016-02-21 16:52:31
LUZ : 631 en 2016-02-21 16:52:31
HUM : 37 en 2016-02-21 16:52:31
TEM : 20 en 2016-02-21 16:52:31
COCINA
PIR : 1 en 2015-08-13 22:07:03
LUZ : 303 en 2015-08-13 22:07:03
HUM : 29 en 2015-08-13 22:07:03
TEM : 31 en 2015-08-13 22:07:03
CONTADORES
TEM : 100 en 2015-09-15 09:26:34
PIR : 1 en 2015-09-10 10:59:59
LUZ : 253 en 2015-09-10 10:59:59
HUM : 12 en 2015-09-10 10:59:59
DORMITORIO
PIR : 1 en 2015-09-23 09:52:07
LUZ : 350 en 2015-09-23 09:52:07
HUM : 15 en 2015-09-23 09:52:07
TEM : 35 en 2015-09-23 09:52:07
5.2.3.1 Setup.html
Se trata de un formulario para introducir Usuario y Contraseña, así se podrá comprobar de forma segura que el
acceso al panel de administración esté protegido. Estos datos se enviarán al servicio admin.php mediante
HTTP POST para proteger lo datos enviados. Pese a que esta parte pertenecería al frontend se ha decidido
colocar aquí para simplificar su documentación admin.php
Tras recibir los datos de usuario y contraseña se identificará si son válidos. En el caso de que no lo sean se
devolverá el mensaje “Usuario o Contraseña erróneo” junto con la posibilidad de volver a introducir usuario y
contraseña.
En caso contrario generará una lista con todos los datos de la tabla Registro, los usuarios de la tabla rfid, y el
estado de la alarma. Se pueden asignar etiquetas a nuevos nodos o personas con acceso a la vivienda. Y
también corregir de forma remota un descuido al no pasar la tarjeta RFID por el lector y no armar o desarmar
la alarma.
5.2.3.2 mRegistro.php
Se trata de un archivo similar al anterior, difiere en que los parámetros de entrada son Actualizar o Eliminar en
el registro, de tal forma que se puede efectuar una acción en la base de datos. Para ello es necesario la
dirección MAC del sensor o la ID de la tarjeta RFID y la nueva etiqueta para efectuar los cambios.
Tanto en el archivo admin.php como en el archivo mRegistro.php, los cambios se hacen uno a uno y cada
botón de actualizar funciona como actualizador o eliminador de valores que están asociados a él.
Ejemplo 1 de actualización:
En la figura 5-3 se puede observar como queda el archivo admin.php correctamente logeado.
Se cambian dos elementos simultáneamente en la figura 5-4 y pulsamos actualizar sobre el primero de los
elementos cambiados.
Tras pulsar el botón actualizar, se puede observar en la figura 5-5 tan solo se actualizó el elemento donde se
pulsa dicho botón.
Ejemplo 2 de actualización:
En la figura 5-3 se puede observar como queda el archivo admin.php correctamente logeado.
Se cambian dos elementos simultáneamente en la figura 5-4 y pulsamos actualizar sobre cualquier elemento
no cambiado.
Tras pulsar el botón actualizar en la tercera opción, se puede observar en la figura 5-6, se pierden ambas
actualizaciones.
5.3 Middleware
5.3.1 Servicio NodeJS
Sirve para atender a los datos que se envían desde la placa de arduino desde el lado del servidor. Para ello es
necesario que exista un servicio subscrito a los datos que envía el nodo central. Cuando llega una trama al
servicio, se parsea y se almacenan los datos en la base de datos.
Se necesita un servicio que tenga la capacidad de soportar subscripciones MQTT, que pueda almacenarlas en
una base de datos mySQL y que este corriendo constantemente. Por lo que se tendrá que recurrir a un potente
lenguaje. En este proyecto se ha seleccionado nodeJS por las posibilidades que ofrece.
Su función es almacenar la información recogida en la base de datos y comprobar si la alarma está armada en
caso de que la trama indicase que hay una presencia. Si esto ocurriese se mandaría una trama MQTT avisando
de que la alarma debe ser encendida. Si tras esto se detectase que la alarma es desarmada o cancelada, se
enviaría una nueva trama MQTT para cancelar el proceso de encendido de la sirena
Recibe los datos de los sensores y los de los registros realizados con la tarjeta RFID, comprobando si esa
persona entra, sale o no está registrada.
Se ha incluido un sistema de envío de e-mails para informar cuando se inscribe un nuevo nodo o se registre
una tarjeta, ya sea porque una persona salga o entre de casa o sea una persona sin acceso.
También avisará cuando se arme la alarma y cuando empiece a sonar.
5.3.1.1 MQTT
Es imprescindible para el Proyecto que MQTT este disponible en el servicio, para ello se agrega la librería que
debe estar previamente instalada por npm.
Para realizar la conexión es necesario que sea un ID nuevo y por ello se utiliza una función para generar datos
aleatorios para generar un ID aleatorio.
Se establece un keepalive de cinco segundos, si durante este tiempo no se envia una señal de ping, se
desconectará del bróker. Una vez conectado se subscribirá a los topics donde publica el nodo central. Y a otros
topics que se usará para generar una espera.
En JavaScript, la ejecución no es totalmente secuencial, por tanto si puede realizar una tarea mientras espera
una respuesta la realiza. Esto conlleva a que mientras esta leiendo de la base de datos, ejecuta el resto del
Red de sensores para monitorización inteligente de vivienda 65
5.3.1.2 E-Mail
Una vez configurada con una cuenta de Gmail, único requisito de esta librería, se pueden enviar e-mails de la
siguente forma.
5.3.1.3 mySQL
Con esta librería se pueden realizar cualquier consulta en codigo mySQL, una vez realizada se ejecutará una
función definida por el programador.
5.4 Frontend
En esta sección se describen las diferentes interfaces con las se va a visualizar y gestionar los datos obtenidos
por los sensores. En la página web del proyecto hay tres secciones principales, un menú para acceder a las
secciones y un pie de página con el enlace a la web de la Escuela Técnica Superior de Ingenieros de la
Universidad de Sevilla. La primera sección muestra una pequeña introducción del proyecto, la segunda
muestra los datos de los sensores y la tercera información personal del autor del proyecto.
Para acceder a la información de la base de datos se usa la programación. Se utilizará un archivo escrito en
JavaScript con una llamada AJAX a los servicios PHP comentados en el apartado 5.1.2. Para realizar este tipo
de llamada es necesario el uso de jQuery, un framework de JavaScript que habilita la utilización de AJAX.
El uso de un framework CSS como boopstrap sirve para que la web se adapte a todo tipo de dispositivos. Este
ripo de páginas se denominan páginas web responsivas.
66 Desarrollo Software
5.4.1.1 Introducción
En ella se establecen tres textos, un breve resumen del proyecto, su funcionamiento y una descripción del
sistema de alarma, esta página es totalmente estática y no dispone de ningún enlace.
5.4.1.2 Sensores
En esta página se hará la llamada a SuperConsulta.php. Mostrará la información de los sensores de todos los
nodos y mostrará un enlace del histórico de los sensores en forma de gráfica. De la misma forma informará de
que personas están en la vivienda y si existe algún nodo o tarjeta RFID sin identificar. En tal caso se mostrará
un enlace al panel de administración. Se mostrará por pantalla la salida del servicio superconsulta pero con el
formato que se puede apreciar en la siguiente figura.
5.4.1.3 Acerca de
Se mostrarán los datos del autor, así como los datos del proyecto final de carrera. Tras esta información se
muesta el logo de la Escuela Superior de Ingenieros de la Universidad de Sevilla y del departamento de
Ingeniería Electrónica. Al igual que la sección de introducción es totalmente estática, aunque los logos serán
enlaces a las webs oficiales del organismo que representan.
Se trata de un DIV oculto en el que se mostrará la gráfica de histórico. Para acceder al contenido de este DIV
es necesario pulsar sobre el botón de Ver gráficas. Además de la gráfica, este DIV contiene un pequeño
formulario que permite ver los gráficos de los nodos de los sensores en la fecha que se desee.
5.4.1.5 CSS
CSS es un pseudo lenguaje para definir un diseño a una web ya maquetada. Las hojas de estilos CSS permiten
darle color y forma a los diferentes elementos que componen la pagina web. Para el desarrollo de la web se
optado por un color verde #4fab2f y negro.
La pagina web tiene un diseño basodo en tres cuerpos cada uno de ellos representa una sección diferente por lo
que tendrán un color de fondo propio cada una de estas secciones.
En cambio la web de administración, al estar formada por diversos div, se ha optado por hacer cuadrados con
esquinas redondeadas verdes sobre fondo negro.
68 Desarrollo Software
5.4.2 JavaScript
Existen dos códigos de javascript adicionales a los necesarios para poder trabajar con jQuery. Uno alojado en
un documento externo al index llamado javascript.js y otro llamado grafica.js.
5.4.2.1 javascript.js
Este código es el encargado de colocar dentro del div subdivdatos todo el contenido devuelto por el servicio
superConsulta.php. Se utilizará la función get() basada en AJAX para obtener estos datos. Para mostrarlo en el
div se utiliza la función getElementById(). Mientras se cargan los datos, se mostrará un mensaje que dice
"Cargando datos, por favor espere".
$.get("SuperConsulta.php",function(datos, status){
texto = datos;
document.getElementById("subdivdatos").innerHTML = texto;
});
Se llamará al servicio superConsulta.php cada diez segundos para mantener actualizados los datos alojados en
la base de datos y detectar los cambios de los mismos. Se utilizará la función SetInterval():
Es un pequeño código insertado en el propio index.html. Contiene la información para generar la gráfica del
histórico de los sensores seleccionando las fechas máximas y mínimas. Este formulario de selección está
incluido dentro del framework de jQuery User Interface (jQuery UI). Su función se puede ver en la figura 5-
12. En este archivo JS se puede iniciar la fecha actual con la clase date de JS. Con los métodos getDay(),
getMonth() y getFullYear(), se elige el día, el mes y el año en cuatro cifras respectivamente. Sin embargo con
Red de sensores para monitorización inteligente de vivienda 69
este método se obtiene únicamente la fecha actual, e interesa conseguir el día posterior. Por ello se utilizará
getDay()+1. De esta forma siempre se tendrá un día posterior, pese a que sea el 31 de Julio, la propia función
datepicker, al detectar 32 de Julio, actualizará la fecha a 1 de Agosto. De esta forma siempre se tendrá el día
posterior.
<script>
$(function() {
$( "#desde" ).datepicker();
$( "#hasta" ).datepicker();
$( "#desde" ).datepicker("option", "dateFormat", "yy-mm-dd");
$( "#hasta" ).datepicker("option", "dateFormat", "yy-mm-dd");
var f = new Date();
$('#desde').datepicker("setDate", new Date(f.getFullYear() ,
f.getMonth() , f.getDate()) );
$('#hasta').datepicker("setDate", new Date(f.getFullYear() ,
f.getMonth() , (f.getDate()+1)) );
});
</script>
El formato de la fecha es año, mes, día. La razón de esto es porque es la forma más cercana al TIMESTAMP,
donde se define una fecha de forma única como un entero, AAAAMMDDHHMMSS. AAAA es el año en
cuatro cifras, MM el mes en dos cifras, DD el dia, HH las horas, MM los minutos y SS los segundos. La
llamada se realizará con el año, mes y día elegidos seguidos de seis ceros para contar con todos los datos del
día elegido.
Desde: 20160624000000
Hasta: 20160624000000
Ofrecerá los datos desde el 24 de Junio de 2016 hasta 30 junio de 2016 a las 00:00:00 o lo que podría
traducirse como 29 de junio de 2016 en la práctica.
5.4.2.3 grafica.js
Este archivo contiene toda la programación necesaria para realizar las gráficas. Se utiliza un API de Google
para generar diferentes tipos de gráficas pasándole como parámetro un array en formato JSON. Tal como se
genera a la salida del servicio get_data.php, este se utilizará para obtener los datos que se desean mostrar en la
gráfica.
Antes de dibujar la gráfica será necesario especificar el sensor del nodo y el rango de fechas a mostrar. Para
seleccionarla se utiliza el script especificado en el apartado anterior. Aprovechando que todos los nodos tienen
los mismos sensores se pondrá un menú de selección desplegable con los sensores de temperatura, humedad,
luminosidad y presencia.
Como el número de sensores es variable, se requiere acceder a la base de datos para conocer que nodos están
disponibles con su correspondiente etiqueta. Esta información es generada por el servivio get_sensor.php.
La salida de este servicio es un JSON, por lo que hay que convertirlo en array y parsearlo para que desde el
menú desplegable se pueda seleccionar el nodo del sensor seleccionado.
function cargaHabitaciones(){
var url_data = "get_sensor.php";
Con toda esta información se tiene completado el formulario, se puede apreciar en la figura 5.12.
El botón cargar ejecuta los datos necesarios para generar la gráfica. En primer lugar llama al servicio
get_data.php para recibir los datos mostrados en la gráfica.
var url_data =
"get_data.php?MAC="+$("#habitacion").val()+"&SENSOR="+$("#sensor").val
()+"&FROM="+d+"&TO="+h;
Donde d y h son las conversiones de las fechas desde y hasta consecutivamente para que la entienda el
servicio php. Los datos recibidos hay que convertirlos en un array y pasárselo a la función dibujaGrafica()
como único parámetro.
Esta función llamará al servicio de google chart y con los parámetros especificados generará una gráfica de
histórico con los datos requeridos.
Se accede al popup para mostrar una gráfica. Para que no quede vacío en la primera visita se genera una con el
primer sensor del primer nodo detectado. Esto se realiza con la función cargaPrimeraVez(), la cual es llamada
cuando se abre la página.
72 Pruebas y validación
6 PRUEBAS Y VALIDACIÓN
na vez finalizado el desarrollo del sistema, este se somete a una serie de problemas que se llevan a
U cabo emulando todos los posibles casos de error. El objetivo es cuantificar la robustez del mismo y
demostrar que cumple los objetivos del proyecto, esperando que el sistema responda adecuadamente.
Es importante que cuando exista un problema con el router y este se apague o deje de dar señal WiFi por un
periodo limitado de tiempo, el nodo central pueda volver a conectarse. Para realizar esta comprobación se
apaga el router esperando una reconexión.
El bróker MQTT se sirve de conexiones ininterrumpidas, por lo tanto es necesario que exista una
comunicación de comprobación de conexión. Esta comprobación recibe el nombre “ping”, y tiene la misma
función que un ping de ethernet. Si durante un tiempo acordado entre el cliente y bróker no se recibe ninguna
trama de ping se corta la conexión. En ciertas ocaciones las tareas ejecutadas por arduino llevan un tiempo
superior al tiempo de desconexión o keep alive. Es por esta razón que es importante que exista una reconexión
al bróker antes de mandar cualquier trama. Esta se sirve de una comprobación del estado de la conexión y en el
caso que no esté conectado, realizará una conexión MQTT. Si esta conexión no es posible se comprobará que
existe conexión con el router. En el caso de que no exista no volverá a intentar una conexión al bróker hasta no
encontrar una conexión con el router. Para simular la pérdida de conexión con el bróker se desconecta la
raspberry de la red. Produciendo una caída del bróker.
Figura 6-4 – (A) Recepción de datos en el nodo central, (B) Envío de datos desde el nodo periférico
En primer lugar, se enciende el nodo central. Este nodo debe conectarse a la red y enviar los datos de lectura
de sus sensores mediante una publicación MQTT. El daemon debe leer la trama, meterla en la base de datos.
Al ser un nodo que no está registrado, el daemon enviará un e-mail al usuario que indicará que se ha agregado
un nuevo nodo al sistema. Desde la página web del sistema no se debe observar ningún dato hasta que sea
modificado el nombre en el panel de administración. Una vez cambiado el nombre se verán todos los datos
registrados con este módulo incluso si este ha sido borrado alguna vez. Para poder ver el historial completo del
sistema hay que pulsar sobre “ver gráficas” y seleccionar el nodo, el sensor y el rango de fechas que se desea
conocer, al pulsar sobre “Cargar” se podrán ver los datos del sensor a modo de gráfica.
Una vez puesto en marcha el nodo central, al no existir ninguna persona registrada mediante una tarjeta RFID,
no debe de empezar a sonar la alarma. Para que pueda activarse será necesario registrar una tarjeta RFID.
Pasándola sobre el lector RFID instalado en el nodo central, se registrará la tarjeta y se notificará por e-mail.
Se activa la tarjeta cambiando su nombre desde el panel de administración. Una vez activado, cada vez que se
pase la tarjeta por el lectro RFID avisará por e-mail si esa persona sale o entra de casa. Si por algún motivo
uno de usuarios olvida registrar una salida o entrada se producirá un desfase el cual puede ser arreglado en el
panel de control.
Cuando todos los usuarios registran una salida y no queda nadie en casa se arma la alarma, la cual empezará a
sonar si se detecta a alguien. Para evitar falsas alarma se esperará treinta segundos desde que se detecta una
presencia, si transcurrido este tiempo se sigue detectando la presencia se activará la alarma.
78 Pruebas y validación
Se van agregando nodos periféricos y se le van asignando nombres a cada uno de ellos, de esta forma se
comprueba que el sistema puede aceptar de forma automática tantos nodos como se necesiten hasta un
máximo de 254 nodos periféricos.
Red de sensores para monitorización inteligente de vivienda 79
80 Conclusiones y desarrollos futuros
urante el desarrollo el proyecto ha sufrido varias modificaciones desde la idea original. Al inicio
D consistía en una red de sensores completamente cerrada para una casa en concreto con tres nodos
periféricos (baño, cocina y dormitorio) y un nodo central (salón). Cuyo único cometido era las
lecturas de los sensores en una red tipo estrella, donde los nodos periféricos enviarían tramas con las lecturas
de los sensores de luminosidad, humedad y temperatura junto con una interfaz gráfica en Fi-Ware. Por el
cierre de las licencias gratuitas de servidores Fi-Ware se optó por diseñar una interfaz gráfica web para la
lectura de sensores por HTML y PHP. Tras la aceptación del proyecto por parte del tutor Antonio Luque, se
desarrolló una prueba de concepto donde se podían leer los datos de los sensores junto a un plano de la casa, y
junto a estos datos se mostraba las gráficas de histórico de los sensores.
Cuando se realizó y presentó la prueba de concepto a Antonio Luque, se plantearon tres mejoras del proyecto.
En primer lugar, se plantea que se tratase de una red de sensores abierta y que desde la interfaz web se
gestionase el nombre de estos dispositivos en función de la mac del módem de comunicación xBee. En
segundo lugar, la gestión de una alarma mediante sensores RFID en el nodo central para la gestión de las
entradas y salidas de la vivienda. Así como los sensores de presencia por infrarrojos (PIR) en todos los nodos
de la red. Y como tercera y última mejora se encuentra la posibilidad de modificar el rango temporal de las
gráficas.
La primera mejora estaba ideada para que el nodo central reconociera de forma automática a los nodos
periféricos, y estos reconocieran de la misma forma al nodo central. Por el diseño de la librería no es factible
cambiar la dirección de envío de las tramas de los nodos periféricos, ya que esto desconfiguraría otros
parámetros de la red impidiendo realizar la conexión. El nodo central si es capaz de averiguar cual es el nodo
emisor, de tal forma que se puede obtener la mac del módem como identificador único del nodo periférico.
La segunda mejora se realiza mediante la lectura de los identificadores de la tarjeta RFID, pudiéndose
identificar también de forma única. Se pensaba utilizar algunos espacios de su memoria para la comprobación
de que es una tarjeta real y no copiada. Finalmente se prefiere no utilizar esta opción, ya que si el suplantador
de identidad entra antes que el usuario real podría generar problemas de accesos. En lugar de ello se decidió
utilizar un servicio de e-mail que avisará a tiempo real de quien entra y quien sale de casa. Aprovechando este
servicio se ofrece también el envío de avisos de la alarma, así como de detección de nuevos sensores o nuevas
tarjetas RFID.
Para realizar la selección de la fecha sobre la gráfica, se ha optado por generar un JSON en el servicio PHP.
Debido a que realizar una llamada a un servicio PHP de forma recurrente desde un javascript era poco
eficiente y generaba una serie de errores. Con el uso de JSON se dibuja la gráfica mediante un pop-up interno
en el HTML. Durante el desarrollo de las gráficas Google restringió estas a solo una por página. Por lo que se
Red de sensores para monitorización inteligente de vivienda 81
decidió que desde el mismo pop-up se pudiera ver una gráfica seleccionando un nodo, un sensor y un rango de
fechas.
7.1.1 GSM
Esta sería la actualización más importante. Este sistema ha sido diseñado mediante un módulo WiFi para que
cumpliera los objetivos al menor coste de mantenimiento. Si se desea mayor funcionalidad un sistema con
conexión GSM y gestión de batería permitiría informar si se ha desconectado la corriente eléctrica entre otras
muchas posibilidades.
7.1.2 Actuación
Actuar con elementos de climatización o de iluminación del hogar combinan bien con los sensores instalados
en los diferentes nodos, esto proporcionaría un valor añadido que beneficia al usuario permitiendo gestionar su
estado de bienestar de forma automática.
8 REFERENCIAS BIBLIOGRÁFICAS
[1] Isabel Yanez. “La domótica, un bien para todos”. Revista digital - Innovación y Experiencias Educativas,
Nº30, Mayo 2010.
[2] David A. Wheeler, “Why Open-source Software/ Free Software (OSS/FS, FLOSS, or FOSS)?Look at the
Numbres!” July 18,2015 [online] Disponible en: http://www.dwheeler.com/oss_fs_why.html
[3] Iván González, Juan González, Francisco Gómez-Arribas. ”Hardware libre: Clasificación y desarrollo de
hardware reconfigurable en entornos GNU/Linuz", 06 de Septiembre de 2016 [online] Disponible en:
http://es.tldp.org/Presentaciones/200309hispalinux/8/8.pdf
[4] Sección “About Us” página web www.arduino.cc [online] Disponible en:
https://www.arduino.cc/en/Main/AboutUs
[5] Massimo Banzi. ”Fighting for Arduino”. Make Magazine (Makezine). March 19, 2015 [online] Disponible
en: http://makezine.com/2015/03/19/massimo-banzi-fighting-for-arduino/
[6] Sección “Older Boards” página web www.arduino.cc [online] Disponible en:
https://www.arduino.cc/en/Main/Boards
[7] Sección “Arduino UNO” página web www.arduino.cc [online] Disponible en:
https://www.arduino.cc/en/Main/ArduinoBoardUno
[8] Datasheet Atmel ATmega48A/PA/88A/PA/168A/PA/328/P
[9] Sección “Products” página web www.arduino.cc [online] Disponible en:
https://www.arduino.cc/en/Main/Products
[10] Sección “Arduino Leonardo” página web www.arduino.org [online] Disponible en:
http://www.arduino.org/products/boards/arduino-leonardo
[11] Datasheet Atmel ATmega16U4/ATmega32U4
[12] Sección “Arduino Mega” página web www.arduino.cc [online] Disponible en:
https://www.arduino.cc/en/Main/ArduinoBoardMega2560
[13] Datasheet Atmel ATmega640/V-1280/V-1281/V-2560/V-2561/V
[14] Sección “Arduino Pro” página web www.arduino.cc [online] Disponible en:
https://www.arduino.cc/en/Main/ArduinoBoardPro
[15] Sección “Arduino Pro Mini” página web www.arduino.cc [online] Disponible en:
https://www.arduino.cc/en/Main/ArduinoBoardProMini
[16] Sección “Arduino Nano” página web www.arduino.cc [online] Disponible en:
https://www.arduino.cc/en/Main/ArduinoBoardNano
[17] Sección “Arduino Micro” página web www.arduino.cc [online] Disponible en:
https://www.arduino.cc/en/Main/ArduinoBoardMicro
[18] Sección “Arduino Fio” página web www.arduino.cc [online] Disponible en:
https://www.arduino.cc/en/Main/ArduinoBoardFio
[19] Sección “Arduino Due” página web www.arduino.org [online] Disponible en:
http://www.arduino.org/products/boards/arduino-due
[20] Datasheet Atmel SAM3X / SAM3A Series
Red de sensores para monitorización inteligente de vivienda 83
[21] Sección “Arduino Zero” página web www.arduino.cc [online] Disponible en:
https://www.arduino.cc/en/Main/ArduinoBoardZero
[22] Sección “Arduino M0 Pro” página web www.arduino.org [online] Disponible en:
http://www.arduino.org/products/boards/arduino-M0-pro
[23] Sección “Arduino M0” página web www.arduino.org [online] Disponible en:
http://www.arduino.org/products/boards/arduino-M0
[24] Sección “Arduino 101” página web www.arduino.cc [online] Disponible en:
https://www.arduino.cc/en/Main/Arduino101
[25] Sección “Arduino MKR1000” página web www.arduino.cc [online] Disponible en:
https://www.arduino.cc/en/Main/ArduinoMKR1000
[26] Sección “Arduino Yún” página web www.arduino.org [online] Disponible en:
http://www.arduino.org/products/boards/arduino-yun
[27] Sección “Arduino Tian” página web www.arduino.org [online] Disponible en:
http://www.arduino.org/products/boards/arduino-tian
[28] Sección “Arduino Industrial 101” página web www.arduino.org [online] Disponible en:
http://www.arduino.org/products/boards/arduino-industrial-101
[29] Matt Sarnoff. ”Why I‟m Excited That Microchip Is Buying Atmel”. Make Magazine (Makezine), January
25, 2016 [online] Disponible en: http://makezine.com/2016/01/25/why-im-excited-that-microchip-is-buying-
Atmel/
[30] Seccion “Pinguino” pagina web www.hackinlab.org, creadores de arduino [online] Disponible en:
http://www.hackinglab.org/pinguino/index_pinguino.html
[31] Sección “UNO32” página web www.chipkit.net [online] Disponible en:
http://chipkit.net/wpcproduct/chipkit-uno32/
[32] Sección “MAX32” página web www.chipkit.net [online] Disponible en:
http://chipkit.net/wpcproduct/chipkit-max32/
[33] Sección “waspmote” página web www.libelium.com [online] Disponible en:
http://www.libelium.com/products/waspmote/
[34] Pagina web www.energia.nu [online]
[35] Sección “launchpad” página web www.ti.com [online] Disponible en:
http://www.ti.com/ww/en/launchpad/launchpad.html?DCMP=mcu-launchpad&HQS=launchpad
[36] IEEE Std 802.11, 2012
[37] IEEE Std 802.15.1 , 2005
[38] Sección “Basic Rate/Enhanced Data Rate” página web www.bluetooth.com [online] Disponible en:
https://www.bluetooth.com/what-is-bluetooth-technology/bluetooth-technology-basics/br-edr
[39] Sección “Bluetooth High Speed” página web www.bluetooth.com [online] Disponible en:
https://www.bluetooth.com/what-is-bluetooth-technology/bluetooth-technology-basics/bluetooth-high-speed
[40] Sección “Bluetooth Low Energy” página web www.bluetooth.com [online] Disponible en:
https://www.bluetooth.com/what-is-bluetooth-technology/bluetooth-technology-basics/low-energy
[41] IEEE Std 802.15.4, 2003
[42] Seccion “xBee” página web www.digi.com [online] Disponible en: http://www.digi.com/lp/xbee
[43] Seccion “xBee” página web www.digi.com [online] Disponible en: http://www.digi.com/products/xbee-
rf-solutions/modules/xbee-802-15-4
[44] Seccion “ZigBee” página web www.digi.com [online] Disponible en:
http://www.digi.com/products/xbee-rf-solutions/rf-modules/xbee-zigbee
84 Referencias bibliográficas
[45] Antonio Perez Yuste. "El proceso de implantación de la telefonía móvil en España". Revista Antena del
COITT. Septiembre 2002.
[46] Sección “about” página web www.sigfox.com [online] Disponible en: http://makers.sigfox.com/#about
[47] Telit LE51 868S RF Module User Guide Rev.1, 2014
[48] "La mayoría de los operadores móviles fijan el fin de las redes GSM en 2017", Revista PCworld España,
Junio 2015 [online] disponible en: http://www.pcworld.es/movilidad/la-mayoria-de-los-operadores-moviles-fijan-el-
fin-de-las-redes-gsm-en-2017
[49] Sección “About” página web www.nodejs.org [online] Disponible en: https://nodejs.org/es/about/
[50] Sección “Upgrading the WiFi shield firmware” pagina web www.arduino.cc [online] Disponible en:
https://www.arduino.cc/en/Hacking/WiFiShieldFirmwareUpgrading
Red de sensores para monitorización inteligente de vivienda 85
86 Anexos
9 ANEXOS
9.1 Anexo I - Código del nodo central
/******************************************************************
Nodo central:
El nodo central es el encargado en primer lugar de comunicar
la red de sensores con la nube. En segunda instancia se encarga
del sistema de alarma. Si estando el sistema de alarma activo
se detecta una persona sin autentificacion RFID, la alarma
sonará e informará al inquilino/propietario. En último lugar,
al igual que el resto de nodos, se encargara tambien de las
mediciones de Luz, Humedad, Temperatura y Presencia.
El nodo consta:
Arduino Uno
Shield WiFi
Shield xBee
Módulo xBee Serie 2 (ZigBee)
Módulo RFID-RC522
Sensor PIR
Sensor DHT11
LDR
Módulo Relé
******************************************************************/
//librerias externas
#include <XBee.h>
#include <PubSubClient.h>
#include <dht11.h>
#include <MFRC522.h>
float luminosidad;
// Variable donde se almacena la luminosidad leída
boolean presencia;
// Variable donde se almacena la presencia leída
//Datos de conexion
char ssid[] = "JAVIER";
// SSID de la red a conectar.
char pass[] = "password";
// Password de la red a conectar
char tramaGet[100];
// Array de caracteres donde almacenar la trama recibida
char MAC[10];
// Array de caracteres donde almacenar la MAC del emisor
//variable de estado:
int status = WL_IDLE_STATUS;
// Varlor de estado de la Shield WiFi
//declaración de funciones:
char texto[55] ;
// Array donde almacenar la trama a enviar por WiFi
//Otras variables
boolean Alarma = false;
// Bandera que activa la Alarma
boolean Tpresente = false;
// Bandara que avisa de que existe una tarjeta presente
boolean primero = false;
// Bandera que avisa si se ha enviado la primera trama MQTT
int cuentaIntentos = 0;
// Variable que cuenta los intentos de reconexión
/*
* Función que se ejecuta una sola vez al iniciar la ejecución del programa
o tras un reset
*/
void setup() {
//Inicializamos el puerto Serie a 115200 ya que es el BaudRate configurado
con los xBee.
Serial.begin(115200);
//Inicializamos el xBee
Red de sensores para monitorización inteligente de vivienda 89
xbee.begin(Serial);
//Inicializamos el RFID
SPI.begin();
mfrc522.PCD_Init();
/*
* Función principal, se ejecuta en bucle
*/
void loop() {
//Se realiza una lectura de los sensores
lectura();
//Se comprueba el estado de la conexión MQTT
if (!clientmqtt.connected()) {
//Si está desconectado, intentamos reconectarlo.
Serial.println(clientmqtt.state());
Serial.println("desconectado");
char clientID_buffer[22];
//Se genera un ID aleatorio para el servidor MQTT
for (int i = 0; i < 22; i++)
clientID_buffer[i] = random('a', 'z');
//Se realiza la conexión MQTT
if (clientmqtt.connect(clientID_buffer, MQTT_USER, MQTT_PASS,
"pfc/estado", 0, 1, "0")) {
//Se subscribe a la alarma y se publica un estado ON.
clientmqtt.publish("pfc/estado", (uint8_t*)"on", strlen("on"), true);
clientmqtt.subscribe("pfc/alarma");
Serial.println("Se ha conectado al broker");
cuentaIntentos = 0;
//Se comprueba si es la primera conexión de ser así se envía una
lectura
if (primero) {
creaTrama();
Serial.println(texto);
clientmqtt.publish("pfc/lectura", (uint8_t*)texto, strlen(texto),
true);
tantiguo = millis();
primero = false;
}
} else {
Serial.println("No se pudo conectar al broker");
//Si no puede conectarse, lo intentará nuevamente en la prózima
iteración
delay(6000);
//Si fallan 10 intentos se reinicia la placa
if (cuentaIntentos++ > 10) {
softReset();
}
//Se imprime el buffer del modem
while (client.available()) {
char c = client.read();
Serial.write(c);
}
//Se comprueba el estado de la conexión
status = WiFi.status();
while ( status != WL_CONNECTED ) {
// Serial.print/println solo activo para debugear el programa
Serial.println("Reiniciando conexion a la red");
//Realizamos la conexion mediante el siguiente comando:
90 Anexos
conectarRed();
}
}
} else {
//Si esta conectado comprueba si ha recibido algún paquete xBee
if (leeXBee()) {
Serial.println("Paquete Recibido:");
Serial.println(Trama);
//Monta la trama con la MAC
montaTrama();
Serial.println(tramaGet);
//Publica la trama por MQTT
clientmqtt.publish("pfc/lectura", (uint8_t*)tramaGet,
strlen(tramaGet), true);
Serial.println("ok");
}
//Realiza una lectura de los sensores
lectura();
tactual = millis();
//Se comprueba si millis() ha desbordado
if (tactual < tantiguo) {
tantiguo = tactual;
creaTrama();
Serial.println(texto);
/Se publica la trama
clientmqtt.publish("pfc/lectura", (uint8_t*)texto, strlen(texto),
true);
}
//Se comprueba si tiene que volver a mandar una trama por MQTT
if ( (tactual - tantiguo >= 900000) || (Alarma && (tactual - tantiguo >=
60000)) ) {
tantiguo = tactual;
creaTrama();
Serial.println(texto);
//Se publica la trama
clientmqtt.publish("pfc/lectura", (uint8_t*)texto, strlen(texto),
true);
}
}
/*
* Se comprueba si hay una tarjeta en el sensor RFID
*/
if ( mfrc522.PICC_IsNewCardPresent() && !Tpresente) {
IDcard = 0;
char RFID_ID[10];
if ( mfrc522.PICC_ReadCardSerial()) {
for (byte i = 0; i < mfrc522.uid.size; i++) {
RFID_ID[i] = (char) mfrc522.uid.uidByte[i];
IDcard += RFID_ID[i] * pow(10, (mfrc522.uid.size - i - 1));
}
Serial.println(IDcard);
long2Char(IDcard, RFID_ID);
Serial.println(RFID_ID);
clientmqtt.publish("pfc/rfid", (uint8_t*)RFID_ID, strlen(RFID_ID),
true);
Tpresente = true;
}
}
No aceptara una nueva tarjeta hasta que no se retire la anterior
if (!mfrc522.PICC_IsNewCardPresent() && Tpresente) {
return;
Red de sensores para monitorización inteligente de vivienda 91
} else {
Tpresente = false;
}
//Se realiza un ping al broker MQTT
clientmqtt.loop();
if (Alarma) {
suenaAlarma();
}
}
/*
Esta función es obligatoria para poder utilizar la librería MQTT. Esta
función permite trabajar con los datos recibidos de una subscripcción MQTT.
Para saber que hacer con el mensaje es necesrio comprobar el topic.
Una vez comprobado el Topic se realiza la tarea indicada.
*/
void callback(char* topic, byte* payload, unsigned int length) {
//Se copia la trama recibida en una variable local
char recibido[128];
int i = 0;
for (i = 0; i < length; i++) {
recibido[i] = payload[i];
}
delay(1000);
//Se reseteará sola para comprobar si se ha instalado.
softReset();
}
/*
* Se genera la trama, en este caso es necesario incluir el valor LSB de la
MAC
*/
void creaTrama() {
//definimos las variables que vamos a utilizar y las inicializamos
int trama = 0;
int auxtrama = 0;
uint8_t tam;
uint8_t ASCII = B10000000;
char datos[4] = {0, 0, 0, 0};
char pir[]="PIR";
char tem[]="TEM";
char hum[]="HUM";
char luz[]="LUZ";
char mac[]="MAC=1085975315&";
uint8_t i = 0;
uint8_t j = 0;
//borrado de trama.
texto[j++] = '&';
texto[j++] = '&';
texto[j++] = '&';
else
texto[j++]='0';
texto[j] = 0x00;
/*
* Función que realiza la lectura de los sensores
*/
void lectura() {
int chk = DHT11.read(2);
humedad = DHT11.humidity;
temperatura = DHT11.temperature;
presencia = 0;
if (digitalRead(5)) {
presencia = 5;
}
luminosidad = analogRead(A0);
}
/*
* Se ejecuta la funcion lee xBee para leer, en el caso de que halla alguna
trama
* Devuelve como resultado el tamaño de la trama. Quedandose almacenada la
trama en
* la variable vacía Trama
*/
int leeXBee() {
//Leemos el Paquete
int existe=0;
xbee.readPacket();
RxFlag=0;
if (xbee.getResponse().getApiId() == ZB_RX_RESPONSE) {
xbee.getResponse().getZBRxResponse(rx);
RxFlag=1;
SendFlag=1;
}
if (SendFlag==1){
if(RxFlag=0){
Serial.println("Paquete Recibido");
tam=rx.getDataLength();
//Serial.println(tam);
for(int aux=0;aux<55;aux++){
Trama[aux]=(char)rx.getData(aux);
}
macLsb = rx.getRemoteAddress64().getLsb();
Serial.println(macLsb);
for(int aux=0;aux<10;aux++){
MAC[aux]=0x00;
}
long2Char(macLsb, MAC);
Serial.write(MAC);
Serial.println();
SendFlag=0;
existe=1;
}
}
return existe;
}
96 Anexos
/*
* La funcion montaTrama, genera una trama para poder hacer la llamada al
* webservice, que introducirá los datos en una base de datos.
*/
void montaTrama(){
char cabecera[]="MAC=";
int i = 0;
int j = 0;
//Borramos la trama.
for (i = 0; i < 100; i++) {
tramaGet[i] = 0x00;
}
for(i = 0 ; i < 4 ; i++,j++){
tramaGet[j] = cabecera[i];
}
for(i = 0; i<10; i++ , j++){
tramaGet[j] = MAC[9-i];
}
tramaGet[j++] = '&';
for(i = 0 ; Trama[i] != 0x00 ; i++,j++){
tramaGet[j] = Trama[i];
}
}
/*
Variable que pasa una variable del tipo long a una cadena de caracteres.
Tiene dos parametros, el primero es la variable, y el segundo
es la dirección de la cadenna donde se quiere almacenar.
*/
void long2Char(unsigned long int largo, char * caracter) {
int subvalor = 0;
while (largo >= 1000000000) {
largo -= 1000000000;
subvalor++;
}
if (subvalor) {
caracter[9] = subvalor + '0';
} else {
caracter[9] = '\0';
}
subvalor = 0;
while (largo >= 100000000) {
largo -= 100000000;
subvalor++;
}
if (subvalor == 0 && caracter[9] == '\0') {
caracter[8] = '\0';
} else {
caracter[8] = subvalor + '0';
}
subvalor = 0;
while (largo >= 10000000) {
largo -= 10000000;
subvalor++;
}
if (subvalor == 0 && caracter[8] == '\0') {
caracter[7] = '\0';
} else {
caracter[7] = subvalor + '0';
}
Red de sensores para monitorización inteligente de vivienda 97
subvalor = 0;
while (largo >= 1000000) {
largo -= 1000000;
subvalor++;
}
if (subvalor == 0 && caracter[7] == '\0') {
caracter[6] = '\0';
} else {
caracter[6] = subvalor + '0';
}
subvalor = 0;
while (largo >= 100000) {
largo -= 100000;
subvalor++;
}
if (subvalor == 0 && caracter[6] == '\0') {
caracter[5] = '\0';
} else {
caracter[5] = subvalor + '0';
}
subvalor = 0;
while (largo >= 10000) {
largo -= 10000;
subvalor++;
}
if (subvalor == 0 && caracter[5] == '\0') {
caracter[4] = '\0';
} else {
caracter[4] = subvalor + '0';
}
subvalor = 0;
while (largo >= 1000) {
largo -= 1000;
subvalor++;
}
if (subvalor == 0 && caracter[4] == '\0') {
caracter[3] = '\0';
} else {
caracter[3] = subvalor + '0';
}
subvalor = 0;
while (largo >= 100) {
largo -= 100;
subvalor++;
}
if (subvalor == 0 && caracter[3] == '\0') {
caracter[2] = '\0';
} else {
caracter[2] = subvalor + '0';
}
subvalor = 0;
while (largo >= 10) {
largo -= 10;
subvalor++;
}
if (subvalor == 0 && caracter[2] == '\0') {
caracter[1] = '\0';
} else {
caracter[1] = subvalor + '0';
}
subvalor = 0;
while (largo >= 1) {
largo -= 1;
98 Anexos
subvalor++;
}
if (subvalor == 0 && caracter[1] == '\0') {
caracter[0] = '\0';
} else {
caracter[0] = subvalor + '0';
}
}
/*
Función que realiza un reset software. El programa empieza desde cero, pero
no resetea ni los perifericos ni los registros
*/
void softReset()
{
asm volatile (" jmp 0");
}
Red de sensores para monitorización inteligente de vivienda 99
100 Anexos
//Librerías externas
#include <XBee.h>
#include <dht11.h>
//Variables a modificar
int minutos = 30; // Minutos
entre envíos
int horas = 1; // Horas
entre envíos
boolean repetirPIR = false; // Bandera
para repetir lectura
boolean ultimaLectura =false; // Bandera
de presencia
//Variables
Red de sensores para monitorización inteligente de vivienda 101
/*
* Función setup, solo se ejecuta una vez al inicio de la ejecución del
programa
*/
void setup() {
//Se configura el PIN del DTR como salida
pinMode(DTR,OUTPUT);
//Iniciamos el puerto serie al BR del xBee
Serial.begin(115200);
//Inicializamos el xBee.
xbee.setSerial(Serial);
//Comando de prueba
Serial.println("Activo");
//Esperamos a que se inicialize la comunicación del xBee en su PAN ID.
delay(5000);
//Iniciamos el contador de errores.
errores=0;
//Encendemos el temporizador del wdt
watchDogOn();
//Para comprobar reinicios.
tiempo= millis();
}
/*
* Función que se ejecuta en bucle constantemente cuando el dispositivo
* está funcionando.
*/
void loop() {
WDTCSR=0x00; //desactivo el wdt
// Cada 25 ciclos del watchdog se envía un dato a pantalla para saber
// si se ha quedado bloqueado
if(contador == cuenta){
Serial.println(contador);
delay(1);
cuenta = contador-25;
}
//Comprobamos si hay que volver a dormir el dispositivo
if (contador > 1) {
WDTCSR=0x71; //activo el wdt
102 Anexos
duerme();
} else {
//Si no hay que dormirlo, se despierta con el DTR
digitalWrite(DTR,LOW);
delay(100);
//Reenvía la ultima trama, no debe de llegar
xbee.send(zbTx);
//Se espera suficiente tiempo para despertar el xBee
delay(30000);
//Se realiza una lectura de los sensores
lectura();
//Se crea la trama a enviar
CreaTrama();
//Se env´ia la trama que s´i debe de llegar
xbee.send(zbTx);
delay(500);
char tem[]="TEM";
char hum[]="HUM";
char luz[]="LUZ";
//variables auxiliares
uint8_t i = 0;
uint8_t j = 0;
//borrado de trama.
texto[j++] = '&';
auxtrama = 1;
}
if (trama >= 10 || auxtrama == 1) {
texto[j] = 0x30;
while (trama >= 10) {
texto[j] += 1;
trama -= 10;
}
j++;
auxtrama = 1;
}
texto[j] = 0x30;
while (trama >= 1) {
texto[j] += 1;
trama -= 1;
}
j++;
auxtrama = 0;
texto[j++] = '&';
auxtrama = 0;
texto[j++] = '&';
texto[j] = 0x00;
}
/*
* Función que permite que el dispositivo entre en modo de ahorro
* de energía.
*/
void duerme() {
//Se pone el dispositivo a dormir
digitalWrite(DTR,HIGH);
//Se establece el modo ahorro de energía que nos interese
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable(); //lo ponemos para que pueda dormir
//apagamos todos los modulos
PRR=B11111111;
power_timer0_disable();
power_timer1_disable();
power_timer2_disable();
power_adc_disable();
power_twi_disable();
power_spi_disable();
//duerme
sleep_mode();
//------->despierta Se encienden todos los modulos
PRR=B00000000;
power_all_enable();
sleep_disable();
}
/*
* Función que se ejecuta al desbordar el watchdog, comprueba
* si hay alguna presencia nueva para alarmar al nodo central
*/
ISR(WDT_vect)
{
contador--;
if (digitalRead(4) && !ultimaLectura) {
contador = 0;
}
}
/*
* Función donde se realizan las lecturas de los sensores
*/
void lectura() {
// Se comprueba si existe el sensor DHT11 asociado al pin 4
int chk = DHT11.read(4);
106 Anexos
if (!chk) {
// Si existe se almacenan los datos de tempereratura y humedad
humedad = DHT11.humidity;
temperatura = DHT11.temperature;
}
// Se comprueba si existe presencia
presencia = 0;
if (digitalRead(2)) {
presencia = 5;
}
// Se lee el valor de luminosidad
luminosidad = analogRead(A0);
// Se establece el valor de presencia como última lectura
ultimaLectura = presencia;
}
/*
* Función para hacer un reset software
*/
void softReset()
{
asm volatile (" jmp 0");
}
/*
* Sirve para configurar y activar el watchdog
*/
void watchDogOn(){
// Borra la marca de reinicio, el bit WDRF (bit 3) de MCUSR
MCUSR = MCUSR & B11110111;
/*
Coloca el bit WDCE (bit 4) y el bit WDE bit (bit 3)
de WDTCSR. El bit WDCE debe ser colocado en orden a
a cambiar WDE o los preescaladores del watchdog. Configurando el
bit WDCE permitirá actualizar a los preescaladores y
WDE para 4 ciclos de reloj, luego será reiniciado por hardware.
*/
WDTCSR = WDTCSR | B00011000;
// Establce el preescalador de tiempo de espera de vigilancia a un valor
de 1024k
// el cual rentabilizará el intervalo de tiempo de espera sobre los
8seg.
WDTCSR = B00100001;
// Activa la interrupción por temporizador.
WDTCSR = WDTCSR | B01000000;
MCUSR = MCUSR & B11110111;
}
Red de sensores para monitorización inteligente de vivienda 107
108 Anexos
/*
Definimos el usuario, contraseña y servidor de correos de la cuenta que
vamos a utilizar para mandar el e-mail.
*/
var transporter =
nodemailer.createTransport('smtps://j.arcenegui.pfc%40gmail.com:password@smtp
.gmail.com');
/*
Genera un valor aleatorio. Sera utilizado para generar una palabra aleatoria
como usuario
que servira para subscribirse al broker de MQTT.
*/
var rand = function(){
return Math.random().toString(36).substr(2);
}
/*
Genera la palabra aleatoria basandose en la funcion rand();
*/
var token = function() {
return rand() + rand();
};
/*
Pasa la palabra generada de forma aleatoria a String para convertirlo en una
palabra
lejible para el broker
*/
var client_ID = token().toString();
/*
Se hace la conexion al MQTT , como primer objeto le pasamos la direccion del
broker con
su puerto. El usuario y el password que se necesita en el broker para su
conexion. El
identificador del cliente (el cual hemos generados de forma aleatoria). Y
por ultimo
el keepalive.
*/
client = mqtt.connect("mqtt://127.0.0.1:1883", {username: "admin",
password: "123456jaa", clientId: client_ID, keepalive: 5});
/*
Nos subscribimos a todos los topics necesarios.
*/
Red de sensores para monitorización inteligente de vivienda 109
client.on('connect', function () {
client.subscribe("pfc/lectura");
client.subscribe("pfc/rfid");
client.subscribe("pfc/rfidFB");
client.subscribe("pfc/macFB");
client.subscribe("pfc/alarma");
});
/*
Por cada mensaje que llege lo vamos a ir parseando
*/
client.on('message', function (topic, message) {
// message is Buffer
console.log(message.toString());
/*
Implementamos una variable que servira para registrar la conexion mySQL, en
principio no
vamos a estar constantemente conectado, tan solo cuando una trama
*/
/*
Realizamos la conexion a la base de datos, es necesario tener el paquete
mysql instalado y requerido para ello. Si la conexion se puede realizar se
ejecuta
el parseado de los elementos, en caso contrario, dara un mensaje de error
*/
connection.connect(function(error){
if(error){
/*
Al no haberse podido conectar enviara un mensaje de error
*/
console.log("error de conexion");
throw error;
}else{
/*
Se comprueba que si se ha recibido una lectura o una identificación
*/
var array = topic.split('/');
console.log(array[1]);
if(array[1] == "lectura"){
console.log("Se ha recibido una lectura");
var array2 = message.toString().split('&');
var array3 = array2[0].split('=');
if (array3[0] == "MAC"){
var MAC = array3[1];
for(i = 1 ; i < array2.length ; i++){
var array3 = array2[i].split('=');
var query = connection.query('INSERT INTO Sensores(mac, sensor, valor)
VALUES(?, ?, ?)' , [ MAC , array3[0] , array3[1] ], function(error, result){
if(error){
/*
Al no haberse podido conectar enviara un mensaje de error
*/
console.log("error de insercion");
throw error;
}else{
110 Anexos
console.log("ok");
}
});
if(array3[0] == 'PIR' && array3[1] == '1'){
console.log(array3[1]);
var query = connection.query("SELECT * FROM Alarma WHERE Armado = 1",
function(error, result){
if(error){
/*
Al no haberse podido conectar enviara un mensaje de error
*/
console.log("error de petición");
throw error;
}else{
resultado = result;
if(resultado.length > 0){
if(resultado[0].Sonando){
}else {
client.publish('pfc/alarma',"Sonar");
}
}
}
});
}
}
console.log("mac:"+MAC);
var query = connection.query("SELECT * FROM Registro WHERE mac = "+MAC,
function(error, result){
if(error){
/*
Al no haberse podido conectar enviara un mensaje de error
*/
console.log("error de petición");
throw error;
}else{
resultado = result;
if(resultado.length > 0){
console.log(resultado.length);
}else{
client.publish('pfc/macFB',"ID:"+ MAC + '&NAME:SinAsignar');
}
}
});
}
}else if(array[1] == "rfid"){
console.log("Se ha recibido una identificacion");
var array2 = message.toString()
console.log(array2);
var query = connection.query("SELECT * FROM rfid WHERE ID = "+array2,
function(error, result){
if(error){
/*
Al no haberse podido conectar enviara un mensaje de error
*/
console.log("error de peticion");
throw error;
}else{
resultado = result;
if(resultado.length > 0){
var estado = resultado[0].encasa;
var nombre = resultado[0].usuario;
Red de sensores para monitorización inteligente de vivienda 111
text: 'Se ha registrado un nuevo usuario con ID: ' +RFID_ID + '.
Puede asignarle un nombre de usuario en el panel de administración para que
el usuario pueda registrarse en casa.', // plaintext body
html: '<H3>Se ha registrado un nuevo usuario con ID: ' + RFID_ID
+ '</H3> <p>Puede asignarle un nombre de usuario en el <a
href="www.ardugeek.es/pfc">panel de administración</a> para que el usuario
pueda registrarse en casa.</p> ' // html body
};
transporter.sendMail(mailOptions, function(error, info){
if(error){
return console.log(error);
}
console.log('Message sent: ' + info.response);
});
}
});
}
}else{
array3 = array2[2].split(':');
if(array3[0] == 'STT'){
if(array3[1] == '0'){
var query = connection.query('UPDATE rfid SET encasa = 1 WHERE id
=' + RFID_ID, function(error, result){
if(error){
/*
Al no haberse podido conectar enviara un mensaje de error
*/
console.log("error de insercion");
throw error;
}else{
console.log("Usuario registrado");
/*
Se ha escrito los datos en la base de datos, vamos a mandar la
confirmación por e-mail
*/
var mailOptions = {
from: '"Casa Domotica" <j.arcenegui.pfc@gmail.com>', // sender
address
to: 'j.arcenegui@gmail.com', // list of receivers
subject: NAME_R + ' se ha registrado en casa', // Subject line
text: NAME_R + ' se ha registrado en casa, si el usuario ha
salido de casa corríjalo en el panel de administración', // plaintext body
html: '<H3>' + NAME_R + ' se ha registrado en casa</H3> <p> Si
el usuario ha salido de casa, por favor, corríjalo en el <a
href="www.ardugeek.es/pfc">panel de administración</a></p> ' // html body
};
transporter.sendMail(mailOptions, function(error, info){
if(error){
return console.log(error);
}
console.log('Message sent: ' + info.response);
});
}
});
client.publish('pfc/alarma',"OFF");
var query = connection.query('UPDATE Alarma SET Armado = 0 ,
Activado = 0 , Sonando = 0 WHERE Alarma = Alarma', function(error, result){
if(error){
/*
Al no haberse podido conectar enviara un mensaje de error
*/
console.log("error de insercion");
Red de sensores para monitorización inteligente de vivienda 113
throw error;
}else{
console.log("Alarma Desarmada y a apagada");
}
});
}else if(array3[1] == '1'){
var query = connection.query('UPDATE rfid SET encasa = 0 WHERE id
=' + RFID_ID, function(error, result){
if(error){
/*
Al no haberse podido conectar enviara un mensaje de error
*/
console.log("error de insercion");
throw error;
}else{
console.log("Usuario registrado");
/*
Se ha escrito los datos en la base de datos, vamos a mandar la
confirmación por e-mail
*/
var mailOptions = {
from: '"Casa Domotica" <j.arcenegui.pfc@gmail.com>', // sender
address
to: 'j.arcenegui@gmail.com', // list of receivers
subject: NAME_R + ' ha salido de casa', // Subject line
text: NAME_R + ' ha salido de casa, si el usuario se ha
registrado en casa corríjalo en el panel de administración', // plaintext
body
html: '<H3>' + NAME_R + ' ha salido de casa</H3> <p> Si el
usuario e ha registrado en casa, por favor, corríjalo en el <a
href="www.ardugeek.es/pfc">panel de administración</a></p> ' // html body
};
transporter.sendMail(mailOptions, function(error, info){
if(error){
return console.log(error);
}else{
console.log('Message sent: ' + info.response);
}
});
}
});
var query = connection.query("SELECT * FROM rfid WHERE encasa =
1", function(error, result){
if(error){
/*
Al no haberse podido conectar enviara un mensaje de error
*/
console.log("error de petición");
throw error;
}else{
resultado = result;
if(resultado.length == 0){
client.publish('pfc/alarma',"Armar");
}
}
});
}else {
console.log(array3[1]);
}
}
}
}
}
114 Anexos
if(error){
return console.log(error);
}
console.log('Message sent: ' + info.response);
});
}
});
}
}
}
/*
Finalizada la lectura de la trama, sea correcta o erronea se desconecta de
la
base de datos.
*/
connection.end();
});
});
Red de sensores para monitorización inteligente de vivienda 117
118 Anexos
<ul>
<li><a href="#inicio">Inicio</a></li>
<li><a href="#sensores">Sensores</a></li>
<li><a href="#acercade">Acerca De</a></li>
</ul>
</nav>
</header>
<section id="inicio">
<div class="container-flow divinicio">
<div class="row">
<div class="col-sm-10 col-md-10 col-sm-offset-1 col-md-offset-1">
<div class="container-flow">
<div class="row">
<div class="subdivc col-xs-12 col-md-4">
<div id="divintrologo"></div>
<h3>Introducción</h3>
<p>SenHome es el nombre comercial del proyecto final de carrera
"Red de sensores para domótica y sistemas de alarma". Está realizado por
Javier Arcenegui Almenara y tutorizado por Antonio Luque Estepa (Dpto. de
Electrónica de la Escuela Superior de Ingenieros de la Universidad de
Sevilla).</p>
<p>Es un proyecto de domótica dirigido a personas concienciadas con
el medio ambiente y la eficiencia energética. Está formado por un conjunto de
sensores repartidos por diferentes habitaciones del hogar como son, el
dormitorio, la cocina, el baño y el salón; y una alarma antirrobo de registro
de presencia.</p>
</div>
<div class="subdivc col-xs-12 col-md-4">
<div id="divtaplogo"></div>
<h3>Funcionamiento</h3>
<p>Su objetivo es medir las principales variables relacionadas con
la eficiencia energética, como son, la humedad, la temperatura, la
luminosidad y la presencia. La utilización de este servicio es muy intuitivo
y accesible. El usuario podrá acceder a la sección de sensores donde
aparecerá una lista con la última lectura realizada, un enlace para ver las
gráficas en tiempo real y también aparecerán si existen elementos sin
etiquetar, en dicho caso se podrá acceder al panel de administrador. Al
seleccionar las gráficas se generará la del sensor que se quiera del nodo
elegido, se puede además seleccionar un rango de fechas concreto a
mostrar.</p>
</div>
<div class="subdivc col-xs-12 col-md-4">
<div id="divalarmlogo"></div>
<h3>Alarma</h3>
<p>El sistema detecta personas en su interior. Funciona mediante un
sistema de tarjetas con lector RFID, con el que se puede saber quién se
encuentra en casa y por lo tanto si hay alguien ajeno a ella. Para la
seguridad de la vivienda y por tanto de los propietarios, se les avisará por
e-mail si entra alguien en casa.</p>
<p>Además de para el uso antirrobo, este sistema es útil para saber
si los hijos, los trabajadores del hogar o cualquier persona que el
propietario desee saber están en la vivienda.</p>
<p>Si en un futuro se quisiese añadir un sensor de movimiento para
encender la luz, se podría añadir a dicho sistema.</p>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<section id="sensores">
Red de sensores para monitorización inteligente de vivienda 121
<div class="container-flow">
<div class="row">
<div class="col-sm-10 col-md-10 col-sm-offset-1 col-md-offset-1
titulosensor">
<h3>Sensores</h3>
<div class="container-flow">
<div id="subdivdatos" class="row">
</div>
</div>
</div>
</div>
</div>
</section>
<section id="acercade">
<div class="container-flow">
<div class="row">
<div class="col-sm-10 col-md-10 col-sm-offset-1 col-md-offset-1">
<div class="container-flow">
<div class="col-xs-12 col-md-6 acerca">
<h3>Javier Arcenegui Almenara</h3>
<p>Estudiante de Ingeniero en Telecomunicación en la Universidad de
Sevilla</p>
<p>Investigador del departamento de I+D+i en TopDigital consulting
especializado en hardware para dispositivos IoT y M2M.
<p>j.arcenegui@xxmail.com</p>
<p>+34 647 8xx xxx</p>
</div>
<div class="col-xs-12 col-md-6 acerca">
<h3>Red de sensores para domótica y sistemas de alarma</h3>
<p>Proyecto de Fin de Carrera del curso 2015-2016</p>
<p>Tutor del proyecto: Antonio Luque Estepa</p>
<p>Escuela Técnica Superior de Ingenieros</p>
<p>Escuela Superior de Ingenieros</p>
<p>Universidad de sevilla</p>
</div>
header{
background: #111;
padding: 0;
margin: 0;
height: 50px;
width: 100%;
z-index: 300;
}
#barranav{
padding: 0;
margin: 0;
background: #4fab2f;
height: 50px;
top:0;
width: 100%;
position: fixed;
border-bottom: solid black 1px;
z-index: 300;
}
#barranav ul{
list-style-type: none;
text-align: center;
margin-top: 12px;
}
#barranav li{
display: inline;
text-align: center;
}
#barranav a{
font-family: 'Roboto', sans-serif;
color: white;
text-decoration: none;
margin: 0 40px 0 40px;
#inicio{
background: #222;
color: white;
height: 100%;
width: 100%;
float: left;
}
.divinicio{
width: 100%;
}
Red de sensores para monitorización inteligente de vivienda 125
.subdivc{
margin-top: 100px;
margin-bottom: 180px;
text-align: center;
.subdivc p{
text-align: justify;
}
#divintrologo{
width: 100px;
height: 100px;
background-image: url(Info.png);
background-size: 100px 100px;
background-repeat: no-repeat;
margin-bottom: 20px;
left: 50%;
margin-left: -50px;
position: relative;
}
#divtaplogo{
width: 100px;
height: 100px;
background-image: url(tap.png);
background-size: 100px 100px;
background-repeat: no-repeat;
margin-bottom: 20px;
left: 50%;
margin-left: -50px;
position: relative;
}
#divalarmlogo{
width: 100px;
height: 100px;
background-image: url(alarm.png);
background-size: 100px 100px;
background-repeat: no-repeat;
margin-bottom: 20px;
left: 50%;
margin-left: -50px;
position: relative;
}
#sensores{
background:#4fab2f;.
position: relative;
color:black;
height: 100%;
width: 100%;
float: left;
}
#divsensores{
width: 100%;
}
.datos{
padding-top: 10px;
padding-bottom: 10px;
126 Anexos
padding: 10px;
text-align: center;
#subdivdatos{
text-align: center;
margin-top: 100px;
width: 100%;
height: 100%;
margin-bottom: 150px;
#sensorBano{
margin-top: 110px;
margin-left: 250px;
width: 25px;
height:25px;
background-image: url(sensor.png);
background-size: 25px 25px;
background-repeat: no-repeat;
position: relative;
}
#sensorDormitorio{
margin-top: -25px;
margin-left: 400px;
width: 25px;
height:25px;
background-image: url(sensor.png);
background-size: 25px 25px;
background-repeat: no-repeat;
position: relative;
}
#sensorSalon{
margin-top: 155px;
margin-left: 130px;
width: 25px;
height:25px;
background-image: url(sensor.png);
background-size: 25px 25px;
background-repeat: no-repeat;
position: relative;
}
.piesensor{
margin-top: 30px;
}
.titulosensor{
margin-top: 50px;
margin-left: 50px;
}
#sensorCocina{
width: 25px;
height:25px;
margin-left: 290px;
margin-top: -25px;
background-image: url(sensor.png);
background-size: 25px 25px;
Red de sensores para monitorización inteligente de vivienda 127
background-repeat: no-repeat;
position: relative;
}
#acercade{
background:#fff;
color:black;
height: 100%;
width: 100%;
float: left;
}
.acerca{
padding: 50px 50px 50px 50px;
margin-bottom: 50px;
}
#LogoUS{
width: 30%;
height: 100px;
background-image: url(LogoUS.png);
float: left;
background-repeat: no-repeat;
background-position: center;
background-size: 100px 100px;
}#Logodep{
width: 30%;
height: 100px;
background-image: url(Logodep.png);
float: left;
background-repeat: no-repeat;
background-position: center;
background-size: 100px 100px;
margin-bottom: 100px;
}
#LogoESI{
width: 30%;
height: 100px;
background-image: url(LogoESI.png);
float: left;
background-repeat: no-repeat;
background-position: center;
background-size: 100px 100px;
#pie{
background: #4fab2f;
text-align: center;
}
#pie a{
color: white;
text-decoration: underline;
font-size: 80%;
}
.piesensor a{
color: #111;
}
128 Anexos
.piesensor a:hover {
color:#333;
text-decoration: none;
}
.subdivdatos a{
color: #111;
}
.subdivdatos a:hover {
color:#333;
text-decoration: none;
}
.bodygraf{
background-color: white;
overflow: hidden;
.grafico{
position: relative;
margin-top: 3%;
height: 45%;
padding-left:3%;
width: 98%;
padding-right: 3%;
}
Red de sensores para monitorización inteligente de vivienda 129
130 Anexos
*****************************************************************************
**************************************/
}
echo'<div class="col-lg-12 piesensor"> <p>';
$sql = "SELECT * FROM `rfid` WHERE encasa=1";
$consulta = mysqli_query($conexion,$sql);
$auxiliar = 1;
Red de sensores para monitorización inteligente de vivienda 133
echo '</div>';
}
mysqli_close($conexion);
?>
134 Anexos
*****************************************************************************
**************************************/
//$conexion = mysqli_connect('10.6.64.25','u3227504_pfc'
,'B8Iov*c<;z','db3227504_sense');
$conexion = mysqli_connect('127.0.0.1','root' ,'password','PFC');
if($conexion ==false){
echo('Error al conectar con la base de datos');
}else{
mysqli_close($conexion);
?>
Red de sensores para monitorización inteligente de vivienda 135
136 Anexos
*****************************************************************************
**************************************/
if($conexion ==false){
echo('Error al conectar con la base de datos');
}else{
$MAC = $_GET['MAC'];
$SENSOR = $_GET['SENSOR'];
$FROM = $_GET['FROM'];
$TO = $_GET['TO'];
array_push($array, $dato);
}
echo json_encode($array);
mysqli_close($conexion);
?>
Red de sensores para monitorización inteligente de vivienda 137
138 Anexos
<body>
<div class="container-flow">
<div class="row">
<div class="col-xs-8 col-sm-6 col-md-4 col-xs-offset-2 col-sm-offset-3
col-md-offset-4 login">
<div class="container-flow divinicio">
<div class="row">
<div class="tittle_Admin">
</div>
</div>
</div>
<div class="container-flow">
<div class="row">
<div class="col-xs-10 col-xs-offset-1">
<form method="post" action="admin.php">
<div class="container-flow recuadroAdmin">
<div class="row">
<div class="col-xs-4">
<label for="user">Usuario : </label>
</div>
<div class="col-xs-8">
<input type="text" name="user" id="user"
class="rellenaAdmin"></input>
</div>
</div>
</div>
<div class="container-flow recuadroAdmin">
<div class="row">
<div class="col-xs-4">
<label for="password">Contraseña : </label>
</div>
<div class="col-xs-8">
<input type="password" name="password" id="password"
class="rellenaAdmin"></input>
</div>
</div>
</div>
<div class="botonAdmin">
<input type="submit" value="Acceder"></input>
</div>
</form>
</div>
</div>
</div>
Red de sensores para monitorización inteligente de vivienda 139
</div>
</div>
</div>
</body>
</html>
140 Anexos
.login{
background: #4fab2f;
margin-top: 150px;
border-radius: 20px 20px 20px 20px;
padding-top: 20px;
}
.admin{
background: #4fab2f;
margin-top: 10px;
border-radius: 20px 20px 20px 20px;
padding-top: 20px;
}
.tittle_Admin h1{
text-align: left;
font-weight: bold;
}
.tittle_Admin h5{
font-weight: bold;
text-align: right;
margin-top: -10px;
}
.tittle_Admin{
background-image: url("logoPanel.jpg");
background-size: 380px 108px;
background-repeat: no-repeat;
background-position: center;
width: 100%;
margin-bottom: 30px;
height: 108px;
}
.tittle_Admin2 h1{
text-align: left;
font-weight: bold;
}
.tittle_Admin2 h5{
font-weight: bold;
text-align: right;
margin-top: -10px;
}
.tittle_Admin2{
max-width: 380px;
margin-bottom: 30px;
float: center;
}
Red de sensores para monitorización inteligente de vivienda 141
.recuadroAdmin{
margin-bottom: 20px;
}
.rellenaAdmin{
width: 100%;
border: 0;
box-shadow: inset 1px 2px 0px 0px #555 ;
background-color: white;
text-align: center;
font-weight: bold;
padding-top: 5px;
margin-top: -5px;
}
.NOrellena{
width: 100%;
border: 0;
box-shadow: inset 0px 0px 0px 0px #4fab2f ;
background-color: #4fab2f;
text-align: center;
font-weight: bold;
padding-top: 5px;
margin-top: -5px;
}
.botonAdmin{
float: right;
margin-top: 10px;
margin-right: -10px;
margin-bottom: 30px;
}
.botonAdmin input{
background-color: white;
border-radius: 5px 5px 5px 5px;
padding: 7px;
padding-left: 20px;
padding-right: 20px;
font-weight: bold;
}
.botonAtualizar{
margin-top: -8px;
}
.botonAtualizar input{
background-color: white;
border-radius: 5px 5px 5px 5px;
padding: 7px;
padding-left: 20px;
padding-right: 20px;
font-weight: bold;
}
.sensores h4{
text-align: center;
font-weight: bold;
margin-top: 0px;
margin-bottom: 20px;
}
.sensores p{
142 Anexos
text-align: center;
}
.leyenda{
text-align: center;
font-weight: bold;
}
.formulario{
padding-top: 50px;
}
.nota{
padding-top: 20px;
}
Red de sensores para monitorización inteligente de vivienda 143
144 Anexos
*****************************************************************************
**************************************/
session_start();
$usuario = $_POST['user'];
$contrasena = $_POST['password'];
if($conexion ==false){
echo('Error al conectar con la base de datos');
}else{
//Realizamos la consulta
$query = "SELECT * FROM users WHERE usuario = '$usuario' AND contrasena =
'$contrasena'";
//Lanzamos la consulta
$resultado = $conexion->query($query);
//Comprobamos el resultado
if(mysqli_num_rows($resultado) > 0){
//login correcto
</head>
<body>
<div class="container-flow">
<div class="row">
<div class="col-xs-8 col-xs-offset-2 admin">
<div class="container-flow divinicio">
<div class="row">
<div class="tittle_Admin">
</div>
</div>
</div>
</div>
</div>
</div>
<div class="container-flow">
<div class="row">
<div class="col-xs-8 col-xs-offset-2 admin sensores">
<h4>Nodos de sensores</h4>
<div class="container-flow">
<div class="row">
<div class="col-sm-3 col-sm-offset-1 leyenda">
<p>MAC</p>
</div>
<div class="col-sm-3 leyenda">
<p>HABITACIÓN</p>
</div>
<div class="col-sm-1 leyenda">
<p>BORRAR</p>
</div>
<div class="col-sm-3 leyenda">
<p>ACTUALIZAR</p>
</div>';
$indice = 0;
while ($fila = mysqli_fetch_array($consulta)){
echo '<div class="formulario">
<form method="post" action="mRegistro.php">
<div class="col-sm-3 col-sm-offset-1 leyenda">
<input for="mac" id="mac" name="mac" class="NOrellena"
value="'.$fila['mac'].'" readonly="readonly"></input>
</div>
<div class="col-sm-3 leyenda">
<input type="text" name="room" id="room"
class="rellenaAdmin" value="'.$fila['room'].'"></input>
</div>
<div class="col-sm-1 leyenda">
<input type="checkbox" name="borrar"></input>
</div>
<div class="col-sm-3 leyenda">
<div class="botonAtualizar">
<input type="submit" name="registro"
value="Actualizar"></input>
</div>
</div>
</form>
</div>'
;
}
$sql = "SELECT * FROM `rfid`";
$consulta = mysqli_query($conexion,$sql);
if (!$consulta) {
146 Anexos
</form>
</div>';
}
echo '<div class="formulario">
</div>
<div class="formulario">
</div>
</div>
</div>
</div>
</div>';
$sql = "SELECT * FROM `Alarma`";
$consulta = mysqli_query($conexion,$sql);
if (!$consulta) {
$message = 'Invalid query: ' . mysql_error() . " ";
$message .= 'Whole query: ' . $sql;
die($message);
}
echo '</form>
</div>
</div>
<br>
<p>Nota: Desarmar la alarma también desactiva la sirena si esta
estuviera sonando</p>
</div>
</div>
148 Anexos
</div>
</body>
</html>';
}else{
//Usuario o Contrasena incorrecto
echo '<!DOCTYPE html>
<html>
<head lang="es">
<meta charset="utf-8" />
<title>Panel de Administración</title>
<link rel="icon" type="image/png" href="mifavicon.png" />
<link href="http://fonts.googleapis.com/css?family=Roboto"
rel="stylesheet" type="text/css">
<link rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<script
src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></s
cript>
<link rel="stylesheet" type="text/css" href="estilosAdmin.css">
</head>
<body>
<div class="container-flow">
<div class="row">
<div class="col-xs-8 col-sm-6 col-md-4 col-xs-offset-2 col-sm-offset-3
col-md-offset-4 login">
<div class="container-flow divinicio">
<div class="row">
<div class="tittle_Admin">
</div>
</div>
</div>
<div class="container-flow">
<div class="row">
<div class="col-xs-10 col-xs-offset-1">
<form method="post" action="admin.php">
<div class="container-flow recuadroAdmin">
<div class="row">
<div class="col-xs-8 col-xs-offset-2 admin sensores">
<h4>Usuario o contraseña erroneo.</h4>
</div>
<div class="col-xs-4">
<label for="user">Usuario : </label>
</div>
<div class="col-xs-8">
<input type="text" name="user" id="user"
class="rellenaAdmin"></input>
</div>
</div>
</div>
<div class="container-flow recuadroAdmin">
<div class="row">
<div class="col-xs-4">
<label for="password">Contraseña : </label>
</div>
<div class="col-xs-8">
<input type="password" name="password" id="password"
class="rellenaAdmin"></input>
</div>
</div>
</div>
<div class="botonAdmin">
Red de sensores para monitorización inteligente de vivienda 149
</div>
</div>
</div>
</body>
</html>';
}
}
mysqli_close($conexion);
?>
150 Anexos
*/
if($conexion ==false){
}else{
if($_POST['registro'] == 'Actualizar') {
$dispositivo = $_POST['mac'];
$room = $_POST['room'];
if($dispositivo){
if(isset($_POST['borrar'])){
$sql = "DELETE FROM Registro WHERE mac = '".$dispositivo."' ";
$consulta = mysqli_query($conexion, $sql);
$escribe = 1;
}else{
if(!($_POST['room']))
{
$room='SinAsignar';
}
$sql = "UPDATE Registro SET room = '".$room."' WHERE mac =
'".$dispositivo."' ";
$consulta = mysqli_query($conexion, $sql);
}
$escribe = 1;
}else{
$escribe = 0;
}
}else if($_POST['rfid'] == 'Actualizar') {
$id= $_POST['id'];
$usuario = $_POST['usuario'];
if(isset($_POST['encasa'])){
$encasa = '1';
}else{
$encasa = '0';
}
if($id){
if(isset($_POST['borrar'])){
$sql = "DELETE FROM rfid WHERE id = '".$id."' ";
$consulta = mysqli_query($conexion, $sql);
$escribe = 1;
}else{
if(!($_POST['usuario']))
Red de sensores para monitorización inteligente de vivienda 151
{
$usuario='SinRegistrar';
}
$sql = "UPDATE rfid SET usuario = '".$usuario."' , encasa =".$encasa."
WHERE id = '".$id."' ";
$consulta = mysqli_query($conexion, $sql);
$escribe = 1;
}
}else{
$escribe = 0;
}
}else if($_POST['Alarma'] == 'Actualizar') {
if(isset($_POST['armar'])){
$sql = "UPDATE Alarma SET Armado = 1 WHERE Alarma = Alarma";
$consulta = mysqli_query($conexion, $sql);
$escribe = 1;
}else if(isset($_POST['desarmar'])){
$sql = "UPDATE Alarma SET Armado = 0 , Activado = 0 , Sonando = 0 WHERE
Alarma = Alarma";
$consulta = mysqli_query($conexion, $sql);
$escribe = 1;
}else{
$escribe = 1;
}
}else{
$escribe = 0;
}
//echo $escribe;
//Comprobamos el resultado
if($escribe){
//login correcto
<body>
<div class="container-flow">
<div class="row">
<div class="col-xs-8 col-xs-offset-2 admin">
<div class="container-flow divinicio">
<div class="row">
<div class="tittle_Admin">
152 Anexos
</div>
</div>
</div>
</div>
</div>
</div>
<div class="container-flow">
<div class="row">
<div class="col-xs-8 col-xs-offset-2 admin sensores">
<h4>Nodos de sensores</h4>
<div class="container-flow">
<div class="row">
<div class="col-sm-3 col-sm-offset-1 leyenda">
<p>MAC</p>
</div>
<div class="col-sm-3 leyenda">
<p>HABITACIÓN</p>
</div>
<div class="col-sm-1 leyenda">
<p>BORRAR</p>
</div>
<div class="col-sm-3 leyenda">
<p>ACTUALIZAR</p>
</div>';
$indice = 0;
while ($fila = mysqli_fetch_array($consulta)){
echo '<div class="formulario">
<form method="post" action="mRegistro.php">
<div class="col-sm-3 col-sm-offset-1 leyenda">
<input for="mac" id="mac" name="mac" class="NOrellena"
value="'.$fila['mac'].'" readonly="readonly"></input>
</div>
<div class="col-sm-3 leyenda">
<input type="text" name="room" id="room"
class="rellenaAdmin" value="'.$fila['room'].'"></input>
</div>
<div class="col-sm-1 leyenda">
<input type="checkbox" name="borrar"></input>
</div>
<div class="col-sm-3 leyenda">
<div class="botonAtualizar">
<input type="submit" name="registro"
value="Actualizar"></input>
</div>
</div>
</form>
</div>'
;
}
$sql = "SELECT * FROM `rfid`";
$consulta = mysqli_query($conexion,$sql);
if (!$consulta) {
$message = 'Invalid query: ' . mysql_error() . " ";
$message .= 'Whole query: ' . $sql;
die($message);
}
echo '<div class="formulario">
</div>
<div class="formulario">
</div>
Red de sensores para monitorización inteligente de vivienda 153
</div>
</div>
</div>
</div>
</div>
<div class="container-flow">
<div class="row">
<div class="col-xs-8 col-xs-offset-2 admin sensores">
<h4>Usuarios RFID</h4>
<div class="container-flow">
<div class="row">
<div class="col-xs-3 leyenda">
<p>ID</p>
</div>
<div class="col-xs-3 leyenda">
<p>INQUILINO</p>
</div>
<div class="col-xs-1 leyenda">
<p>CASA</p>
</div>
<div class="col-xs-1 leyenda">
<p>BORRAR</p>
</div>
<div class="col-xs-4 leyenda">
<p>ACTUALIZAR</p>
</div>';
$indice = 0;
while ($fila = mysqli_fetch_array($consulta)){
echo '<div class="formulario">
<form method="post" action="mRegistro.php">
<div class="col-xs-3 leyenda">
<input for="mac" id="id" name="id" value="'.$fila['id'].'"
class="NOrellena" readonly="readonly"></input>
</div>
<div class="col-xs-3 leyenda">
<input type="text" name="usuario" id="usuario"
value='.$fila['usuario'].' class="rellenaAdmin"></input>
</div>
<div class="col-xs-1 leyenda">';
if($fila['encasa']){
echo '<input type="checkbox" name="encasa" checked></imput>';
}else{
echo '<input type="checkbox" name="encasa"></imput>';
}
echo '</div>
<div class="col-xs-1 leyenda">
<input type="checkbox" name="borrar"></imput>
</div>
<div class="col-xs-4 leyenda">
<div class="botonAtualizar">
<input type="submit" name="rfid"
value="Actualizar"></input>
</div>
</div>
</form>
</div>';
}
echo '<div class="formulario">
</div>
<div class="formulario">
</div>
</div>
</div>
154 Anexos
</div>
</div>';
$sql = "SELECT * FROM `Alarma`";
$consulta = mysqli_query($conexion,$sql);
if (!$consulta) {
$message = 'Invalid query: ' . mysql_error() . " ";
$message .= 'Whole query: ' . $sql;
die($message);
}
echo '</form>
</div>
</div>
<br>
<p>Nota: Desarmar la alarma también desactiva la sirena si esta
estuviera sonando</p>
</div>
</div>
</div>
</body>
</html>';
}else{
//Usuario o Contrasena incorrecto
echo '<!DOCTYPE html>
<html>
<head lang="es">
Red de sensores para monitorización inteligente de vivienda 155
<body>
<div class="container-flow">
<div class="row">
<div class="col-xs-8 col-sm-6 col-md-4 col-xs-offset-2 col-sm-
offset-3 col-md-offset-4 login">
<div class="container-flow divinicio">
<div class="row">
<div class="tittle_Admin">
</div>
</div>
</div>
<div class="container-flow">
<div class="row">
<div class="col-xs-10 col-xs-offset-1">
<form method="post" action="admin.php">
<div class="container-flow recuadroAdmin">
<div class="row">
<div class="col-xs-8 col-xs-offset-2 admin sensores">
<h4>Sesión caducada.</h4>
</div>
<div class="col-xs-4">
<label for="user">Usuario : </label>
</div>
<div class="col-xs-8">
<input type="text" name="user" id="user"
class="rellenaAdmin"></input>
</div>
</div>
</div>
<div class="container-flow recuadroAdmin">
<div class="row">
<div class="col-xs-4">
<label for="password">Contraseña : </label>
</div>
<div class="col-xs-8">
<input type="password" name="password" id="password"
class="rellenaAdmin"></input>
</div>
</div>
</div>
<div class="botonAdmin">
<input type="submit" value="Acceder"></input>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
156 Anexos
</div>
</body>
</html>';
}
}
mysqli_close($conexion);
?>
Red de sensores para monitorización inteligente de vivienda 157
158 Anexos