
Quer aprender a montar uma operação de IoT na nuvem totalmente gerenciada, com auto-scaling e serverless?
Nesta série de três posts IoT on GCP, vamos percorrer um fluxo completo de IoT: do registro do dispositivo ao streaming e armazenamento de longo prazo dos dados, até a análise e visualização dessas informações.
Boas práticas de IoT em escala de produção
Ao terminar a Parte Um, você vai saber registrar com segurança milhões de dispositivos IoT que enviam dados de telemetria para o seu ambiente Google Cloud.
Esta é a primeira de uma série de três partes:
- O armazenamento e a visualização desses streams de alto throughput serão tratados na Parte Dois;
- A construção de um modelo funcional de machine learning sobre dados de IoT virá na Parte Três.
Ao longo da série, usaremos o GCP como provedor de nuvem e dispositivos Raspberry Pi com sensores de temperatura como nossos exemplos de dispositivos IoT.
Visão geral
Este conteúdo está dividido nas seguintes seções:
- Configuração de software e hardware do Raspberry Pi
- Registro de dispositivos e provisionamento de credenciais na prática
- Teste de conectividade dos dispositivos e streaming de dados de temperatura
- Ressalvas sobre as funcionalidades de IoT do Google Cloud
- Armazenamento dos dados em streaming (Parte Dois)
- Visualização dos dados em streaming (Parte Dois)
- Construção de um modelo de machine learning eficaz com dados de IoT (Parte 3)
Para acompanhar este artigo, basta ter experiência com Bash e Python e uma noção básica de como navegar pelo Google Cloud Console.
Configurando o software e o hardware do Raspberry Pi
Primeiro, coloque alguns dispositivos Raspberry Pi para rodar — vou usar Pi 3. Recomendo o Raspbian OS Imager para automatizar a instalação do sistema operacional em cartões microSD.
Instale os pacotes Python
Depois de chegar à área de trabalho e atualizar o dispositivo, execute o comando a seguir para instalar o SDK específico do Google Cloud IoT:
pip3 install -U pyjwt paho-mqttAntes de seguir, vale entender por que estamos instalando o paho-mqtt em vez do SDK Python de uso geral google-api-python-client do Google Cloud. O SDK Python mais comum, assim como a CLI gcloud do GCP, é baseado em HTTP. Esse protocolo é útil para executar a maioria das ações com agilidade. No entanto, o HTTP não é adequado para enviar mensagens em conexões de longa duração com alta probabilidade de conectividade intermitente, em que os dados fluem majoritariamente do dispositivo para fora.
O MQTT é um protocolo usado em IoT, por meio de pacotes como o paho-mqtt, justamente porque foi projetado para que um dispositivo publique mensagens com frequência e receba mensagens esporadicamente, mesmo diante de problemas de conectividade.
Conecte um sensor digital de temperatura
Agora que seu Raspberry Pi tem os pacotes Python necessários, é hora de conectar um sensor digital de temperatura a ele. Recomendo este sensor DS18B20 caso queira acompanhar o artigo.
Você também vai precisar dos seguintes itens para conectar o sensor ao Raspberry Pi:
- Mini protoboards
- Fios jumper para protoboard
- Kit variado de resistores (precisamos de um resistor de 4,7K Ohm)
Se precisar esperar a chegada desses itens, fique à vontade para continuar lendo o artigo: vamos disponibilizar um script para fazer streaming de temperaturas simuladas.
Caso já tenha os componentes em mãos, os primeiros cinco minutos deste tutorial mostram como conectar o sensor ao Raspberry Pi e validar que ele está recebendo valores de temperatura.
Além do processo descrito no tutorial acima, recomendo adicionar o seguinte ao /etc/modules para garantir que os módulos onewire sejam carregados na inicialização, evitando rodar modprobe a cada reboot:
w1-gpiow1-thermRegistrando seus dispositivos IoT
Veja a seguir um exemplo completo e funcional de como configurar o IoT Registry com dispositivos registrados de forma segura, a partir dos quais faremos streaming de dados de temperatura para a plataforma Google Cloud IoT.
Crie um registry para seus dispositivos
No Google Cloud Console:
- Crie um novo projeto (por exemplo, "IoTTempStreaming")
- Acesse o serviço IoT Core para habilitar a IoT API
- Clique em "Create registry" para criar um registry e adicionar seus dispositivos IoT.
Dispositivos IoT que enviam dados ao GCP só conseguem encaminhar mensagens ao IoT Core se forem validados como dispositivos credenciados no IoT Registry, o que torna a criação do registry uma etapa essencial.
Um ambiente IoT Core novinho em folha esperando para ser preenchido com mensagens
Crie um tópico no Pub/Sub
As mensagens enviadas ao IoT Core — junto com metadados críticos, como o deviceId exclusivo do dispositivo — são encaminhadas nos bastidores para um "tópico" no Pub/Sub, o sistema de fila de mensagens do Google Cloud, totalmente gerenciado, com auto-scaling e serverless.
Por isso, também vamos criar tópicos do Pub/Sub a partir do prompt do IoT Registry, para que nossos dados de telemetria cheguem ao Pub/Sub e sigam para o processamento downstream.
Siga estes passos para criar um tópico do Pub/Sub a partir do prompt do IoT registry:
- Defina seu Registry ID como "RaspberryPiDevices" na região us-central1
- Crie um tópico do Pub/Sub chamado "sensordata", para onde as mensagens de telemetria IoT serão enviadas por padrão.
- Em "Additional topics", crie um novo tópico do Pub/Sub chamado "temperature", para onde irão as mensagens publicadas em uma subpasta de tópico IoT — também chamada "temperature".
Essa configuração garante que apenas as mensagens de temperatura publicadas em uma subpasta IoT específica caiam no tópico "temperature" do Pub/Sub, enquanto todos os outros eventos de telemetria (inesperados) vão para o tópico padrão "sensordata".
Também recomendo expandir as opções avançadas e permitir somente o protocolo MQTT, desmarcando o HTTP:
Configuração do IoT Core Registry para streaming de dados de sensor de temperatura
Após a criação, seu registry deve ficar parecido com este:
Configuração bem-sucedida do IoT Core Registry
Crie um dispositivo registrado
Com o registry de dispositivos pronto, vamos criar um dispositivo registrado.
Para começar, vamos precisar de (1) um par de chaves pública-privada associado ao dispositivo e (2) o certificado raiz do Google.
Os comandos a seguir devem ser executados em um Raspberry Pi para gerar chaves Elliptic Curve e baixar o certificado raiz do Google (com base na documentação do Google Cloud). As chaves EC ocupam menos espaço do que as chaves RSA tradicionais e ajudam os dispositivos IoT a manter um throughput ideal em áreas com conectividade ruim:
$ mkdir -p /home/pi/GCP/iot_keys/$ cd /home/pi/GCP/iot_keys/$ wget$ openssl ecparam -genkey -name prime256v1 -noout -out ec_private.pem$ openssl ec -in ec_private.pem -pubout -out ec_public.pem$ cat ec_public.pem$ cd ../Depois de executar os comandos acima:
- Copie a chave pública exibida no terminal
- Vá até o IoT Registry e acesse Devices
- Clique em Add Device
- Dê um nome ao dispositivo (por exemplo, "device1") e cole a chave pública ES256 em Authentication, conforme abaixo.
- Clique em Create
Registro de dispositivo IoT solicitando uma chave Elliptic Curve
Depois de criadas, as credenciais associadas a um dispositivo registrado no IoT core já podem ser usadas no Raspberry Pi!
Anote o Numeric ID atribuído ao dispositivo, o Project ID e o Registry ID.
Com esses valores, mais as chaves e o certificado raiz do Google no dispositivo, precisamos criar um arquivo de configuração chamado gcp_iot_config.txt. Ele define os detalhes de autenticação e do endpoint IoT que cada dispositivo vai usar. Mais adiante no artigo, descrevemos um script Python que faz streaming de valores de temperatura usando esse arquivo de configuração:
$ pwd/home/pi/GCP/$ cat gcp_iot_config.txt[SETTINGS]KEY_PATH = /home/pi/GCP/iot_keys/PRIVATE_KEY = ec_private.pemGOOGLE_ROOT_CERT = roots.pemREGISTRY_ID = <REGISTRY_ID>DEVICE_ID = <DEVICE_NUMERIC_ID>REGION = us-central1PROJECT_ID = <PROJECT_ID>E voilà! Seu dispositivo já pode fazer streaming seguro de dados de telemetria para um tópico do Pub/Sub via plataforma de autenticação IoT Core do GCP. Repita o processo acima para gerar credenciais únicas e registrar cada novo dispositivo.
Teste a conectividade do dispositivo
Vamos testar a conectividade do dispositivo executando o script a seguir, chamado "publish_temps.py", que faz streaming de valores de temperatura reais ou simulados, dependendo de qual linha (107 ou 108) estiver comentada.
(O script é uma adaptação de dois scripts de exemplo do Google Cloud: #1 e #2)
$ pwd/home/pi/GCP/$ ./publish_temps.pyhttps://gist.github.com/doit-mattporter/7e548158a5dc03b3674282cda19ef663
Há bastante coisa acontecendo aqui — recomendo fortemente revisar o código para entender melhor como ele se conecta de forma segura e faz o streaming dos dados.
Ao executar o script, você deve ver uma saída parecida com esta:
Valores reais de temperatura sendo enviados ao GCP IoT Core via MQTT
Se você executar este script no boot via crontab (com um sleep de 30s antes, para dar tempo de os módulos onewire carregarem), o dispositivo IoT retoma o streaming em qualquer reboot, esperado ou não:
$ crontab -e@reboot sleep 30 && /home/pi/GCP/publish_temps.py -c /home/pi/GCP/gcp_iot_config.txt >> /home/pi/GCP/publish_temps.log 2>&1Repita os processos de onboarding e streaming para todos os Raspberry Pi distribuídos pela sua casa. Você está no caminho certo para trabalhar com dados IoT em escala!
Confirme que os dados estão sendo transmitidos
Vamos verificar rapidamente se as mensagens estão chegando ao Google Cloud, observando os dados de telemetria no Pub/Sub.
- Crie uma assinatura no Pub/Sub para o tópico "temperature"
- Acesse a assinatura
- Clique em View Messages e selecione o radio button Pull
Você vai ver as mensagens chegando, com as informações de temperatura e timestamp no corpo, além dos metadados de atributo que identificam de forma única qual dispositivo está enviando esses valores. Esses metadados são úteis não só para analytics e dashboards de usuários finais, mas também para identificar e bloquear dispositivos abusivos ou hackeados.
Criação de uma assinatura no Pub/Sub para visualizar as mensagens de telemetria de temperatura recebidas
Veja a seguir como fica uma assinatura para o tópico de temperatura:
Visualizando mensagens de uma assinatura do Pub/Sub no tópico "temperature"
Depois de clicar em "PULL", você verá as mensagens e seus atributos:
Dados de temperatura chegando a um tópico do Pub/Sub e a uma assinatura do Pub/Sub: corpo da mensagem
Dados de temperatura chegando a um tópico do Pub/Sub e a uma assinatura do Pub/Sub: atributos de identificação exclusiva
Se você chegou até aqui, parabéns (sério mesmo)! Por mais empolgante que seja ver dados reais de dispositivos IoT chegando ao Pub/Sub, ainda mal arranhamos a superfície.
Para realmente extrair valor desses dados, precisamos transformá-los (quando fizer sentido), movê-los ou carregá-los em batch para um data warehouse e analisá-los. Tudo isso precisa rodar em um ecossistema de serviços do GCP que sustente esse fluxo de forma confiável, em escala e com bom custo-benefício, em todos os estágios — do teste inicial ao uso em produção em escala de petabytes e além — com pouca ou nenhuma manutenção de infraestrutura. Quer ver como? Fique de olho nas partes dois e três!
A seguir: armazenamento e visualização
Fique de olho na parte dois, em que vou abordar os serviços ideais de ETL, armazenamento e visualização que tornam relativamente simples colocar em prática grandes volumes de dados IoT em streaming.
Ressalvas sobre as funcionalidades de IoT do Google Cloud
Tratamento aprimorado do deviceId nos serviços totalmente gerenciados do GCP
Você deve ter percebido que o script Python envia um par chave:valor device_id no corpo da mensagem, o que duplica o atributo deviceId presente na mensagem do Pub/Sub, atribuído pelo IoT Core via associação da mensagem com o par chave-valor exclusivo do dispositivo que faz o streaming.
Por que enviar um device_id que poderia ser facilmente forjado num dispositivo hackeado, contaminando o data warehouse quando essas mensagens forem movidas para o armazenamento de longo prazo?
Bem, estou me adiantando, mas, como veremos na Parte Dois, existe um workflow conveniente, totalmente gerenciado, com auto-scaling e majoritariamente serverless, capaz de transformar e mover mensagens do Pub/Sub para o BigQuery usando o Dataflow, a versão totalmente gerenciada do Apache Beam pelo Google Cloud.
Infelizmente, o template padrão "Pub/Sub-to-BigQuery" disponível no Dataflow, escrito pelo GCP, não oferece nenhuma forma de mover atributos de mensagens para o BigQuery; só o conteúdo do corpo da mensagem é movido. Confirmei com vários engenheiros do GCP que não dá para escrever uma UDF Javascript customizada nos templates padrão para incluir atributos de mensagem em destinos do Dataflow como o BigQuery. A alternativa — escrever jobs em Java no Dataflow, do zero ou modificando os templates existentes do GCP — exige bastante tempo e manutenção contínua dos templates, algo que imagino que a maioria dos clientes do GCP não vai querer encarar.
Ou seja, por padrão, não há um meio simples e seguro de associar uma mensagem IoT que chega ao Pub/Sub e é encaminhada aos destinos finais de dados ao deviceId dessa mensagem.
Levei essa lacuna ao GCP e, desde então, eles abriram uma solicitação pública de funcionalidade para garantir que os templates padrão passem a repassar esses valores valiosos — e absolutamente necessários — para suportar o caso de uso de IoT. Vou atualizar o artigo assim que essa FR for atendida; até lá, para fins de demonstração, é muito mais simples testar o uso do device_id enviando-o pelo corpo da mensagem do que reescrever um template do Dataflow que deveria existir por padrão.
Como eu provisionaria, idealmente, credenciais únicas por dispositivo?
O processo de registro de um único dispositivo IoT costuma ser descrito assim:
- Criar, no GCP, um par de chaves pública-privada com permissões de IoT
- Provisionar e instalar esses arquivos no dispositivo, na fábrica
- A fábrica registra essas credenciais no IoT Registry
- Habilitar o par de chaves para fazer chamadas à IoT API que enviam dados em streaming para a nuvem.
Por si só, esse arranjo não é ideal, já que cenários reais de IoT envolvem milhões de dispositivos enviando dados para um ambiente de nuvem. Cada dispositivo dessa frota precisa ter um conjunto único de credenciais para que, se um deles ou suas credenciais do Google Cloud forem comprometidos e usados de forma ilegítima, esse conjunto possa ser desativado sem impactar os demais dispositivos.
O GCP oferece essa funcionalidade e, como mostra o script acima, também permite restringir um dispositivo a publicar apenas em um tópico exclusivo dele. Mas, com as metodologias de provisionamento de credenciais disponíveis hoje, coordenar criação, deploy e registro de chaves para milhões de dispositivos é um desafio.
Como simplificar ao máximo a criação de credenciais específicas por dispositivo? Dá para fazer isso sem gerar milhões de certificados antecipadamente e coordenar a colocação única de cada um nos dispositivos durante a fabricação? Você quer mesmo depender de um fabricante para instalar esses arquivos de forma confiável e sem duplicação?
Como alternativa, é possível registrar e credenciar dispositivos sem exigir que o fabricante chame a API do seu IoT Registry para criar novas credenciais sob demanda quando um dispositivo desce a linha de produção para receber software e credenciais? E se a conexão com o API Gateway que sustenta o registro IoT cair? O que acontece com a linha de produção?
Prefiro evitar esses caminhos: são mais complexos, mais propensos a erro e impõem um peso desnecessário ao fabricante.
Um sistema seguro e razoavelmente escalável de registro de dispositivos que eu gostaria de ver no GCP seguiria estas diretrizes:
- Cria-se um único certificado IoT, instalado em todos os dispositivos. Esse certificado, apelidado de "bootstrap", estaria associado a uma política de permissões que só permite ao dispositivo (a) emitir uma solicitação para criar e recuperar credenciais específicas do dispositivo, caso a solicitação seja aprovada, e (b) adicionar a si mesmo ao IoT Registry de dispositivos.
- A plataforma GCP IoT Core, ao receber e aprovar a solicitação de criação de credenciais, gera um novo par de chaves. As permissões IoT associadas — como o Google Cloud já faz hoje — devem permitir que o dispositivo publique mensagens apenas em um tópico exclusivo dele.
- A criação de credenciais únicas por dispositivo deve passar por uma etapa de validação. Seria uma Cloud Function escrita por você, exigindo identificadores únicos na solicitação, para que possam ser checados contra uma whitelist (por exemplo, lista de números de série fabricados ou endereços MAC usados) e/ou uma blacklist (por exemplo, números de série associados a dispositivos comprometidos, abusivos ou já registrados).
- Se a solicitação do certificado único do dispositivo for aprovada na validação, o dispositivo é incluído no IoT Registry e os novos arquivos de credenciais são entregues a ele para uso no streaming de dados.
Com esse fluxo, o fabricante de dispositivos IoT só precisaria entregar a cada unidade o certificado de bootstrap. O par de chaves exclusivo do dispositivo, que viabiliza o streaming de dados, poderia ser criado e obtido ainda dentro da planta industrial, se desejado, ou depois, quando o dispositivo já estivesse com o usuário final.
Independentemente de quando as credenciais forem obtidas, o fabricante simplesmente faria o bootstrap, no dispositivo, do software fornecido por você, que executa o processo de criação do par de chaves único — baseado no certificado de bootstrap — quando:
- O dispositivo é ligado
- Há conexão com a Internet, e
- É detectado que o par de chaves único do dispositivo está faltando
Infelizmente, essa funcionalidade ainda não existe (por enquanto). Mas, fora a questão do registro em massa de dispositivos, a oferta de IoT do Google Cloud — combinada com os serviços downstream totalmente gerenciados de processamento de mensagens (abordados na Parte Dois) — forma uma solução nativa da nuvem robusta, segura e fácil de escalar no universo IoT.