LSM110A - Acessando a rede pública LoRaWAN da American Tower / EveryNet - AU915
O objetivo deste BLOG é verificar se o LSM110A consegue se conectar na rede American Tower / EveryNet e enviar pacotes.
ATENÇÃO: PARA UTILIZAR SERVIÇOS DA EVERYNET, CONTATE E PEÇA OS BROKERS.
A American Tower é uma multi nacional presente em mais de 16 paises, com de 160.000 sites no mundo onde ela aluga espaço para as operadoras colocarem suas torres celulares e rádios. No Brasil ela possui mais de 19.000 sites, tendo uma ampla presença geográfica. Ela decidiu de forma pioneira no Brasil lançar uma rede LoRaWAN junto com a EveryNet, de forma a permitir o avanço do IoT.
O cliente que tem um produto que siga o padrão LoRaWAN pode contratar o serviço de dados da American Tower / EveyNet de forma a se preocupar somente com seus devices e aplicação, sem ter que se focar na infra-estrutura e gateways.
OTAA
• Vantagem: a rede gera e envia as chaves de criptografia; isto torna mais seguro. Devido ao maior nível de segurança, o OTAA é o método mais utilizado em IoT / LoRaWAN.
• AppEUI: Este é um identificador de aplicativo exclusivo usado para agrupar objetos. este
endereço, 64 bits, é usado para classificar os dispositivos periféricos por aplicação. Essa configuração pode seja ajustado.
• DevEUI: Este identificador, configurado de fábrica, torna cada objeto único. Em princípio, esta
configuração não pode ser ajustada.
• AppKey: esta é uma chave secreta compartilhada entre o dispositivo periférico e a rede. É usado para determinar as chaves da sessão. Essa configuração pode ser ajustada.
Concentre-se na OTAA
O Servido de Rede é o componente de software encarregado de estabelecer uma conexão com os objetos e gerenciando o núcleo da rede. Durante a conexão OTAA, e supondo que o dispositivo esteja autorizado a conectar-se a rede, a rede troca chaves de criptografia específicas da sessão com o núcleo da rede. O Servidor de Rede então aloca informações específicas para a sessão e as envia para o aparelho periférico:
• DevAddr: Endereço lógico (equivalente a um endereço IP) que será usado para todos comunicação subseqüente.
• NetSKey (chave de sessão de rede): chave de criptografia entre o objeto e o operador usado para transmissões e para validar a integridade das mensagens.
• AppSKey (chave de sessão do aplicativo): chave de criptografia entre o objeto e operador (através da aplicação) utilizado para as transmissões e para validar a integridade das mensagens
1.1 Entrando na EveryNet
1.2 Adicionar um dispositivo EndDevice LoRaWan
Esta seção mostra como adicionar um dispositivo EndDevice LoRaWAN à rede LoRaWAN e ver os dados pelo web site da EveryNet
Usamos o LSM110A como um dispositivo de referência - a configuração para outros dispositivos LoRaWAN será semelhante.
Passo 1: Criar uma definição de dispositivos no EveryNet
Três códigos são necessários para definir o dispositivo no EveryNet:
Device EUI - código de identificação único para um dispositivo em particular.
Application EUI - código de identificação para um aplicativo definido no Everynet.
Application key - Chave exclusiva para proteger as comunicações com um dispositivo em particular.
Três códigos são necessários para definir o dispositivo no EveryNet:
Device EUI - código de identificação único para um dispositivo em particular.
Application EUI - código de identificação para um aplicativo definido no Everynet.
Application key - Chave exclusiva para proteger as comunicações com um dispositivo em particular.
Para o servidor EveryNet, você pode usar os códigos estabelecidos por você ou criados pelo servidor.
Pressione o sinal de + para abrir a tela abaixo e adicionar device!
Mude para Activation para OTAA e Encryption para NS
Nota-se que há uma APP EUI já criado por EveryNet, mas esta não é a definida no dispositivo. Para adicionar o APP EUI do dispositivo LSM110A, utilize comandos AT.
Pressione o sinal de + para abrir a tela abaixo e adicionar device!
Mude para Activation para OTAA e Encryption para NS
LA915-928-16
Dicas
Device EUI – deixe o sistema gerar
Application EUI – deixe o sistema gerar
Application key – deixe o sistema gerar
Nota-se que há uma APP EUI já criado por EveryNet, mas esta não é a definida no dispositivo. Para adicionar o APP EUI do dispositivo LSM110A, utilize comandos AT.
Passo 2: Ligar dispositivo LSM110A e vai juntar-se automaticamente a rede EveryNet.
Depois de ingressar com sucesso, ele vai começar a fazer upload de mensagens para a EveryNet. Selecione a guia Dados e você vai ver os dados que aparecem no painel.
Note que isso pode levar algum tempo para que os dados do dispositivo para aparecer no visor EveryNet.
Dados são mostrados no final da página
Dados são mostrados no final da página
Configuração no Servidor final.
//AT+DEVEUI=cc4faa3a04a4a2cb
//AT+APPEUI=534ae9677ffc1c41
//AT+APPKEY=708ce3cfacf88f24eb88da478ce56fca
//AT+DEVADDR=e4086b48
//4.1.0 - LA915
//ATZ
#define DEBUGGER_ON 0
#define LOW_POWER_DISABLE 0
#define OTAA_BAND RAK_REGION_LA915
#define OTAA_DEVEUI {0x62,0x35,0x51,0x50,0x32,0x0f,0x48,0xac}
#define OTAA_APPEUI {0xb5,0x73,0xb0,0xbb,0x19,0x4e,0xcf,0x56}
#define OTAA_APPKEY {0xd5,0xcb,0xe7,0x89,0x4b,0x7f,0xb3,0xf4,0xa9,0x21,0xd1,0x20,0xc1,0x2e,0xbf,0x5d}
/** Time interval to send packets in milliseconds */
uint32_t g_send_repeat_time = 10000;
uint32_t WDT = 0;
#define WDT_INTERVAL 360 //1 hour
uint8_t QNT_LINKCHECK_FAIL = 0;
uint8_t QNT_JOINED_FAIL = 0;
uint16_t maskBuff = 0x0001;
uint8_t buff[16];
#include "app.h"
float BAT;
float intpart; // A variable to store the integer part
float floatpart; // A variable to store the float part
bool LINKCHECK_ERROR = 0;
#define ANALOG_BAT PB3
//ATC+SENDCOUNTER=0
//flash
uint8_t flash_value[4] = {0};
bool wr_result = false;
uint32_t data_to_save = 0;
uint8_t flash_read[4] = {0};
uint32_t flash_data = 0;
/** Packet is confirmed/unconfirmed (Set with AT commands) */
bool g_confirmed_mode = false;
/** If confirmed packet, number or retries (Set with AT commands) */
uint8_t g_confirmed_retry = 0;
/** Data rate (Set with AT commands) */
uint8_t g_data_rate = 3;
/** Counter pulse */
uint32_t g_send_counter = 0;
/** Flag if transmit is active, used by some sensors */
volatile bool tx_active = false;
/** fPort to send packages */
uint8_t set_fPort = 2;
/** Payload buffer */
uint8_t g_solution_data[64];
/**
* @brief Callback after join request cycle
*
* @param status Join result
*/
void joinCallback(int32_t status)
{
// MYLOG("JOIN-CB", "Join result %d", status);
if (status != 0)
{
MYLOG("JOIN-CB", "LoRaWan OTAA - join fail! \r\n");
// To be checked if this makes sense
// api.lorawan.join();
// adicionado por Miguel
}
else
{
MYLOG("JOIN-CB", "LoRaWan OTAA - joined! \r\n");
}
}
/**
* @brief LoRaWAN callback after packet was received
*
* @param data Structure with the received data
*/
void receiveCallback(SERVICE_LORA_RECEIVE_T *data)
{
MYLOG("RX-CB", "RX, port %d, DR %d, RSSI %d, SNR %d", data->Port, data->RxDatarate, data->Rssi, data->Snr);
//number of digits on register
if(data->BufferSize==7) {
flash_data = 0;
flash_data = flash_data + (data->Buffer[0]-'0')*1000000;
flash_data = flash_data + (data->Buffer[1]-'0')*100000;
flash_data = flash_data + (data->Buffer[2]-'0')*10000;
flash_data = flash_data + (data->Buffer[3]-'0')*1000;
flash_data = flash_data + (data->Buffer[4]-'0')*100;
flash_data = flash_data + (data->Buffer[5]-'0')*10;
flash_data = flash_data + (data->Buffer[6]-'0')*1;
Serial.print("New Downlink Flash data: ");
Serial.print(flash_data);
Serial.println();
flash_value[0] = (uint8_t)(flash_data >> 0);
flash_value[1] = (uint8_t)(flash_data >> 8);
flash_value[2] = (uint8_t)(flash_data >> 16);
flash_value[3] = (uint8_t)(flash_data >> 24);
wr_result = api.system.flash.set(0, flash_value, 4);
while (!wr_result)
{
// Retry
wr_result = api.system.flash.set(0, flash_value, 4);
delay(100);
}
//for (int i = 0; i < data->BufferSize; i++)
//{
//Serial.printf("%02X", data->Buffer[i]);
//}
//Serial.print("\r\n");
}
tx_active = false;
}
/**
* @brief LoRaWAN callback after TX is finished
*
* @param status TX status
*/
void sendCallback(int32_t status)
{
WDT = 0;
MYLOG("TX-CB", "TX status %d", status);
tx_active = false;
}
uint8_t Hall_Sensor = PB8; // pin to measure pulses
void Hydrometer_Pulse()
{
sensor_handler(NULL);
}
/**
* @brief Arduino setup, called once after reboot/power-up
*
*/
void setup()
{
analogReadResolution(12);
Serial.begin(115200);
//Para entrada de comandos apos o reset
delay(10000);
// sensor hall
pinMode(Hall_Sensor, INPUT_PULLUP);
attachInterrupt(Hall_Sensor, Hydrometer_Pulse, CHANGE);
// OTAA Device EUI MSB first
uint8_t node_device_eui[8] = OTAA_DEVEUI;
// OTAA Application EUI MSB first
if(api.lorawan.deui.get(buff, 8) == true) {
Serial.print("LoRaWan DevEui = 0x");
for(int i = 0; i < 8; i++) {
Serial.printf("%02X", buff[i]);
}
Serial.println("");
} else {
Serial.println("LoRaWan DEVEUI get fail");
}
uint8_t node_app_eui[8] = OTAA_APPEUI;
if(api.lorawan.appeui.get(buff, 8) == true) {
Serial.print("LoRaWan AppEui = 0x");
for(int i = 0; i < 8; i++) {
Serial.printf("%02X", buff[i]);
}
Serial.println("");
} else {
Serial.println("LoRaWan APPEUI get fail");
}
////// if (!api.lorawan.appkey.set(buff, 16)) {
////// Serial.printf("LoRaWan OTAA - set application key is incorrect! \r\n");
////// return;
////// }
// OTAA Application Key MSB first
uint8_t node_app_key[16] = OTAA_APPKEY;
if(api.lorawan.appkey.get(buff, 16) == true) {
Serial.print("LoRaWan AppKey = 0x");
for(int i = 0; i < 16; i++) {
Serial.printf("%02X", buff[i]);
}
Serial.println("");
} else {
Serial.println("LoRaWan APPKEY get fail");
}
if(api.lorawan.daddr.get(buff, 4) == true) {
Serial.print("LoRaWan DevAddr = 0x");
for(int i = 0; i < 3; i++) {
Serial.printf("%02X", buff[i]);
}
Serial.println("");
} else {
Serial.println("LoRaWan DEVADDR get fail");
}
////// if (!api.lorawan.deui.set(buff, 8)) {
////// Serial.printf("LoRaWan OTAA - set device EUI is incorrect! \r\n");
////// return;
////// }
////// if (!api.lorawan.appeui.set(node_app_eui, 8)) {
////// Serial.printf("LoRaWan OTAA - set application EUI is incorrect! \r\n");
////// return;
////// }
if (!api.lorawan.band.set(OTAA_BAND)) {
Serial.printf("LoRaWan OTAA - set band is incorrect! \r\n");
return;
}
if (!api.lorawan.deviceClass.set(RAK_LORA_CLASS_A)) {
Serial.printf("LoRaWan OTAA - set device class is incorrect! \r\n");
return;
}
if (!api.lorawan.njm.set(RAK_LORA_OTAA)) // Set the network join mode to OTAA
{
Serial.printf("LoRaWan OTAA - set network join mode is incorrect! \r\n");
return;
}
if (!api.lorawan.rety.set(1)) {
Serial.printf("LoRaWan OTAA - set retry times is incorrect! \r\n");
return;
}
if (!api.lorawan.cfm.set(0)) {
Serial.printf("LoRaWan OTAA - set confirm mode is incorrect! \r\n");
return;
}
if (!api.lorawan.adr.set(true)) {
Serial.printf("LoRaWan OTAA - set adaptive data rate is incorrect! \r\n");
return;
}
Serial.printf("Set the data rate %s\r\n", api.lorawan.dr.set(2) ? "Success" : "Fail");
Serial.printf("Set channel mask %s\r\n", api.lorawan.mask.set(&maskBuff) ? "Success" : "Fail");
// Setup for LoRaWAN
g_confirmed_mode = api.lorawan.cfm.get();
g_confirmed_retry = api.lorawan.rety.get();
g_data_rate = api.lorawan.dr.get();
// Setup the callbacks for joined and send finished
api.lorawan.registerRecvCallback(receiveCallback);
api.lorawan.registerSendCallback(sendCallback);
api.lorawan.registerJoinCallback(joinCallback);
Serial.printf("RUI3 %s\n", api.system.firmwareVersion.get().c_str());
api.lorawan.linkcheck.set(1);
// Initialize module
Wire.begin();
// Register the custom AT command to get device status
if (!init_status_at())
{
MYLOG("SETUP", "Add custom AT command STATUS fail");
}
// Register the custom AT command to set the send Counter
if (!init_counter_at())
{
MYLOG("SETUP", "Add custom AT command Send Counter fail");
}
// Get saved sending counter from flash
get_at_setting();
// Create a timer.
api.system.timer.create(RAK_TIMER_0, sensor_handler, RAK_TIMER_PERIODIC);
if (g_send_repeat_time != 0)
{
// Start a timer.
api.system.timer.start(RAK_TIMER_0, g_send_repeat_time, NULL);
}
if (g_confirmed_mode)
{
MYLOG("SETUP", "Confirmed enabled");
}
else
{
MYLOG("SETUP", "Confirmed disabled");
}
MYLOG("SETUP", "Retry = %d", g_confirmed_retry);
MYLOG("SETUP", "DR = %d", g_data_rate);
api.system.lpm.set(1);
if (!api.lorawan.join()) // Join to Gateway
{
Serial.printf("LoRaWan OTAA - join fail! \r\n");
return;
}
}
/**
* @brief sensor_handler is a Interrupt function or user call
*/
void sensor_handler(void *)
{
MYLOG("UPLINK", "Start");
WDT++;
if(WDT==WDT_INTERVAL) //1 hour
api.system.reboot();
//FALLING
if(digitalRead(Hall_Sensor)==LOW)
{
if (api.system.flash.get(0, flash_read, 4))
{
flash_data |= flash_read[0] << 0;
flash_data |= flash_read[1] << 8;
flash_data |= flash_read[2] << 16;
flash_data |= flash_read[3] << 24;
}
flash_data++;
//Overflow Register
if(flash_data==9999999)
flash_data++;
flash_value[0] = (uint8_t)(flash_data >> 0);
flash_value[1] = (uint8_t)(flash_data >> 8);
flash_value[2] = (uint8_t)(flash_data >> 16);
flash_value[3] = (uint8_t)(flash_data >> 24);
wr_result = api.system.flash.set(0, flash_value, 4);
}
// Create payload
char value = 0x31;
for (int idx = 0; idx < 7; idx++)
{
g_solution_data[idx] = value;
value++;
}
// BAT = (analogRead(ANALOG_BAT) * 3.0) / 4096.0; //CR
BAT = (analogRead(ANALOG_BAT) * 3.3) / 4096.0;
Serial.println(BAT);
intpart = floor (BAT); // Get the integer part by rounding down
floatpart = fmod (BAT, intpart); // Get the float part by calculating the remainder
g_solution_data[0] = flash_value[0];
g_solution_data[1] = flash_value[1];
g_solution_data[2] = flash_value[2];
g_solution_data[3] = flash_value[3];
g_solution_data[4] = intpart;
g_solution_data[5] = floatpart*100.0;
g_solution_data[6] = digitalRead(Hall_Sensor);
// Send the packet
send_packet();
}
/**
* @brief Send the data packet
*/
void send_packet(void)
{
Serial.println(flash_data);
if (!api.lorawan.njs.get())
{
MYLOG("UPLINK", "Not joined, skip sending");
QNT_JOINED_FAIL++;
//Tem min
if(QNT_JOINED_FAIL==(WDT_INTERVAL/10))
{
QNT_JOINED_FAIL=0;
api.system.reboot();
}
return;
}
// Check if it is LoRaWAN
MYLOG("UPLINK", "Sending packet...");
// Send the packet
api.lorawan.linkcheck.set(1);
api.lorawan.mask.set(&maskBuff);
//Serial.printf("Set channel mask %s\r\n", api.lorawan.mask.set(&maskBuff) ? "Success" : "Fail");
if (api.lorawan.send(7, g_solution_data, set_fPort, g_confirmed_mode, g_confirmed_retry))
{
MYLOG("UPLINK", "Packet enqueued, size 7");
tx_active = true;
}
//linkcheck fails 3 times
if(LINKCHECK_ERROR==true)
{
LINKCHECK_ERROR=false;
QNT_LINKCHECK_FAIL++;
if(QNT_LINKCHECK_FAIL==3)
{
QNT_LINKCHECK_FAIL=0;
//api.system.reboot();
}
}
}
/**
* @brief This example is complete Interrupt Sensor (GPIO)
* driven. The loop() does nothing than
* sleep.
*
*/
void loop()
{
api.system.sleep.all();
}
Dentro da EveryNet você vai obter o APPLICATION EUI e APPLICATION KEY os quais deve ser cadastrados no módulo LoRa antes de realizar o JOIN, via aplicativo "Lora Wan Gui" ou fazer hardcoded ou via comandos AT.
Questoes: suporte@smartcore.com.br
Sobre a SMARTCORE
A SmartCore fornece módulos para comunição wireless, biometria, conectividade, rastreamento e automação.
Nosso portifólio inclui modem 2G/3G/4G/NB-IoT/Cat.M, satelital, módulos WiFi, Bluetooth, GNSS / GPS, Sigfox, LoRa, leitor de cartão, leitor QR code, mecanismo de impressão, mini-board PC, antena, pigtail, LCD, bateria, repetidor GPS e sensores.
Mais detalhes em www.smartcore.com.br
Nenhum comentário:
Postar um comentário