A integração Helium e TagoIO te possibilita utilizar a segunda maior cobertura de LoRaWAN no Brasil juntamente com a maior plataforma cloud para IoT.
Fazer a integração pode parecer ser algo extremamente complexo, mas não é, na verdade é bem simples porém há margens para erros. Caso você não conheça a Helium ainda, recomendo ler esse post para que possa entender como a rede funciona e até entrar.
Integrando a Helium com a TagoIO
Para apontar para a TagoIO precisamos inicialmente adicionar um integrador no próprio console da Helium e dentro das integrações possíveis a Tago Já se faz presente, porém para conseguirmos adiciona-la faz-se necessário de uma autorização como mostra na imagem a seguir:

Essa autorização só é possível ser obtido do lado da Tago, para obtermos precisamos ir no painel da sua aplicação da Tago e clicar em ‘devices‘ depois ‘authorization‘.

Em seguida irá aparecer um painel similar a esse, porém irá ter todas as autorizações geradas. Como você não irá ter nenhuma, será necessário criar. É bastante importante que não adicione absolutamente nada no item riscado abaixo, após concluído essa tarefa, copie a autorização que você acabou de criar.

Feito isso, agora só é preciso voltar para Helium e colar essa autorização. Pronto sua integração está 100% concluída, mas há alguns passos que você precisa fazer ainda.
Criando um decodificador e formatador
Para deixarmos uma integração com a TagoIO funcional é preciso primeiramente decodificar o pacote que chega e formatar ele de acordo com um formato válido pela própria Tago. Mas qual formato é válido? Basta simplesmente olhar o próprio exemplo de uso do ‘maps‘ e replicar essa formatação, já é um ótimo ponto de partida.

Antes de continuarmos vamos entender essa estrutura fornecida, isso é extremamente importante para evitarmos erros posteriores principalmente a respeito do ‘lat‘ e ‘lng‘.
| Nome | Tipo |
| variable | String |
| value | String |
| <mesmo nome de variable> | Array |
| lat | Float |
| lng | Float |
É bastante importante cuidar do tipo da variável, pois se o decodificador enviar para a tago algum valor diferente do que já é, haverá problemas. Também é necessário colocar o mesmo nome de ‘variable‘ no array, pois essa será o identificador que iremos usar no ‘maps‘ para que ele possa pegar as posições.
Para usarmos o ‘maps’ e qualquer outra função dentro da Tago, é necessário ter uma variável para que a função consiga ler a entrada de valor. Mas como vamos adicionar uma variável na tago? Isso não será necessário, pois assim que for enviado pela primeira vez será automaticamente adicionado.
Gerando uma função customizada
Agora que já sabemos como é necessário formatar um json para o ‘maps‘, basta criar um decodificador para receber o pacote do ‘end device‘ para separar o ‘lat‘ do ‘lng‘. No lado do ‘end device‘ ele enviará dessa forma: “lat;lng“. O ponto e virgula realmente não é um método adequado, pois é um byte perdido para um caso como esse, mas para fins de teste ele tende a facilitar nossa vida.
Para criamos essa função personalizada basta ir no console da Helium ir na secção ‘function’ e em seguida criar uma função customizada e selecione a opção ‘Decoder‘, o nome pode ser qualquer um, mas particularmente coloquei o nome de ‘Decoder‘, depois copie e cole esse mesmo código abaixo:
function convertByteToString(hexString){
const byteArray = hexString.match(/.{1,2}/g).map(byte => parseInt(byte, 16));
return String.fromCharCode(...byteArray);
}
function extractBytes(hexString, delimiter) {
const bytes = hexString.split(delimiter);
const beforeDelimiter = bytes[0];
const afterDelimiter = bytes.slice(1).join(delimiter);
return [beforeDelimiter, afterDelimiter];
}
function Decoder(bytes, port, uplink_info) {
if(port != 1) return;
const a = bytes;
const b = a.map(byte => byte.toString(16).padStart(2, '0')).join('');
const extractedBytes = extractBytes(b, '3b');
return [
{
"variable": "device_location",
"value":"Elcereza IoT",
"location": {
"lat": parseFloat(convertByteToString(extractedBytes[0])),
"lng": parseFloat(convertByteToString(extractedBytes[1]))
}
}
];
}
Dois pontos importantes aqui: O primeiro é que essa ‘function Decoder(bytes, port, uplink_info)‘ do JS é uma função gerada a partir do tipo de uso, lembra que ao criarmos escolhemos ‘Decoder‘? Então […]. Ela funciona como uma função main, ou seja, tudo parte dela assim que essa função é chamada e seu retorno é apontado para uma integração; O segundo ponto é que temos as portas, para que serve isso? Basicamente a porta será por onde você vai separar cada pacote, impedindo que o pacote A seja tratado como pacote B.
Testando função de decodificação e formatação
Um dos pontos que adorei na Helium e TTN é que podemos criar nossas funções e testarmos para que possamos ou não validar o código feito. Para comprovar o funcionamento a função deve retornar um json idêntico ao da TagoIO e funcionar exclusivamente na porta 1, para testar basta inserir esses bytes ‘2d32312e3631333234303b2d34322e373432313230‘ e clicar em play, o retorno deve ser idêntico ao da imagem a seguir:

Por fim, vá em ‘flows‘ e faça as ligações necessárias para que o pacote enviado do ‘end device‘ seja destinado a uma função de decodificação e que sua saída seja para uma integração igual da imagem a seguir:

Criando uma simulação de rastreamento no End device
Para realmente comprovar o funcionamento 100% de tudo precisamos testar de forma completa, então nada melhor que simular um rastreamento com um ESP32 e um módulo LoRaWAN da Radioenge, porém para isso funcionar de fato é necessário que você já tenha cadastrado o ‘end device‘ tanto na Helium como também na TagoIO com conector “Custom Helium“.
Circuito para teste
Para testes vamos usar literalmente um ESP32 e um módulo LoRaWAN da Radioenge que é um hardware amplamente usado aqui, mas você pode repetir esse mesmo processo com qualquer outro hardware que funcionará da mesma forma.

- ESP32: Aliexpress;
- Módulo LoRaWAN Radioenge: Mercado Livre / Amazon.
Código de simulação
O código não tem nada complexo, nada além do que já foi mostrado em outros posts. De qualquer forma, por mais que seja uma simulação bastante simples você poderá modificar o código e adicionar um GPS e montar um rastreador LoRaWAN.
#include "LoRaWAN_Radioenge.h"
LoRaWAN_Radioenge LoRa(&Serial2);
void setup() {
Serial.begin(9600);
Serial2.begin(9600);
LoRa.begin(true);
LoRa.AJOIN(false);
LoRa.printParameters();
if(LoRa.JoinNetwork(OTAA, TTN, true, false))
LoRa.SendString("-25.613268;-46.742196", 1);
LoRa.pinMode(2, OUTPUT);
}
void loop() {
LoRa.SendString("-24.613368;-45.722196", 1);
delay(5000);
LoRa.SendString("-23.613128;-44.752115", 1);
delay(5000);
LoRa.SendString("-23.613020;-43.782110", 1);
delay(5000);
LoRa.SendString("-21.613240;-42.742120", 1);
delay(5000);
}
Funcionamento da integração da Helium e TagoIO
Diferentemente de outras postagens, esse tópico de funcionamento terá que ser um pouco diferente nesse caso, pois você se lembra que anteriormente foi dito que a Tago reconhece automaticamente as variáveis? Pois então, usaremos essa característica para inserirmos uma variável.
Então primeiramente vamos rodar o código do ‘end device‘ e ficar analisando o ‘Live inspector‘, configurar o ‘maps‘ e por fim ver os dados de localização em tempo real.
Testando conexão do end device com a rede
Nesse teste vamos primeiramente analisar a comunicação de tudo, então deixe o seu ‘end device‘ rodando por um tempo e fique analisando o ‘live inspector‘ se houver qualquer registro de comunicação, será exibido lá igual no vídeo a seguir:
Configurando e usando o maps da TagoIO
Se o passo anterior funcionou então será possível fazer este passo agora, para isso vá no seu painel do seu deshboard e adicione o ‘maps‘ caso ainda não tenha adicionado.

Depois clique em editar, ‘Data from‘, ‘Add new Data‘, selecione o device, o nome da variável como ‘device_location‘ e por fim salve. Agora é só deixar a aplicação rodando e ver os pontos aparecendo no mapa.
