El Internet de los objetos (IoT) se está poniendo de moda últimamente. Poder fabricar cualquier dispositivo mecánico, por ejemplo relojes, televisores, termostatos, y hacer que se comuniquen a través de Internet es la era moderna. En esta era moderna, una cosa que permanece constante es la necesidad de transferir y almacenar datos. ¿Cómo se hace esto desde un dispositivo IoT?
Servidor Couchbase para almacenar cantidades masivas de datos empresariales y Couchbase Móvil existe para almacenar datos localmente en dispositivos móviles y sincronizarlos con Couchbase Server cuando sea posible. ¿Dónde encaja IoT en todo esto? Los dispositivos IoT no son servidores y técnicamente no son dispositivos móviles.
¿Sabías que muchos dispositivos IoT son capaces de ejecutar aplicaciones Java? En realidad hay un SDK de Couchbase Lite para Java. No es un SDK para Android o iOS. Es un SDK para aplicaciones Java en general. Con esto, podemos usarlo para IoT.
Alcance del proyecto
Ahora que sabemos que es posible, pensemos en un buen ejemplo de IoT y ejecutémoslo. Vamos con un ejemplo iBeacon bajo el siguiente escenario.
Supongamos que desea rastrear a su mascota cuando está fuera de casa. Quiere saber por dónde pasa su mascota y a qué horas del día. Así que decide colocar un iBeacon en el collar de su mascota e instalar varios escáneres IoT en su casa.
Así, con el iBeacon conectado y las pasarelas IoT instaladas, los dispositivos IoT pueden buscar continuamente iBeacons. Cuando un iBeacon entra en el radio de alcance, se guarda una marca de tiempo junto con la ubicación y la información de la baliza, y se carga en el servidor. Más tarde puede crear su propio panel de control con un mapa de calor para comprender mejor sus datos.
¿Qué hace falta para probar este proyecto?
Requisitos
Hay algunos requisitos tanto en el ámbito del software como del hardware. Pueden verse a continuación:
- Mínimo uno (1) Pasarela Intel IoT
- Mínimo uno (1) Gimbal baliza de proximidad
- Java 1.7+
- Maven
- Pasarela de sincronización Couchbase
Aunque hay un requisito de hardware, la marca del hardware es un poco flexible. He incluido tanto la pasarela Intel IoT como las balizas de proximidad Gimbal porque no sólo son increíblemente asequibles, sino que son las que he utilizado al crear mi aplicación. Para sacar el máximo provecho de este ejemplo, lo mejor es tener varias balizas y puertas de enlace, pero una estará bien para la creación de prototipos.
A continuación se explica cómo se llevará a cabo este proyecto.
El código fuente completo de este proyecto puede consultarse en GitHub.
Guardar los datos con Couchbase
Antes de entrar en el trabajo de IoT y balizas, sería una buena idea definir nuestro modelo de datos y construir nuestra aplicación Java. En este escenario, que es uno de muchos, la aplicación Java no buscará balizas. Sólo será responsable de guardar los datos.
El modelo de datos de Couchbase Beacon
Si no estás familiarizado con los iBeacons, no ofrecen nada más que unos pocos valores de cadena y enteros en su transmisión. No se puede conectar a ellos y no pueden ver otros dispositivos. Lo único que hacen es emitir. Dicho esto, los valores emitidos son los siguientes:
- UUID
- Mayor
- Menor
- Potencia
En UUID, Mayory Menor ofrecen información uniquness sobre una baliza concreta. Los tres valores pueden formar una clave compuesta útil para consultas posteriores.
Pensemos en cómo vamos a almacenar los datos de la baliza cada vez que se detecte una.
Podríamos crear un nuevo documento JSON cada vez que se detecte una baliza. Los documentos individuales podrían tener un aspecto similar a:
1 2 3 4 5 6 7 8 9 |
{ "uuid": "32342342", "mayor": 1, "menor": 0, "createdAt": 1932847298, "gatewayDevice": "cocina" } |
El planteamiento anterior no tiene nada de malo. Sin embargo, podrías acabar con cantidades masivas de documentos dependiendo de cuántas balizas tengas circulando. Una vez más, Couchbase fue diseñado para manejar esto, así que es una cuestión de preferencia. Yo prefiero mantener todas las transacciones de una baliza en particular en el mismo documento:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
{ "uuid": "23423423", "mayor": 1, "menor": 0, "beaconStatus": [ { "createdAt": 234234321234, "gatewayDevice": "cocina" }, { "createdAt": 12312323544, "gatewayDevice": "garaje" } ] } |
En el segundo escenario, cada vez que se descubra una baliza, se consultará a Couchbase en función de la clave compuesta y, a continuación, los datos de estado se añadirán a la matriz de estado.
Añadir las dependencias de Maven
Dado que este proyecto Java va a estar basado en Maven, el archivo pom.xml necesita satisfacer ciertas dependencias. Añade la siguiente dependencia a tu archivo Maven para incluir Couchbase Lite Java SDK en tu proyecto:
1 2 3 4 5 6 7 |
com.couchbase.lite couchbase-lite-java 1.2.0 |
La dependencia anterior te permitirá almacenar documentos Couchbase localmente en tu dispositivo IoT y hacer que se sincronicen con Couchbase Sync Gateway.
Creación de una clase de baliza
Dado que vamos a trabajar con iBeacons, tiene sentido crear una clase Java Beacon. Esta clase debe ser responsable de guardar los datos de la baliza, así como de cargarlos en caso de consulta. Empecemos echando un vistazo a cómo es la carga:
1 2 3 4 5 6 7 8 9 10 |
privado Documento carga(Base de datos base de datos) { Documento documento = null; pruebe { Ver beaconView = base de datos.getView("balizas"); beaconView.setMap(nuevo Mapeador() { @Anular público void mapa(Mapa<Cadena, Objeto> documento, Emisor emisor) { Lista<objeto> llaves = nuevo ArrayList<objeto>(); llaves.añada(documento.consiga("uuid")); llaves.añada(documento.consiga("mayor")); llaves.añada(documento.consiga("menor")); emisor.emite(llaves, documento.consiga("beaconStatus")); } }, "1"); Consulta consulta = beaconView.createQuery(); Lista<objeto> llaves = nuevo ArrayList<objeto>(); Lista<objeto> clave = nuevo ArrayList<objeto>(); clave.añada(este.uuid); clave.añada(este.mayor); clave.añada(este.menor); llaves.añada(clave); consulta.setKeys(llaves); QueryEnumerator resultado = consulta.ejecute(); para (Iterador it = resultado; it.hasNext(); ) { Fila de consulta fila = it.siguiente(); documento = fila.getDocument(); } } captura (Excepción e) { e.printStackTrace(); } devolver documento;}A lote es sucediendo en el sobre carga así que dejeDado que las consultas de Couchbase Lite se basan en vistas MapReduce, primero creamos una vista. Recuerda que vamos a utilizar una clave compuesta, por lo que crearemos una lista de claves. Los únicos datos que necesitamos que nos devuelva si se ha encontrado una coincidencia es el array de estado que contiene la información de timestamp y gateway. Como estamos en una clase Java personalizada, vamos a's asuma que nosotros've capturado el <strong>uuid</strong>, <strong>mayor</strong>y <strong>menor</strong> valores en algún momento. Nosotrosll construir el clave enumera fuera de el valores y configure el consulta a utilice ellos con el <código>consulta.setKeys</código> función.En el consulta corre nosotros'll bucle a través de los resultados. Sólo esperamos un resultado, que puede asegurarse utilizando una función de limitación antes de ejecutar la consulta. El resultado de la consulta, si lo hay, se devolverá a la función de carga. En este caso, la función guardar la llamará antes de guardarla.s toma a mira en el guardar función de nuestra faro clase. <pre><código>público Cadena guardar(Base de datos base de datos) { Cadena docId = ""; Mapa<Cadena, Objeto> propiedades = nuevo HashMap<Cadena, Objeto>(); ArrayList beaconStatusList = nuevo ArrayList(); Documento documento = este.carga(base de datos); si(documento != null) { propiedades.putAll(documento.getProperties()); beaconStatusList = (ArrayList) propiedades.consiga("beaconStatus"); } si no { documento = base de datos.crearDocumento(); propiedades.poner("uuid", este.uuid); propiedades.poner("mayor", este.mayor); propiedades.poner("menor", este.menor); } beaconStatusList.añada(este.beaconStatus); propiedades.poner("beaconStatus", beaconStatusList); pruebe { docId = documento.putProperties(propiedades).getDocument().getId(); } captura (Excepción e) { e.printStackTrace(); } devolver docId;} |
En la función de guardar, primero queremos cargar los documentos para ver si ya existen. Si existe un documento para la información de la baliza, queremos añadirlo a él, de lo contrario podemos simplemente crear un nuevo documento. Después de haber reconstruido nuestro documento Couchbase, ya sea desde cero o a partir de datos de documentos existentes, lo guardamos a través de la función putProperties
En este punto, los datos de la baliza pueden guardarse y leerse desde la base de datos local de Couchbase Lite.
Sincronización con Couchbase Sync Gateway
Lo más probable es que vayas a trabajar con más de una pasarela de escaneo IoT. Por ello, los datos de la baliza (en el modelo de documento incrustado) deberán sincronizarse entre dispositivos IoT. Ahora podemos llevar nuestro código de guardado y carga al siguiente nivel.Echa un vistazo al siguiente código:
1 |
pruebe { director = nuevo Director(nuevo JavaContext("datos"), Director.OPCIONES_POR_DEFECTO); base de datos = director.getDatabase("proyecto-iot"); URL url = nuevo URL("http://192.168.1.174:4984/beacons-iot/"); final Replicación pulse = base de datos.createPushReplication(url); Replicación tire de = base de datos.createPullReplication(url); tire de.setContinuous(falso); pulse.setContinuous(falso); tire de.addChangeListener(nuevo Replicación.ChangeListener() { @Anular público void cambiado(Replicación.Evento de cambio evento) { si(evento.getSource().getStatus() == Replicación.ReplicationStatus.REPLICACIÓN_PARADA) { faro.guardar(base de datos); pulse.iniciar(); } } }); pulse.addChangeListener(nuevo Replicación.ChangeListener() { @Anular público void cambiado(Replicación.Evento de cambio evento) { si(evento.getSource().getStatus() == Replicación.ReplicationStatus.REPLICACIÓN_PARADA) { Sistema.salida(1); } } }); tire de.iniciar();} captura (Excepción e) { e.printStackTrace();} |
Este código debe existir en otra clase, preferiblemente la clase que contiene su principal
función. Esencialmente, inicializará la conexión a su base de datos local, configurará los replicadores push y pull a una instancia de Sync Gateway que se ejecuta de forma remota e iniciará el proceso de guardado y sincronización. Cuando ejecutemos la aplicación, primero extraeremos del servidor cualquier documento de baliza relevante. Utilizando escuchadores de cambios en los replicadores podemos esperar a guardar sólo cuando hayamos terminado de descargar cualquier cambio. Para evitar que la aplicación Java permanezca abierta después de empujar, añadimos un oyente que cerrará la aplicación al finalizar.
Resolución de errores de dependencia de SQLite
Al construir esta aplicación con Maven, no debería haber ningún problema. Sin embargo, dependiendo del dispositivo IoT en el que se despliegue podría haber un problema de dependencia de librerías. Hay muchas arquitecturas diferentes en circulación. Un ejemplo de error podría ser el siguiente:
1 |
Biblioteca no encontrado: /nativo/linux/i386/libsqlite3.así que |
Esto puede resolverse fácilmente extrayendo el archivo JAR, renombrando uno de los directorios y empaquetándolo de nuevo en un JAR. Para ser más específicos, para extraer su archivo JAR, ejecute el siguiente comando:
1 |
tarro xvf [nombre de archivo].tarro |
A partir de los documentos y archivos extraídos, cambie el nombre de los archivos /nativo/linux/x86 al directorio /nativo/linux/i386. Una vez hecho esto, puede volver a empaquetar su archivo JAR y volver a desplegarlo.
1 |
tarro cvfm [nombre de archivo].tarro META-INF/MANIFIESTE.MF . |
El comando anterior volverá a empaquetar el archivo JAR para usted.
Búsqueda de iBeacons y seguimiento de su estado
Como se ha mencionado anteriormente, la aplicación Java no es responsable de detectar los iBeacons. Sólo es responsable de guardar los datos. En su lugar vamos a hacer uso de algunas herramientas que vienen preinstaladas en un sistema operativo Linux.
Escaneado con herramientas Linux
La mayoría de las distribuciones de Linux incluyen hcitool y hcidump aplicaciones. El sitio hcitool te permitirá buscar dispositivos bluetooth que estén dentro de su alcance. Deberías ejecutar algo como lo siguiente:
1 |
hcitool lescan |
Lo anterior devolvería información básica sobre los dispositivos encontrados en un escaneo. A continuación, se utilizaría la función hcidump herramienta para mostrar cualquier cosa y todo sobre los datos bluetooth que se descubrió. Algo como esto mostraría los datos en bruto:
1 |
hcidump --en bruto |
El problema es que los datos están en bruto. No es algo con lo que podamos trabajar en su forma actual. No podríamos utilizarlos para dar sentido a los datos de iBeacon.
Simplifique el proceso con una herramienta de Radius Networks
Aquí es donde un guión de Redes Radius entra en juego. Existe un script llamado Escaneado iBeacon que hará uso de hcitool y hcidumppero analizado y limpio. Se puede ver a continuación:
1 |
#!/bin/bash# iBeacon Scan by Radius Networks# Modificado por Nic Raboy en Couchbaseif [[ $1 == "parse" ]]; then packet="" capturing="" count=0 while read line do count=$[count + 1] if [ "$capturing" ]; then if [[ $line =~ ^[0-9a-fA-F]{2} [0-9a-fA-F] ]; then packet="$packet $line" else if [[ $packet =~ ^04 3E 2A 02 01 .{2} [0-9a-fA-F] ]]; then packet="$packet $line" else if [[ $packet =~ ^04 3E 2A 02 01 .{26} 02 01 .{14} 02 15 ]]; then UUID=`echo $packet | sed 's/^.{69}(.{47}).*$/1/'` MAJOR=`echo $packet | sed 's/^.{117}(.{5}).*$/1/'` MINOR=`echo $packet | sed 's/^.{123}(.{5}).*$/1/'` POWER=`echo $packet | sed 's/^.{129}(.{2}).*$/1/'` UUID=`echo $UUID | sed -e 's/ //g' -e 's/^(.{8})(.{4})(.{4})(.{4})(.{12})$/1-2-3-4-5/'` MAJOR=`echo $MAJOR | sed 's/ //g'` MAJOR=`echo "ibase=16; $MAJOR" | bc` MINOR=`echo $MINOR | sed 's/ //g'` MINOR=`echo "ibase=16; $MINOR" | bc` POWER=`echo "ibase=16; $POWER" | bc` POWER=$[POWER - 256] # Launch Couchbase Java Application To Save Beacon Transaction java -jar iot-couchbase-project.jar $UUID $MAJOR $MINOR $POWER fi capturing="" packet="" fi if [ ! "$capturing" ]; then if [[ $line =~ ^> ]]; then packet=`echo $line | sed 's/^>.(.*$)/1/'` capturing=1 fi doneelse sudo hcitool lescan --duplicates 1>/dev/null & sudo hcidump --raw | ./$0 parse $1fi |
Este script fue escrito por Radius Networks con la excepción de una línea:
1 |
java -tarro iot-couchbase-proyecto.tarro $UUID $MAYOR $MENOR $POTENCIA |
Tomamos la información analizada por el script y la enviamos a nuestra aplicación Java para guardarla. Este script se ejecutará continuamente hasta que se detenga manualmente.Arriba se muestra una animación de este proyecto en acción.
Conclusión
No ha estado tan mal, ¿verdad? Acabas de crear un simple proyecto de Internet de las Cosas (IoT) que escanea iBeacons y guarda la información en Couchbase. El Couchbase Lite Java SDK es casi idéntico al Couchbase Lite Android SDK. Con él podemos llevar nuestras aplicaciones Java a prácticamente cualquier cosa que soporte Java. GitHub.