Este projeto busca realizar um pequeno teste da tecnologia de transmissão da LORA para coletar informações que podem ser usadas pela Fundação CTIC. As informações serão enviadas de um dispositivo final (nó ou cliente), essas informações serão coletadas por um dispositivo de gateway e isso, por sua vez, a encaminhará para um servidor para armazená -las.
A Lora é uma tecnologia sem fio (como WiFi, Bluetooth, LTE, Sigfox ou ZigBee) que usa um tipo de modulação de radiofrequência patenteada pela Semtech.
Atualmente, a tecnologia é administrada pela Alliance Lora, que certifica toda a fabricação de hardware que busca trabalhar com essa tecnologia.
Lora tem uma alta tolerância à interferência , uma alta sensibilidade para receber dados (-168db), um consumo muito baixo (o dispositivo pode durar uma década com uma única bateria) e um intervalo de 10 a 20 km (dependendo se a visão direta ou a topologia da terra está disponível). Por outro lado, encontramos uma transferência de dados muito baixa (até 255 bytes).
Tudo isso torna essa tecnologia de transferência útil para grandes distâncias ou redes de IoT que não precisam ou não têm acesso à corrente elétrica.
A Lora trabalha em frequências gratuitas (são 868MHz na Europa, 916 MHz na América ou 433MHz na Ásia, por exemplo) que, reunindo o não -necessário para ter um fornecedor de rede elétrica e um provedor de telecomunicações (usamos radiofrequência), possibilita a emissão e envio de informações sem risco.
Podemos nos comunicar com os dispositivos através do Loremac (também conhecido por Lora) ou por Lorawan.
Loramac : Usado para comunicar dois dispositivos entre si com um ponto a ponto a apontar, um envia informações e outro as coleta (ou vice -versa).
LORAWAN : Usado para comunicar uma rede de dispositivos. Nesta abordagem, a figura do gateway é exibida (o dispositivo que coleta as informações de um ou mais dispositivos e a encaminha para o servidor). Em Lorawan, as informações devem ser filtradas para saber quais dispositivos você deve ouvir o gateway e quais ignorar, mas isso será visto mais tarde. Essa abordagem usa uma topologia em estrela.
Por outro lado, em Lorawan , também existem três tipos de dispositivos ou nós finais :
*Nos exemplos, suportam apenas os nós Classe A e B (suportados pela biblioteca usada), mas apenas o tipo A. é implementado apenas
Se a banda de frequência livre na Europa (868MHz) for usada, algumas limitações devem ser levadas em consideração:
Em cada faixa de frequência, existem vários canais ou sub-bandas, no caso do europeu (868MHz), encontramos 10 canais numerados de 0 a 9. Mas, por exemplo, no americano (915MHz), podemos encontrar até 64.
O envio de informações através de um canal ou outro é uma tarefa que as bibliotecas geralmente facilitam usar.
Em alguns eventos finais, é possível modificar o DataCrate ou o Sprevador do dispositivo.
O DATARRATE e o SpreadingFactor estão relacionados: um datArrate de 0 indica um SF12 e um datArrate de 5 indica um SF7. Tudo com uma frequência de 125kHz com a seguinte exceção: um dataterate de 6 indica um SF7 com 250kHz.
Dois dispositivos (um para o nó e outro para o gateway, que também devem ter conectividade Wi -Fi) e uma conta associada no TTS ( The Things Network ) ou Chirpstack (poder usar seu próprio servidor em casa). Neste exemplo, os exemplos de Loremac e Lorawan que usam um nó Arduino e um gateway Pycom.
Para começar, basta clonar o repositório:
git clone https://github.com/Javieral95/Getting_Started_With_LoRa.git
E depois envie os projetos relevantes para os dispositivos
Por que dois Ides? A extensão simples e pymakr mal funciona no código do Visual Studio. Sinta -se à vontade para usar o espaço de trabalho mais confortável.
Ambos os dispositivos têm uma Antera Lora conectada a eles.
NOTA : O código para um Arduinomkr1300 (mais preparado para uso, como o device final Lora) e os códigos para usar uma Pysense ou Pytrack como um final-EVEX também está incluído nos repositórios.

