A Internet das Coisas (IoT) está se tornando a grande moda ultimamente. A capacidade de criar qualquer dispositivo mecânico, por exemplo, relógios, televisores, termostatos, e fazer com que eles se comuniquem pela Internet é a era moderna. Nessa era moderna, uma coisa que permanece consistente é a necessidade de transferir e armazenar dados. Como fazer isso em um dispositivo de IoT?
Servidor Couchbase existe para armazenar grandes quantidades de dados corporativos e Couchbase Mobile existe para armazenar dados localmente em dispositivos móveis e sincronizá-los com o Couchbase Server quando possível. Onde a IoT se encaixa nisso? Os dispositivos de IoT não são servidores e, tecnicamente, não são dispositivos móveis.
Você sabia que muitos dispositivos de IoT são capazes de executar aplicativos Java? Na verdade, existe um SDK do Couchbase Lite para Java. Esse não é um SDK para Android ou iOS. É um SDK para aplicativos Java em geral. Com isso, podemos usá-lo para a IoT.
O escopo do projeto
Agora que sabemos que isso é possível, vamos pensar em um exemplo legal de IoT e executá-lo. Vamos usar um exemplo de iBeacon com o seguinte cenário.
Digamos que você queira rastrear seu animal de estimação quando estiver fora de casa. Você quer saber por onde seu animal de estimação passa em sua casa e a que horas do dia. Então, você decide conectar um iBeacon à coleira do seu animal de estimação e instalar alguns scanners de IoT em sua casa.
Assim, com o iBeacon conectado e os gateways de IoT instalados, os dispositivos de IoT podem procurar iBeacons continuamente. Quando um iBeacon entra no alcance, um registro de data e hora, juntamente com o local e as informações do beacon, pode ser salvo e carregado no seu servidor. Posteriormente, você pode criar seu próprio painel com um mapa de calor para entender melhor seus dados.
Então, o que é necessário para experimentar esse projeto?
Os requisitos
Há alguns requisitos no âmbito do software e do hardware. Eles podem ser vistos abaixo:
- Mínimo de um (1) Gateway IoT da Intel
- Mínimo de um (1) Gimbal sinalizador de proximidade
- Java 1.7+
- Maven
- Gateway de sincronização do Couchbase
Embora haja um requisito de hardware, a marca do hardware é um pouco flexível. Listei o Intel IoT Gateway e os beacons de proximidade Gimbal porque, além de serem incrivelmente acessíveis, foram os que usei ao criar meu aplicativo. Para aproveitar ao máximo este exemplo, é melhor ter vários beacons e gateways, mas um será suficiente para a criação de protótipos.
Veja a seguir como esse projeto será realizado.
O código-fonte completo desse projeto pode ser encontrado em GitHub.
Salvando seus dados com o Couchbase
Antes de entrarmos no trabalho de IoT e beacon, seria uma boa ideia definir nosso modelo de dados e criar nosso aplicativo Java. Nesse cenário, que é um dos muitos, o aplicativo Java não fará a varredura de beacons. Ele será responsável apenas por salvar os dados.
O modelo de dados do beacon do Couchbase
Se você não conhece os iBeacons, eles não oferecem nada além de alguns valores de cadeia de caracteres e inteiros em sua transmissão. Eles não podem ser conectados e não podem ver outros dispositivos. Tudo o que fazem é transmitir. Dito isso, os valores transmitidos são os seguintes:
- UUID
- Maior
- Menor
- Potência
O UUID, Maiore Menor oferecem informações exclusivas sobre um determinado beacon. Os três valores podem formar uma chave composta que é útil para consultas posteriores.
Vamos pensar em como armazenaremos os dados do beacon sempre que um for detectado.
Poderíamos criar um novo documento JSON sempre que um beacon fosse detectado. Os documentos individuais podem ter a aparência de algo como:
1 2 3 4 5 6 7 8 9 |
{ "uuid": "32342342", "major": 1, "menor": 0, "createdAt": 1932847298, "gatewayDevice": "cozinha" } |
Não há nada de errado com a abordagem acima. No entanto, você pode acabar com grandes quantidades de documentos, dependendo de quantos beacons estiverem circulando. Novamente, o Couchbase foi projetado para lidar com isso, portanto é uma questão de preferência. Na verdade, prefiro manter todas as transações de beacon para um beacon específico no mesmo documento, dessa forma:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
{ "uuid": "23423423", "major": 1, "menor": 0, "beaconStatus": [ { "createdAt": 234234321234, "gatewayDevice": "cozinha" }, { "createdAt": 12312323544, "gatewayDevice": "garagem" } ] } |
No segundo cenário, toda vez que um beacon é descoberto, o Couchbase é consultado com base na chave composta e, em seguida, os dados de status são adicionados à matriz de status.
Adição das dependências do Maven
Como este projeto Java será baseado no Maven, o pom.xml precisa que certas dependências sejam atendidas. Adicione a seguinte dependência ao seu arquivo Maven para incluir o Couchbase Lite Java SDK em seu projeto:
1 2 3 4 5 6 7 |
com.couchbase.leve couchbase-leve-java 1.2.0 |
A dependência acima permitirá que você armazene documentos do Couchbase localmente em seu dispositivo IoT e os sincronize com o Couchbase Sync Gateway.
Criação de uma classe de beacon
Como trabalharemos com iBeacons, faz sentido criar uma classe Java Beacon. Essa classe deve ser responsável por salvar os dados do beacon, bem como carregá-los no caso de uma consulta. Vamos começar dando uma olhada em como é o carregamento:
1 2 3 4 5 6 7 8 9 10 |
privado Documento carregar(Banco de dados banco de dados) { Documento documento = nulo; tentar { Ver beaconView = banco de dados.getView("beacons"); beaconView.setMap(novo Mapeador() { @Substituir público vazio mapa(Mapa<Cordas, Objeto> documento, Emissor emissor) { Lista<objeto> chaves = novo ArrayList<objeto>(); chaves.adicionar(documento.obter("uuid")); chaves.adicionar(documento.obter("major")); chaves.adicionar(documento.obter("menor")); emissor.emitir(chaves, documento.obter("beaconStatus")); } }, "1"); Consulta consulta = beaconView.createQuery(); Lista<objeto> chaves = novo ArrayList<objeto>(); Lista<objeto> chave = novo ArrayList<objeto>(); chave.adicionar(este.uuid); chave.adicionar(este.principais); chave.adicionar(este.menor); chaves.adicionar(chave); consulta.setKeys(chaves); QueryEnumerator resultado = consulta.executar(); para (Iterador ele = resultado; ele.hasNext(); ) { QueryRow fila = ele.próxima(); documento = fila.getDocument(); } } captura (Exceção e) { e.printStackTrace(); } retorno documento;}A lote é acontecendo em o acima carregar assim deixarComo o Couchbase Lite faz consultas com base em exibições do MapReduce, primeiro criamos uma exibição. Lembre-se de que planejamos usar uma chave composta, e é por isso que criamos uma lista de chaves. Os únicos dados que precisamos que sejam retornados se uma correspondência for encontrada é o array de status que contém o registro de data e hora e as informações do gateway. Como estamos em uma classe Java personalizada, vamos's assumir que nóscapturaram o <strong>uuid</strong>, <strong>principais</strong>e <strong>menor</strong> valores em algum momento. Nósll construir o chave listas fora de o valores e definir o consulta para uso eles com o <código>consulta.setKeys</código> função.Depois de o consulta corridas nósfará um loop pelos resultados. Estamos esperando apenas um resultado, que pode ser assegurado pelo uso de uma função de limite antes de executar a consulta. O resultado retornado da consulta, se houver, será retornado para o que quer que chame a função load. Nesse caso, a função save a chama antes de salvar.s tomar a olhar em o salvar função de nosso farol classe. <pré><código>público Cordas salvar(Banco de dados banco de dados) { Cordas docId = ""; Mapa<Cordas, Objeto> propriedades = novo HashMap<Cordas, Objeto>(); ArrayList beaconStatusList = novo ArrayList(); Documento documento = este.carregar(banco de dados); se(documento != nulo) { propriedades.putAll(documento.getProperties()); beaconStatusList = (ArrayList) propriedades.obter("beaconStatus"); } mais { documento = banco de dados.createDocument(); propriedades.colocar("uuid", este.uuid); propriedades.colocar("major", este.principais); propriedades.colocar("menor", este.menor); } beaconStatusList.adicionar(este.beaconStatus); propriedades.colocar("beaconStatus", beaconStatusList); tentar { docId = documento.putProperties(propriedades).getDocument().getId(); } captura (Exceção e) { e.printStackTrace(); } retorno docId;} |
Na função salvar, primeiro queremos carregar os documentos para ver se eles existem. Se existir um documento para as informações do beacon, queremos adicioná-lo a ele; caso contrário, podemos simplesmente criar um novo documento. Depois de reconstruirmos nosso documento do Couchbase, seja do zero ou a partir de dados de documentos existentes, nós o salvamos por meio da função putProperties
Nesse ponto, os dados do beacon podem ser salvos e lidos no banco de dados local do Couchbase Lite.
Sincronização com o Couchbase Sync Gateway
É mais do que provável que você trabalhe com mais de um gateway de escaneamento de IoT. Por isso, os dados do beacon (no modelo de documento incorporado) precisarão ser sincronizados entre os dispositivos de IoT. Agora podemos levar nosso código de salvamento e carregamento para o próximo nível:
1 |
tentar { gerente = novo Gerente(novo JavaContext("dados"), Gerente.DEFAULT_OPTIONS); banco de dados = gerente.getDatabase("iot-project" (projeto iot)); URL url = novo URL("http://192.168.1.174:4984/beacons-iot/"); final Replicação empurrar = banco de dados.createPushReplication(url); Replicação puxar = banco de dados.createPullReplication(url); puxar.setContinuous(falso); empurrar.setContinuous(falso); puxar.addChangeListener(novo Replicação.ChangeListener() { @Substituir público vazio alterado(Replicação.ChangeEvent evento) { se(evento.getSource().getStatus() == Replicação.Status da Replicação.REPLICATION_STOPPED) { farol.salvar(banco de dados); empurrar.iniciar(); } } }); empurrar.addChangeListener(novo Replicação.ChangeListener() { @Substituir público vazio alterado(Replicação.ChangeEvent evento) { se(evento.getSource().getStatus() == Replicação.Status da Replicação.REPLICATION_STOPPED) { Sistema.saída(1); } } }); puxar.iniciar();} captura (Exceção e) { e.printStackTrace();} |
Esse código deve existir em outra classe, de preferência na classe que contém o principal
função. Essencialmente, ela inicializará a conexão com o banco de dados local, configurará os replicadores push e pull para uma instância do Sync Gateway em execução remota e iniciará o processo de salvamento e sincronização. Quando executarmos o aplicativo, primeiro baixaremos todos os documentos de beacon relevantes do servidor. Com o uso de ouvintes de alterações nos replicadores, podemos esperar para salvar somente depois que terminarmos de baixar as alterações. Para evitar que o aplicativo Java permaneça aberto após o envio, adicionamos um ouvinte que fechará o aplicativo após a conclusão.
Resolvendo os erros de dependência do SQLite
Ao criar esse aplicativo com o Maven, não deve haver nenhum problema. No entanto, dependendo do dispositivo de IoT que você implantar, poderá haver um problema de dependência de biblioteca. Há muitas arquiteturas diferentes em circulação. Um exemplo de erro pode ser parecido com o seguinte:
1 |
Biblioteca não encontrado: /nativo/linux/i386/libsqlite3.assim |
Isso pode ser facilmente resolvido extraindo o arquivo JAR, renomeando um dos diretórios e, em seguida, empacotando-o novamente em um JAR. Para ser mais específico, para extrair seu arquivo JAR, execute o seguinte comando:
1 |
frasco xvf [nome do arquivo].frasco |
A partir dos documentos e arquivos extraídos, renomeie o arquivo /nativo/linux/x86 para o diretório /nativo/linux/i386. Feito isso, você pode reempacotar o arquivo JAR e reimplantá-lo.
1 |
frasco cvfm [nome do arquivo].frasco META-INF/MANIFESTAR.MF . |
O comando acima reempacotará o arquivo JAR para você.
Verificação de iBeacons e acompanhamento de seu status
Como mencionado anteriormente, o aplicativo Java não é responsável pela detecção de iBeacons. Ele é responsável apenas por salvar os dados. Em vez disso, usaremos algumas ferramentas que vêm pré-instaladas em um sistema operacional Linux.
Varredura com ferramentas do Linux
A maioria das distribuições Linux vem com o hcitool e hcidump aplicativos. Os hcitool permitirá que você procure dispositivos bluetooth que estejam dentro do alcance. Você executaria algo como o seguinte:
1 |
hcitool lescan |
O procedimento acima retornaria informações básicas sobre os dispositivos encontrados em uma varredura. Em seguida, você usaria a função hcidump para mostrar tudo e qualquer coisa sobre os dados do Bluetooth que foram descobertos. Algo como isso mostraria os dados brutos:
1 |
hcidump --bruto |
O problema é que os dados são muito brutos. Não é algo com que possamos trabalhar em sua forma atual. Não poderíamos usá-los para dar sentido aos dados do iBeacon.
Simplifique o processo com uma ferramenta da Radius Networks
É aqui que um script de Redes Radius entra em ação. Há um script chamado Varredura iBeacon que fará uso de hcitool e hcidumpmas analisado e limpo. Ele pode ser visto abaixo:
1 |
#!/bin/bash# iBeacon Scan by Radius Networks# Modificado por Nic Raboy no 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] ]]; então packet="$packet $line" else if [[ $packet =~ ^04 3E 2A 02 01 .{26} 02 01 .{14} 02 15 ]]; então 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})(.{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] # Inicie o aplicativo Java do Couchbase para salvar a transação do beacon java -jar iot-couchbase-project.jar $UUID $MAJOR $MINOR $POWER fi capturing="" packet="" fi fi if [ ! "$capturing" ]; then if [[ $line =~ ^> ]]; then packet=`echo $line | sed 's/^>.(.*$)/1/'` capturando=1 fi fi doneelse sudo hcitool lescan --duplicates 1>/dev/null & sudo hcidump --raw | ./$0 parse $1fi |
Divulgação completa de que esse script foi escrito pela Radius Networks, com exceção de uma linha:
1 |
java -frasco iot-couchbase-projeto.frasco $UUID $MAIOR $MENOR $PODER |
Estamos pegando as informações analisadas pelo script e canalizando-as em nosso aplicativo Java para serem salvas. Esse script será executado continuamente até ser interrompido manualmente.Acima está um exemplo de animação desse projeto em ação.
Conclusão
Isso não foi tão ruim, certo? Você acabou de criar um projeto simples de Internet das Coisas (IoT) que escaneia iBeacons e salva as informações no Couchbase. O SDK Java do Couchbase Lite é quase idêntico ao SDK Android do Couchbase Lite. Com ele, podemos levar nossos aplicativos Java para praticamente qualquer coisa que suporte Java. Um projeto de exemplo completo e funcional pode ser visto em GitHub.