O exemplo do Loramac (são encontrados na pasta homônima) são funcionais usando um dispositivo final do Arduino e um gateway Pycom.
O nó envia apenas informações de código hardcode e o gateway se conecta apenas a Lora e Wi -Fi, recebe as informações da PYCOM e imprime a leitura dos dados (embora tenha implementado a função de enviar os dados para a rede).
O uso de um servidor de rede é dispensado.
Para saber mais, você pode acessar a pasta /Loramac .
Para o uso desses exemplos (que são funcionais que usam um dispositivo final do Arduino e um gateway PYCOM) é necessário um servidor para visualizar os dados. Neste exemplo, o uso da rede e Chirpstack (anteriormente conhecido como Loraserver) foi abordado.
Para saber mais, você pode acessar a pasta /Lorawan e continuar consultando esta documentação.
Existem dois tipos de autenticação em Lorawan:
*Nos exemplos no momento, apenas o OTAA é feito.
Como mencionado anteriormente, precisaremos de um servidor. Para este exemplo, uma versão gratuita da rede Things, um servidor Chirpstack de propriedade da PYCOM e outro implantado em casa foi usado.
É a alternativa mais confiável, segura e melhor documentada. No entanto, tudo indica que deixará de ser aberto (há um limite de 50 nós por aplicação).
Criar um aplicativo é simples, acesse o menu e clique no botão +. Depois de indicarmos o nome do aplicativo, um ID exclusivo e uma descrição.
Quando o aplicativo é criado, podemos adicionar dispositivos finais (nós) clicando no botão +.
Os gateways são dispositivos responsáveis pelo envio de tráfego que vem de vários dispositivos finais (pertencentes a vários aplicativos) e encaminhados para o servidor. Criar um gateway também é simples, clique no botão + e preencha o formulário que presta atenção aos seguintes conceitos:
Para poder ler os dados que o nó enviou ao servidor, é necessário decodificar a carga útil, no caso do TTN, faremos isso para cada dispositivo, na guia Formatters da carga útil . Escolhemos como o formatador digite a opção JavaScript e:
function Decoder(bytes, port) {
// Decode plain text; for testing only
return {
myTestValue: String.fromCharCode.apply(null, bytes)
};
}
arduino_ttn_decoder.js É estabelecido que todos os endereços hexadecimais da rede de coisas estão no prefeito, não é importante ao programar os dispositivos, mas os erros foram sofridos em versões anteriores.
Essa é a alternativa de código aberto, ainda está em desenvolvimento e sua documentação não é tão boa. No entanto, funciona e permite que o servidor seja lançado.
A Pycom oferece um servidor Chirpstack para conectar seu dispositivo de gateway.
O aplicativo é semelhante ao detalhado na seção da rede de coisas.
Você deve acessar os perfis de dispositivos da seção do servidor, uma vez nela, acesso ao perfil que interessa (OTAA neste caso) e modificar as versões:
Para criar um gateway, acesse o mesmo nome e clique no botão +. Preencha o formulário que presta atenção especial ao campo de identificação do gateway (64 bits em hexadecimal que identifica o gateway), você pode fazer com que o Chirpstack os gerar para você, mas o Mac do dispositivo é geralmente usado (se você não o conhece na seção que explica o gateway Pycom, será detalhado como obtê -lo).
Você pode deixar o restante dos valores padrão.
Para ler os dados que o nó enviou ao servidor, é necessário decodificar a carga útil, no caso do ChirpStack, faremos isso para cada perfil do dispositivo, no dispositivo PROPILES_ Acessamos o perfil que nos interessa (neste caso OTAA) e acessamos a guia Codec :
Escolhemos nas funções de codec de decipt personalizadas e:
function Decode(fPort, bytes) {
var tempObj = new Object();
tempObj.data=bytes;
tempObj.decodedData = String.fromCharCode.apply(null, bytes);
tempObj.message = "Informacion recibida del nodo";
return tempObj;
}
arduino_chirpstark_decoder.js É estabelecido que todos os endereços hexadecimais do Chirpstack estão em minúsculos, não é importante ao programar os dispositivos, mas os erros foram sofridos em versões passadas.
O Chirpstack fornece uma alternativa OpenSource para lançar nosso próprio servidor privado em Lorawan e nos permite fazê -lo de uma maneira simples e através de contêineres.
É por isso que outro repositório de propriedade do fundador do ChirpStack (Brocar) que permite esta operação: Chirpstack-Docker foi clonado no presente repositório. Nós o encontramos na pasta chirpstack-docker .
O Chirpstack possui vários componentes em sua arquitetura para tornar o serviço capaz de operar, eles são os seguintes:

A maneira de exibir o servidor na forma de contêineres nos permite abstrair grande parte dos componentes da arquitetura, no entanto, eles são detalhados abaixo:
Antes de implantar, todos os parâmetros necessários devem ser configurados nos arquivos de configuração armazenados na placa de configuração .
Você pode consultar a seguinte documentação oficial:
Nota: Os arquivos de configuração são sensíveis a espaços em branco ou linhas vazias (foram encontradas na rede de mosquitos), verifique os arquivos e elimina para evitar erros.
Como já mencionado anteriormente, a implantação em contêineres é simples e está localizada no diretório chirpstack-docker .
Depois que o necessário já está configurado, basta ser colocado no diretório Chirpstack-Docker e no lançamento:
docker-compose up
Com a configuração padrão, você pode acessar o servidor na direção local: 8080 . O usuário será administrador e a senha do administrador .
Vamos começar a adicionar a configuração básica:
Depois que o servidor estiver configurado, teremos que registrar nossos gateways e criar aplicativos para registrar nossos dispositivos finais. Esse processo é realizado de maneira analogada à explicada na seção anterior desta documentação: Chirpstack (Lora Server).
Além disso, a função que decodifica e codifica as informações recebidas deve ser indicada, também é explicada na seção anterior.
O código usado para iniciar o gateway é detalhado abaixo em um Pycom (FIPY com Pytrack). Este código está localizado em Lorawan/LorapyComgateway .
A biblioteca Nanogateway PY foi usada que permite que o Gateway seja lançado em minutos.
O Nano-Gateway converte um dispositivo Pycom em um gateway simples que ouve apenas um canal de banda de frequência (monocanal) , para ouvir mais bandas no Pycom, é possível ser exigido de um gateway comercial.
No arquivo de configuração, tudo o necessário para personalizar o gateway:
WIFI_MAC = ubinascii.hexlify(machine.unique_id()) #.toUpper() para TTS
SERVER = 'loraserver.pycom.io' #(or url of your server)
GATEWAY_ID = WIFI_MAC[:6] + "ffff" + WIFI_MAC[6:12] #Minusculas: Chirpstack
NTP = "es.pool.ntp.org"
NTP_PERIOD_S = 3600
#WiFi settings (change it)
WLAN_SSID = "MyAwesomeWiFi" #"pycom-wifi"
WLAN_PASS = "CheckOutThisGoodPassword" #"securepassword"
WLAN_TIMEOUT_MS = 180000
### LoRaWAN for EU868 ###
LORA_FREQUENCY = 868500000
#Spreading Factor: (Higher value in SF=More distance but less speed transmision)
LORA_GW_DR = "SF7BW125" # DR_5,Can change in range: SF7 to SF15 (SF7B250 also exists)
LORA_NODE_DR = 5 #5 (6 uses 250Khz) for SF7, 4 for SF6.. all using 125Khz
###
def get_gateway_id():
print("Your gateway_id is: {}".format(GATEWAY_ID)) #The gateway is b'THIS_STRING'
return GATEWAY_ID
Nota: Se você conectar seu gateway a uma rede local sem conexão com a Internet, ele retornará um erro ao sincronizar os relógios. Você pode sair da etapa comentando as seguintes linhas de código na função inicial (self) do arquivo nanogateway.py como o exemplo a seguir mostra:
# get a time sync
self._log('Syncing time with {} ...', self.ntp_server)
#self.rtc.ntp_sync(self.ntp_server, update_period=self.ntp_period)
#while not self.rtc.synced():
# utime.sleep_ms(50)
self._log("RTC NTP sync complete")
Várias funções de arquivo principal não são usadas, é necessário apenas iniciar o gateway da seguinte maneira e já estará funcionando.
def init_loraWAN_gateway():
print("Initializing LoRaWAN nano Gateway")
nanogw = NanoGateway(
id=config.GATEWAY_ID,
frequency=config.LORA_FREQUENCY,
datarate=config.LORA_GW_DR,
ssid=config.WLAN_SSID,
password=config.WLAN_PASS,
server=config.SERVER,
port=config.PORT,
ntp_server=config.NTP,
ntp_period=config.NTP_PERIOD_S
)
print("Ok! Now you have a LoRaWAN Gateway! Lets start it, wait . . .")
pycom.rgbled(0xAA0000)
nanogw.start()
nanogw._log('. . . Yeah! Nano gateway is connected and running, enjoy the log:')
pycom.rgbled(0x000000)
O PYCOM manterá a luz vermelha até que consiga se conectar, uma vez que os dispositivos de dispositivos piscarão seu LED verde.
O seguinte é detalhado para operar o nó de classe A usando Arduino.
A teoria usa todos os canais disponíveis na banda de frequência, mais tarde um modo de força será visto apenas um (não recomendado).
A McCi Arduino Lorawan Library tem sido usada que permite abstrair muitos aspectos da comunicação de Lora. Foi instalado pelo gerenciador de bibliotecas da plataforma.
Basicamente, o código usado para o cliente Arduino é o encontrado no exemplo ttn-otaa.ino da biblioteca, exceto por alguma modificação.
A configuração é feita em dois arquivos diferentes:
Toda a configuração relacionada a Lorawan, como indicado acima, é indicado no arquivo Lorawan.cpp . No início do documento, está detalhado que os dados devem ser indicados: APP_EUI , DEV_EUI e APP_KEY (olho para o formato indicado abaixo).
Então o exemplo no Chirpstack:
static const u1_t PROGMEM APPEUI[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
static const u1_t PROGMEM DEVEUI[8] = {0x7b, 0x6b, 0xff, 0x2c, 0x7b, 0x2c, 0x19, 0x5a};
static const u1_t PROGMEM APPKEY[16] = {0xbd, 0x21, 0x5a, 0x82, 0xb2, 0xf7, 0x92, 0xf3, 0xc7, 0xcb, 0xb2, 0x88, 0xc7, 0x55, 0x33, 0xe7};
Sob toda a configuração de chave, no arquivo loraWan.cpp , podemos escolher se devemos enviar texto ou dados planos do sensor de temperatura e umidade. Decomes a opção desejada:
/******* Send data config *******/
// Use this to send a Hello world in plain text
// static uint8_t mydata[] = "Hello World!";
// Use this to send sensor data
const int neededBytes = 4; // 4 bytes: 2 for temperature and 2 for humidity, can change this value
static byte mydata[neededBytes];
static LoraEncoder encoder(mydata);
Dependendo das informações enviadas, uma função de decodificação ou outra função deve ser usada, conforme indicado nas seções da rede e Chirpstack.
Como visto anteriormente, a placa Nano-Gateway Pycom só pode ler em um canal, enquanto o dispositivo final do Arduino pode transmitir em todos os canais da banda (por exemplo, na banda européia, existem 10 canais). Embora não seja recomendado (a regra de 1%pode ser violada) pode ser forçada a usar apenas um canal e uma frequência apenas devido a problemas de desenvolvimento e teste.
Para isso, é necessário modificar o código da biblioteca, mais especificamente o lorabase_eu868.h (no caso de usar a frequência européia) e forçar a frequência desejada a ser emitida da seguinte maneira (observe como todos os valores foram codificados a indicar a frequência 868.MHz):
enum {
EU868_F1 = 868500000, // g1 SF7-12
EU868_F2 = 868500000, // g1 SF7-12 FSK SF7/250
EU868_F3 = 868500000, // g1 SF7-12
EU868_F4 = 868500000, // g2 SF7-12
EU868_F5 = 868500000, // g2 SF7-12
EU868_F6 = 868500000, // g3 SF7-12
EU868_J4 = 868500000, // g2 SF7-12 used during join
EU868_J5 = 868500000, // g2 SF7-12 ditto
EU868_J6 = 868500000, // g2 SF7-12 ditto
};
enum {
EU868_FREQ_MIN = 868500000,
EU868_FREQ_MAX = 868500000
};
A seguinte função também deve ser chamada no início da função Lora ( Lorawan_StartJob () :
// Define the single channel and data rate (SF) to use
void disableChannels(int selectedChannel, int dr)
{
// Disable all channels, except for the one defined above.
// ONLY FOR TESTING AND DEVELOPING!
for (int i = 0; i < 9; i++)
{ // For EU; for US use i<71
if (i != selectedChannel)
{
LMIC_disableChannel(i);
}
}
// Set data rate (SF) and transmit power for uplink
LMIC_setDrTxpow(dr, 14);
}
O canal e o daterado a serem configurados estão no início do arquivo, nas linhas (por padrão: o canal 0 e o datate desejado do fator de propagação 7 cujo valor é 5):
/******* Channel config (only change if you want to uses a single channel) *******/
const int channel = 0; // Use if you want to use only one Band's Channel.
const int dr = DR_SF7; // Use if you want to use a specific datarate (The spreading factor mark the dr's value).
Isso faria com que a perda de pacotes fosse reduzida consideravelmente, embora ainda haja alguns que o gateway não recebe.
Basta copiar o projeto para o seu prato Arduino.
A livraria funciona por eventos, neste caso o mais importante será a autenticação (quando você concluir, você verá as chaves no console) e o envio de dados.
O evento em que os dados são enviados será EV_TXCOMPLETE na função Void Onevent (EV_T EV) do arquivo lorawan.cpp , observe que o evento inclui a "janela RX", quando o dispositivo ouve.
case EV_TXCOMPLETE:
Serial.println(F("EV_TXCOMPLETE (includes waiting for RX windows)"));
if (LMIC.txrxFlags & TXRX_ACK)
Serial.println(F("Received ack"));
if (LMIC.dataLen)
{
Serial.print(F("Received "));
Serial.print(LMIC.dataLen);
Serial.println(F(" bytes of payload"));
}
// Schedule next transmission
os_setTimedCallback(&sendjob, os_getTime() + sec2osticks(TX_INTERVAL), do_send);
break;
A função, no mesmo arquivo, onde será detalhado quais dados são enviados é fazer (comentar ou descomentar as linhas que codificam as informações se você deseja enviar texto plano):
void do_send(osjob_t *j)
{
// Check if there is not a current TX/RX job running
if (LMIC.opmode & OP_TXRXPEND)
{
Serial.println(F("OP_TXRXPEND, not sending"));
}
else
{
// Leer datos de sensor y codificar (Libreria LoRa_Serialization).
am2315_readedData data = readAM2315Data();
encoder.writeTemperature(data.temp);
encoder.writeHumidity(data.hum);
// Comentar las dos lineas "encoder" para enviar texto plano
// Send packet
LMIC_setTxData2(1, mydata, sizeof(mydata), 0);
if (isLoopRunning)
{
freq = String(LMIC.freq);
Serial.println("-->Packet queued using freq = " + freq);
// Prepare upstream data transmission at the next possible time.
printSensorInfoInDisplay(data.temp, data.hum);
printLoraSentInDisplay(freq);
}
}
// Next TX is scheduled after TX_COMPLETE event.
}
NOTA : Foi sofrido um erro que impedia o nó de receber pacotes traseiros, por isso era impossível autenticar o dispositivo na frente do servidor. Ele foi adicionado no cliente Setup () (mais especificamente na função lorawan_startjob () do arquivo lorawan.cpp ) a seguinte linha de código que aumenta o erro máximo do relógio em 10%:
LMIC_setClockError(MAX_CLOCK_ERROR * 10 / 100);
Tanto o Chirpstack quanto o Things Network oferecem uma série de integrações para enviar os dados que nosso servidor recebe para outros serviços. Por exemplo: podemos enviar os dados para um banco de dados de influência, usar o MQTT, conectar -se aos serviços da AWS ou do Azure ...
Nesta seção, será visto um caso prático no qual podemos usar a integração do HTTP (WebHooks na rede Things) e MQTT para enviar os dados que nossos dispositivos enviam e que nosso servidor recebe um aplicativo próprio.
Para acessar integrações:
No caso de usar chirpstack, estamos interessados
Em ambos os servidores, essa integração funciona de maneira semelhante: inicia um evento toda vez que um dispositivo de aplicativo envia informações (no caso do TTN, devemos marcar a caixa de mensagens Uplink ) e, com essas informações, uma solicitação pós -Type HTTP é lançada ao URL que indicamos.
NOTA: Uma boa prática, para verificar se o evento é lançado corretamente ou para visualizar o formato de dados é acessar o serviço pós -barra, onde podemos criar um compartimento (URL temporário para receber solicitações).
Nota2: Se o aplicativo para o qual você lançará a petição estiver alojado em localhost e no servidor Chirpstack também (de uma maneira intocada, conforme mostrado nesta documentação), você deverá indicar o URL da seguinte maneira:
http://host.docker.internal:PUERTO/uri
Esta documentação cobre apenas o uso do Chirpstack e o TTN não está documentado para enviar dados (ele possui um formato diferente na petição).
Se os dados foram decodificados com os exemplos deste repositório (pasta Decoders-Integrations ), obteremos um corpo na solicitação semelhante ao seguinte:
{
"applicationID": 0,
"applicationName": "Name",
"deviceName": "DeviceName",
"devEUI": "BYTES_EUI",
"txInfo": [Object object],
"adr": true,
"dr": 5,
"fCnt": 24,
"fPort": 1,
"data": "DATA_WITHOUT_DECODE",
"objectJSON": {
"data":"DATA_WITHOUT_DECODE==",
"decodedData":{
"humidity":37,"temperature":23
},
"message":"Informacion recibida del nodo"
},
"tags": [Object object],
"confirmedUplink": false,
"devAddr": "BYTES_DEV_ADDR"
}
ObjectJson é o objeto retornado por nossa função decodificadora .
Para lê-lo, por exemplo, em um aplicativo JavaScript, seria suficiente fazer algo semelhante ao seguinte (mais no arquivo /Decoders-Integrations/arduino_Chirpstack_Http_Integration.js )
const { deviceName, objectJSON, devAddr} = req.body;
var sensorData = JSON.parse(objectJSON);
//devAddr esta codificado!
var temperature = sensorData.decodedData.temperature;
var humidity = sensorData.decodedData.humidity;
Na verdade, a menos que usemos o MQTTS (MQTT com TLS), não será necessário acessar qualquer integração do aplicativo da Web do servidor.
Neste exemplo, assinaremos nosso aplicativo para o tópico para o qual nosso dispositivo final enviará os dados.
Se nosso aplicativo for lançado em casa e o servidor Chirpstack também (Dockerized como mostramos nesta documentação), o host de corretor será o IP da máquina WSL. Para saber esses dados, lançaremos:
wsl hostname -I
Você também terá que fazer algumas configurações lançando os seguintes comandos (1883 é o porto de Mosquitto, se outro modificar for usado):
netsh interface portproxy add v4tov4 listenport=1883 listenaddress=0.0.0.0 connectport=1883 connectaddress=127.0.0.1
Podemos usar o MQTT como ele vem no exemplo do Docker, com o parâmetro anônimo com o valor TRU (sem usar nenhum tipo de senha ou lista de usuários) ou podemos configurar uma lista de usuários (cada um com os tópicos que podem ler ou escrever) com suas respectivas senhas (conforme indicado pela documentação a seguir).
Para fazer isso, lançaremos os seguintes comandos (podemos lançá -los na WSL ), cada um deles solicitará que introduza uma senha para cada usuário (neste exemplo, o passe foi usado para todos):
# Create a password file, with users chirpstack_gw, chirpstack_ns, chirpstack_as, bob and nodeApp
sudo mosquitto_passwd -c /etc/mosquitto/passwd chirpstack_gw
sudo mosquitto_passwd /etc/mosquitto/passwd chirpstack_ns
sudo mosquitto_passwd /etc/mosquitto/passwd chirpstack_as
sudo mosquitto_passwd /etc/mosquitto/passwd bob
sudo mosquitto_passwd /etc/mosquitto/passwd nodeApp
# Optional, Secure the password file
sudo chmod 600 /etc/mosquitto/passwd
Isso criará o arquivo passwd que conterá todos os usuários e senhas, agora podemos configurar uma lista ACLS em um arquivo homônimo como o seguinte:
user chirpstack_gw
topic write gateway/+/event/+
topic read gateway/+/command/+
user chirpstackns
topic read gateway/+/event/+
topic write gateway/+/command/+
user chirpstack_as
topic write application/+/device/+/event/+
topic read application/+/device/+/command/+
user bob
topic read application/123/device/+/event/+
topic write application/123/device/+/command/+
user nodeApp
topic read application/+/device/#
topic write application/+/device/#
Agora, devemos modificar a configuração do servidor para usar essas credenciais modificando os arquivos apresentados em /chirpstack-docker/configuration :
[application_server.integration.mqtt]
server="tcp://mosquitto:1883"
username="chirpstack_as"
password="pass"
[integration.mqtt.auth.generic]
servers=["tcp://mosquitto:1883"]
username="chirpstack_gw"
password="pass"
[network_server.gateway.backend.mqtt]
server="tcp://mosquitto:1883"
username="chirpstack_ns"
password="pass"
listener 1883
password_file /mosquitto/config/passwd
acl_file /mosquitto/config/acls
allow_anonymous false
mosquitto:
image: eclipse-mosquitto:2
ports:
- 1883:1883
volumes:
- ./configuration/eclipse-mosquitto/mosquitto.conf:/mosquitto/config/mosquitto.conf
- ./configuration/eclipse-mosquitto/passwd:/mosquitto/config/passwd
- ./configuration/eclipse-mosquitto/acls:/mosquitto/config/acls
Neste exemplo, usaremos um aplicativo NodeJS para conectar ao nosso servidor local Chirpstack local. Todo o código pode ser encontrado no arquivo /Decoders-Integrations/arduino_Chirpstack_mqtt_Integration.js .
Primeiro, teremos que instalar o pacote MQTT
npm install mqtt --save
Com ele, já podemos nos conectar ao corretor:
var mqtt = require('mqtt')
const host = 'WSL_IP'
const port = '1883' //or your port
const clientId = 'mqtt_NodeApp_' + Math.random().toString(16).slice(3)
const connectUrl = 'mqtt://' + host + ':' + port;
const client = mqtt.connect(connectUrl, {
clientId,
clean: true,
//username: "nodeApp", //Descomentar si usamos contraseñas y acls
//password: "pass", //Colocar el usuario y contraseña correspondiente
connectTimeout: 4000,
reconnectPeriod: 1000,
debug: true
})
E assine o tópico desejado (o personagem # é um curinga multinível, significa que lemos qualquer subtopiano, enquanto o personagem + é um curinga de um único curinga).
const chirpstackApplicationID = 1; //Check url, for example: http://localhost:8080/#/organizations/1/applications. /1/ is the ID
const chirpstackDeviceID = "DEV_EUI";
const chirpstackReadAppTopic = "application/" + chirpstackApplicationID + "/device/#";
const chirpstackWriteAppTopic = "application/" + chirpstackApplicationID + "/device/"+chirpstackDeviceID+"/EXAMPLE";
Usaremos os seguintes eventos para isso:
//Evento al conectarse
client.on('connect', function () {
console.log("Connected")
client.subscribe(chirpstackReadAppTopic, function (err) {
if (!err) {
console.log("Subscribed to topic: "+chirpstackReadAppTopic)
//client.publish(chirpstackWriteAppTopic, 'Hello mqtt') //Podemso enviar un mensaje para debugear
}
else {
console.log("Error in connection:")
console.log(err)
}
})
})
//Evento al recibir un mensaje
client.on('message', function (topic, message) {
// El mensaje es un buffer, convertimos a String.
var stringMsg = message.toString();
console.log(topic + " - " + stringMsg)
insertSensorEntry_Mqtt(topic, stringMsg); //Funcion que lee el mensaje e inserta en base de datos
})
En ambos servidores (Chirpstack y The Things Network) la integración tiene por nombre MQTT , eso sí, antes de realizar ninguna integración debemos configurar los certificados.
A continuación se documentará como realizar la integración con MQTT en un servidor local de Chirpstack (para más info revisar el apartado ChirpStack privado en local de esta documentación).
Antes de generar los certificados, debemos tener instalado CFSSL & CFSSLJSON. Tras ello, clonaremos el siguiente repositorio propiedad del creador de Chirpstack y seguiremos los pasos de su documentación: Chirpstack-Certificates.
NOTA: Si se usa Windows, instalar los pre-requisitos en la máquina WSL pues se necesitará hacer uso del comando make .
Colocamos la carpeta certs generada con el proyecto Chirpstack-Certificates en nuestro proyecto Chirpstack-Docker . Después modificados el archivo docker-compose.yml para añadir a cada contenedor el volumen que contendrá los certificados correspondientes.
Seguimos siguiendo la documentación del proyecto Chirpstack-Certificates para realizar todas las modificaciones pertinentes en la configuración del servidor:
Como hemos visto anteriormente, el evento que se lanza al recibir un mensaje llama a una función que lee el mensaje recibido y lo descodifica.
El formato del mensaje recibido (si hemos usado los descodificadores del ejemplo) es una cadena de texto con el siguiente contenido:
{"applicationID":"1","applicationName":"APP_NAME","deviceName":"DEV_NAME","devEUI":"DEV_ADDRESS", "txInfo":{"frequency":868500000,"dr":5},"adr":true,"fCnt":2, "fPort":1,"data":"DATA","object":{"data":"DATA","decodedData":{"humidity":0,"temperature":-327},"message":"Informacion recibida del nodo"}}
Y es lo que buscamos leer en la siguiente función:
function insertSensorEntry_Mqtt(topic, msg){
console.log("INSERTAMOS DATO DE SENSOR RECIBIDO POR MQTT EN TOPICO: "+topic);
const parseMsg = JSON.parse(msg); //Recordar haber hecho un ToString al buffer antes!
var deviceName = parseMsg.deviceName;
var devAddr = parseMsg.devEUI; //No codificado
var temperature = parseMsg.object.decodedData.temperature;
var humidity = parseMsg.object.decodedData.humidity;
var success = true;
}
object es el objeto retornado por nuestra función Decoder .
Como bien se sabe, la tasa de transferencia de LoRA es muy baja, lo que provoca una gran perdida de paquetes y una enorme latencia cuando se envía información:
Algunos expertos indican que es necesario cierta distancia entre los dispositivos (30m y preferiblemente algún obstaculo entre ellos) para que la comunicación sea más fluida. No ha sido probado y solo se ha lanzado con las dos tarjetas en un extremo cada una de un piso.
Por otro lado se hace uso de versiones antiguas de LoRaWAN (1.0.2 y 1.0.3) que tienen problemas de seguridad que se solventan en parte en las siguientes versiones (1.0.4 y 1.1.0, esta última también implementa re-conectividad en caso de desconectarse de la red LoRaWAN), pero no se dispone de librerias para trabajar con ellas.
Esto no quita que esta técnología pueda ser muy interesante y útil en el futuro debido a no depender de proveedores externos (de comunicaciones y electricidad), siendo una opción ecónomica y muy llamativa para utilizar en proyectos IoT de grandes ciudades o entornos rurales.
Este proyecto ha sido realizado para la Fundación CTIC, su uso es libre y no es necesarío ningún crédito en su uso (Revisar las licencia de las librerias utilizadas).