Broker / Gestión – IoT índice

Esta sección corresponde a implementar un gestor de dispositivos IoT que puede ser implementado sobre un Raspberry o un PC.

Hay que considerar el gestor/broker deberá permanecer encendido siempre , 24horas/días a la semana.

Por el consumo energético es conveniente usar un Raspberry Pi, sin embargo, para pruebas iniciales es posible implementarlo usando una PC con la versión de Raspberry Pi sobre PC.

Pasos de implementación

Las instrucciones de instalación, actualización y configuración para Raspberry Pi se encuentran en la sección:

1.1 Raspberry Pi OS – Instalar

Para luego proceder a instalar MQTT versión Mosquitto para gestionar los mensajes de estado del sensor descritos en la Sección:

1.2 MQTT – Mosquitto instalar

y finalmente instalar Home Assistant para gestionar mediante una página web los estados de los dispositivos, descritos en la Sección:

1.3 Home Assistant – Instalar

Redes de mayor alcance:

1.4 LoRaWan Open Gateway

3.4 LoRaWAN – MQTT – Python reporte txt

Para procesar el archivo del reporte.txt se puede leer mensaje por mensaje y extraer el registro de RSSI y SNR de cada dispositivo usando Python.

# procesar un archivo de mensajes mqtt
import numpy as np
import json as json

# INGRESO
# Parametros para la conexión
servidormqtt = "192.168.xx.xx"
topicolee = "#"

# Para el archivo.txt
nombrearchivo = 'unreporte.txt'
conteo = {"lineas":{'cuenta':0},
          "gateway":{'cuenta':0},
          "application":{'cuenta':0}
          }
tipotrama = []

# para tabular
tabla = []
registros = {}
frecuencias = []
tramabuscada = ['application/1/device/c9c2a03913ac2ec5/event/up',
                'application/1/device/b35915f22af620d1/event/up',
                'application/1/device/b5a2349b828d97ea/event/up',
                'application/1/device/f2f724028c0e996c/event/up']


# PROCEDIMIENTO
archivo = open(nombrearchivo,'r')
unalinea = archivo.readline()
while not(unalinea==''):
    conteo["lineas"]['cuenta'] = conteo["lineas"]['cuenta'] + 1
    unalinea = archivo.readline()
    unalinea = unalinea.strip('\n')
    desde = unalinea.find(" b'{")
    untipotrama = unalinea[0:desde]
    if not(untipotrama in tipotrama) and (untipotrama != ''):
        tipotrama.append(untipotrama)
        conteo[untipotrama] = {'cuenta':0}
    for entrada in conteo:
        if unalinea.startswith(entrada):
            conteo[entrada]['cuenta'] = conteo[entrada]['cuenta']+1

    for unapptrama in tramabuscada:
        tamanot = len(unapptrama)
        if unalinea.startswith(unapptrama):
            datostxt = unalinea[tamanot+3:].strip("'")
            datosjson = json.loads(datostxt)

            undeviceName = datosjson["deviceName"]
            unrssi = datosjson["rxInfo"][0]["rssi"]
            unloRaSNR = datosjson["rxInfo"][0]["loRaSNR"]
            unfrequency = datosjson["txInfo"]["frequency"]
            undr = datosjson["txInfo"]["dr"]
            if not(unfrequency in frecuencias):
                frecuencias.append(unfrequency)
                
            if undeviceName in registros:
                registros[undeviceName]['conteo'] = registros[undeviceName]['conteo']+1
                registros[undeviceName]['rssi'].append([unfrequency,unrssi,
                                                         unloRaSNR,undr])
            else:
                registros[undeviceName]={'rssi':[],
                                         'conteo':0,
                                         'resumen':[0,0,0,0],
                                         }      
 
archivo.close()  # Cierra el archivo

# Calcula resumen por dispositivo
frecuencias.sort()
frecuencia = [902300000, 902500000, 902700000, 902900000,
              903100000, 903300000, 903500000, 903700000]
canalobserva = len(frecuencia)                                               
for dispositivo in registros:
    vector = np.array(registros[dispositivo]['rssi'])
    cuenta = np.zeros(canalobserva, dtype=int)   
    suma = np.zeros(canalobserva,dtype=int)
    channelid = np.arange(1, canalobserva+1)
    cadaRSSI = [[],[],[],[],[],[],[],[],[]]
    cadaSNR  = [[],[],[],[],[],[],[],[],[]]
    cadadr   = [[],[],[],[],[],[],[],[],[]]
    resumen = []
    # Clasificando
    k = len(vector)
    for j in range (0,k,1):
        cual = frecuencia.index(vector[j][0])
        valorRssi = vector[j][1]
        valorSNR = vector[j][2]
        valordr = vector[j][3]
        cadaRSSI[cual].append(valorRssi)
        cadaSNR[cual].append(valorSNR)
        cadadr[cual].append(valordr)
    
    for j in range(0,canalobserva,1):
        vectorRSSI = np.array(cadaRSSI[j])
        vectorSNR = np.array(cadaSNR[j])
        vectordr = np.array(cadadr[j])
        if len(vectorRSSI)>0:
            promedioRSSI = np.average(vectorRSSI)
            maximoRSSI = np.max(vectorRSSI)
            cantidadRSSI = len(vectorRSSI)
            minimoRSSI = np.min(vectorRSSI)
            
            promedioSNR = np.average(vectorSNR)
            maximoSNR = np.max(vectorSNR)
            cantidadSNR = len(vectorSNR)
            minimoSNR = np.min(vectorSNR)

            promediodr = np.average(vectordr)
            maximodr = np.max(vectordr)
            cantidaddr = len(vectordr)
            minimodr = np.min(vectordr)
            
            resumen.append(np.array([ j+1,
                                      cantidadRSSI,
                                      promedioRSSI,
                                      minimoRSSI,
                                      maximoRSSI,
                                      promedioSNR,
                                      minimoSNR,
                                      maximoSNR,
                                      promediodr,
                                      ]))
    resumen = np.array(resumen)
    registros[dispositivo]['resumen'] = resumen

# SALIDA
np.set_printoptions(precision = 2)
print('conteo de tramas')
for entrada in conteo:
    print(entrada,": ", conteo[entrada]['cuenta'])
print('frecuencias: ',frecuencia)
print('\nTabulando ---------')
for dispositivo in registros:
    print()
    print('dispositivo_id: '+str(dispositivo))
    print('total muestras: '+str(registros[dispositivo]['conteo']))
    print('Promedios RSSI y SNR: ')
    print('[canal muestras\t RSSI \t min \t max \t SNR  min   max   DR  ]')
    print(registros[dispositivo]['resumen'])
    registros[dispositivo]['conteo']

 

3.3 LoRaWAN – mensajes MQTT y Python

De disponer de acceso al servidor MQTT se pueden capturar los mensajes y procesarlos por ejemplo para realizar estadísticas de RSSI y SNR de cada dispositivo respecto al Gateway.

Se requiere una conexión autenticada al servidor MQTT, para caso experimental se recurre a Python con la librería PAHO para acceder como cliente.

# grabando mensajes MQTT
# configurar los parámetros para la creacion de archivo de texto
import paho.mqtt.client as mqtt

# INGRESO
# Parametros para la conexión
servidormqtt = "192.168.xx.xx"
topicolee = "#"

# Para el archivo.txt
cuentamensaje = 0
nombrearchivo = 'unreporte.txt'
archivo = open(nombrearchivo,'w')
archivo.close()  # Cierra el archivo

tramabuscada = ['application/1/device/c9c2a03913ac2ec5/event/up',
                'application/1/device/b35915f22af620d1/event/up',
                'application/1/device/b5a2349b828d97ea/event/up',
                'application/1/device/f2f724028c0e996c/event/up']
cuentaDisp = [0,0,0,0]
cuentagtw = 0

# BLOQUE BÁSICO DE PROGRAMA
# Al recibir CONNACK desde el servidor.
def on_connect(client, userdata, flags, rc):
    print("Conexión/código de resultado: "+str(rc))

    # Inicio o renovación de subscripción
    client.subscribe(topicolee)

    return()

# el tópico tiene una publicación
def on_message(client, userdata, msg):
    global cuentamensaje
    print(msg.topic) #+" "+str(msg.payload))
    unmensaje = msg.topic+" "+str(msg.payload)

    # Archivo en modo añadir 'append'
    archivo = open(nombrearchivo,'a')
    unalinea = unmensaje + '\n'
    archivo.write(unalinea)
    
    if (msg.topic in tramabuscada):
        cual = tramabuscada.index(msg.topic)
        cuentaDisp[cual] = cuentaDisp[cual] + 1
        
    cuentamensaje = cuentamensaje + 1
    print('\n mensajes recibidos: ', cuentamensaje)
    print(' cuenta por dispositivos: ', cuentaDisp)
    print()

    return()

client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.connect(servidormqtt, 1883, 60)
client.loop_forever()

3.2 LoRaWAN – ChirpStack-Home Assistant

Una forma de registrar los datos que transmite un dispositivo en Home Assistant es mediante la subscripción al mensaje MQTT correspondiente a la trama LoRaWAN.

En la sección anterior se describe la forma de enviar los datos por LoRaWAN.  mediante la subscripción al mensaje MQTT desde Home Assistant donde se registra y muestra el dato.

Para añadir el dispositivo a Home Assitant, se añade en el archivo de configuración las características del dispositivo y el mensaje MQTT al que se debe conectar. Esto se realiza editando el archivo de dispositivos con la intrucción:

sudo nano /home/homeassistant/.homeassistant/configuration.yaml

por ejemplo, para registrar valores de RSSI y SNR del paquete transmitido se añaden las siguientes instrucciones:

sensor:
  - platform: mqtt
    name: 'Dispositivo_LRW01_rssi'
    unit_of_measurement: 'dBm'
    state_topic: 'application/1/device/c9c2a03913ac2ec5/event/up'
    value_template: "{{ value_json.rxInfo[0].rssi}}"
    json_attributes_topic: 'application/1/device/c9c2a03913ac2ec5/event/up'

  - platform: mqtt
    name: 'Dispositivo_LRW01_SNR'
    unit_of_measurement: 'dB'
    state_topic: 'application/1/device/c9c2a03913ac2ec5/event/up'
    value_template: "{{ value_json.rxInfo[0].loRaSNR}}"

Para cada caso particular, se requiere actualizar el identificador de dispositivo además de  valores a tomar de la trama en formato json.

nota: el editor de archivo «nano» usa las teclas «Ctrl O» para grabar los cambios y «Ctrl X» para salir del editor.

Una vez actualizado el archivo de configuration.yaml, se reinicia Home Assistant desde la sección de configuración/controles de servidor/reiniciar.

Finalmente se visualiza el dispositivo y sus datos en el historial y en su respectiva posición del tablero.

Referencia: https://www.home-assistant.io/integrations/sensor.mqtt/#json-attributes-topic-configuration

 

3.1 LoRaWAN – mensajes MQTT

Los datos son enviados como un tren de bits escritos en hexadecimal desde el dispositivo.

Por ejemplo, un mensaje a transmitir conformado por 4 datos numéricos en hexadecimal desde el dispositivo son:

static void prepareTxFrame( uint8_t port ){
    appDataSize = 4;//AppDataSize max value is 64
    appData[0] = 0x00;
    appData[1] = 0x01;
    appData[2] = 0x02;
    appData[3] = 0x03;
}

Se leen en un mensaje mqtt como:

application/1/device/3532363324003700/event/up {
    "applicationID":"1",
    "applicationName":"GirniAppPrueba01",
    "deviceName":"GirniDispositivo01",
    "devEUI":"3532363324003700",
    "txInfo":{"frequency":902700000,"dr":0},
    "adr":true,
    "fCnt":0,
    "fPort":2,
    "data":"AAECAw=="
    }

por lo que el mensaje recibido por el gateway es:

"data":"AAECAw=="

que para leerlo nuevamente en hexadecimal requiere ser traducido desde «base64» por ejemplo en la consola de Rasberry OS como:

pi@GWHTM01:~ $ echo -n AAECAw== | base64 --decode | hexdump -C
00000000  00 01 02 03                                       |....|
00000004

que es el mensaje original enviado desde el dispositivo

3. LoRaWAN – Codec/Decode para datos en tramas

Los datos de sensor/acción se ordenan en una trama LoRa en forma de bytes antes de la transmisión. Se pretende minimizar la cantidad de bytes usados por mensaje, siguiendo la directiva LoRa de mensajes de corta duración.

Un mensaje se puede simplificar, por ejemplo un «ON»/»OFF» presentado en LoRa puede ser 1 «o» 0, que es tan solo un bit. Los mensajes se administran por ChirpStack y los puede traducir nuevamente en mensajes «ON»/»OFF» para ser actualizados en un Broker como Home Assistant.

Un ejemplo básico de instrucciones para un dispositivo genérico permite presentar el uso de librerías LoRaWAN de HELTEC.

Trama de datos en dispositivo

Los datos son enviados en una trama como un tren de bits escritos en orden. Por ejemplo, en el dispositivo se tiene los valores de contador1, contador2 y unalectura como datos a ser transmitidos, por lo que se plantea el siguiente esquema:

Las instruciones en el IDE arduino para el ejemplo de la trama de datos Sigue el mismo orden.

byte    contador1 = 0;
uint8_t contador2 = 0;  
int unalectura = 221;

static void prepareTxFrame( uint8_t port ){
    contador1 = contador1 + 1;
    contador2 = contador2 - 1;

    //orden de trama
    appDataSize = 4         //AppDataSize max value is 64
    appData[0] = contador1; //0x01;
    appData[1] = contador2;
    appData[2] = highByte(unalectura);
    appData[3] = lowByte(unalectura);

    // mostrar en puerto USB
    Serial.println(contador1);
    Serial.println(contador2);
    Serial.println(unalectura);
}

En casos particulares hay que ajustar la trama de acuerdo a las lecturas de sensores o información que se requiera transmitir

Trama de datos en ChirpStack application – server

La trama de datos llega en binario hasta el componente application-server y de forma predeterminada se presenta en formato Base64.

Para leer los datos se puede usar el convetidor en línea o utilizar un decodificador/codificador con instrucciones en JavaScript.

https://v2.cryptii.com/base64/decimal

En ChirpStack en la sección Device-profiles/codec se puede escribir un decodificador para la trama de datos y reconstruirlo en la forma con las variables originales.

para el ejemplo presentado y siguiendo el esquema inicial, las instrucciones en JavaScript son:

function Decode(fPort, bytes, variables) {
	var contador1 = bytes[0];
  	var contador2 = bytes[1];
  	var unalectura = (bytes[2] << 8) |(bytes[3]);
  var appData = {'contador1':contador1, 'contador2':contador2, 'unalectura': unalectura}
  return appData;
}

Con lo que en Chirpstack se obtiene para datos del dispositivo de una trama en particular:

Referencia: https://heltec-automation-docs.readthedocs.io/en/latest/general/decode_payload.html

Trama de datos en MQTT-Mosquitto

Para capturar los datos en un broker, por ejemplo Home Assistant, se puede usar el mensaje MQTT del application-server. Es posible leer las tramas MQTT de application-server o integrar las plataformas entre si por medio de «integration»

Lecturas de mensajes MQTT

Para observar la estructura del mensaje se realiza una subscripción al mensaje MQTT de la aplicación para un dispositivo:

mosquitto_sub -v -h localhost -p 1883 -t 'application/1/device/#'

y se obtiene los datos decodificados por JavaScript:

Con lo que se puede proceder a incorporar la instrucción en Home-Assistant.

Referencia: TTN – Optimizacion Payload.pdf , https://github.com/akirasan/TTN_LoRaWAN

 

2.5 ChirpStack – Añadir un dispositivo

Para añadir un dispositivo en el Broker ChirpStack, el ejemplo básico envía una trama solo para leer los datos de niveles de señal RSSI y SNR.

1.  Application Service Profile

El perfil de servicio en la aplicación se asigna un nombre acorde a la aplicación que la usará.

se ingresan los parametros requeridos, por simplicidad solo se añade un nombre. Ejemplo:

2. Device Profile

El perfil de dispositivos describe la forma de conexión y autenticación de un grupo de dispositivos.

Por ejemplo, si los dispositivos autentican por medio de OTTA/APB, si se incluirán dispositivos clase B, clase C y las instrucciones para codificar o decodificar los datos del dispositivo (CODEC).

para conexión OTAA/ABP

soporte de dispositivos clase B

soporte de dispositivos clase C

Para el tema de CODEC se recomienda revisar la sección de LoRaWAN – Mensajes y datos entre componentes

3. Applications

La aplicación agrupa dispositivos que realizan funciones semejantes, mediante el perfil del dispositivo, donde se encuentra también el CODEC de los datos.

Se asigna un nombre y una descripción de lo que va a realizar con los dispositivos:

para finalmente registrar la aplicación

4. Añadir dispositivos a la aplicación

Hay que crear cada dispositivo con identificadores únicos y autenticarlos en la red.

los primeros datos corresponden a nombre y nombre y descripción.

El identificador único de dispositivo: Device EUI es primordial para la conexión por OTAA. El Device EUI se puede generar con el boton mostrado en la pantalla y se usa en la programación del dispositivo.

El  perfil del dispositivo se selecciona desde la pestaña y se despliegan las opciones.

https://heltec-automation-docs.readthedocs.io/en/latest/esp32/lorawan/config_parameter.html

https://www.thethingsnetwork.org/docs/lorawan/addressing.html

los parámetros para OTAA se pueden visualizar, generar en la pestaña correspondiente. Hay un boton para visualizar el que se esté usando, o en otro caso se puede generar para usar en la programación del dispositivo.

Si el dispositivo no ha sido conectado al menos una vez, la pestaña de activación aparece vacia. Para obtener los datos de activación es necesario realizar al menos un intento de conexión, con lo que la ventana llena los datos para completar la programación del dispositivo.

Para observar los datos de activación debe usar el boton de visualización en la parte derecha de la ventana.

Los intentos de conexión se pueden visualizar en la pestaña de LoRaWAN Frames

mientras que los datos recibidos se observan en la pestaña de Device Data

Hay que considerar que la primera vez que se conecta el dispositivo, la autenticación puede llevar algunos intentos, por lo que hay que esperar para que se comiencen a recibir los datos, a pesar que las tramas LoRaWAN si se registran en el programa.

5. Instrucciones Arduino IDE ejemplo básico

Los datos para la configuración del dispositivo se obtienen en el proceso descrito anteriormente, por lo que es necesario actualizar los datos.

En el caso de dispositivos HELTEC es necesario obtener los datos de licencia que se encuentran al inicio de las instrucciones. La licencia de cada dispositivo se puede revisar en: https://resource.heltec.cn/search/

/*
 * HelTec Automation(TM) LoRaWAN 1.0.2 OTAA example use OTAA, CLASS A
 * Solo ESP32+LoRa series boards con licencia http://www.heltec.cn/search/);
 *https://github.com/HelTecAutomation/ESP32_LoRaWAN
*/
#include <ESP32_LoRaWAN.h>
#include "Arduino.h"

/*licencia Heltec ESP32 LoRaWan http://resource.heltec.cn/search  
uint32_t  license[4] = {0xBE21335B, 0xAEC3C5CE, 0xCC0A1CF4, 0xB836F981};
/* OTAA parametros 
uint8_t DevEui[] = { 0x01, 0x20, 0x08, 0x93, 0xdf, 0x80, 0x37, 0x74 };
uint8_t AppEui[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t AppKey[] = { 0x05, 0x8e, 0xeb, 0xff, 0x24, 0xf1, 0x01, 0x84, 0xd0, 0x07, 0xbe, 0xd4, 0x65, 0xe7, 0x6b, 0xb5 };

/* ABP parametros 
uint32_t DevAddr =  ( uint32_t )0x0174b1fd;
uint8_t NwkSKey[] = { 0xc1, 0x45, 0x31, 0x28, 0x5f, 0xb2, 0x56, 0x3b, 0x9d, 0x5f, 0x27, 0x15, 0xed, 0x3a, 0x0e, 0xbc}; 
uint8_t AppSKey[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

//LoraWan channelsmask, default channels 0-7/
uint16_t userChannelsMask[6]={ 0x00FF,0x0000,0x0000,0x0000,0x0000,0x0000 };

DeviceClass_t  loraWanClass = CLASS_A;  /*Soporte de A and C 
uint32_t appTxDutyCycle = 15000;        /*15000; en [ms] 
bool overTheAirActivation = true;       /*OTAA or ABP 
bool loraWanAdr    = true;              /*ADR enable 
bool isTxConfirmed = true;              /*confirmed or unconfirmed messages  
uint8_t appPort = 2;                    /* Application port  

/* reintentos de transmisión, en caso de no recibir ack  
uint8_t confirmedNbTrials = 8;

/* Seleccionado de Arduino IDE tools  
uint8_t debugLevel = LoRaWAN_DEBUG_LEVEL; 
LoRaMacRegion_t loraWanRegion = ACTIVE_REGION;

// variables de sensor/actuador
byte    contador1 = 0;
uint8_t contador2 = 0;  
int    unalectura = 221;

void setup(){
  Serial.begin(115200);
  while (!Serial);
  SPI.begin(SCK,MISO,MOSI,SS);
  Mcu.init(SS,RST_LoRa,DIO0,DIO1,license);
  deviceState = DEVICE_STATE_INIT;
}
void loop(){
  switch( deviceState )  {
    case DEVICE_STATE_INIT:    {
      LoRaWAN.init(loraWanClass,loraWanRegion);
      break;
    }
    case DEVICE_STATE_JOIN:    {
      LoRaWAN.join();
      break;
    }
    case DEVICE_STATE_SEND:    {
      prepareTxFrame( appPort );
      LoRaWAN.send(loraWanClass);
      deviceState = DEVICE_STATE_CYCLE;
      break;
      
    }
    case DEVICE_STATE_CYCLE:    {
      // Schedule next packet transmission
      txDutyCycleTime = appTxDutyCycle + randr( -APP_TX_DUTYCYCLE_RND,
                                                APP_TX_DUTYCYCLE_RND );
      LoRaWAN.cycle(txDutyCycleTime);
      deviceState = DEVICE_STATE_SLEEP;
      break;
    }
    case DEVICE_STATE_SLEEP:    {
      LoRaWAN.sleep(loraWanClass,debugLevel);
      break;
    }
    default:    {
      deviceState = DEVICE_STATE_INIT;
      break;
    }
  }
}

static void prepareTxFrame( uint8_t port ){
    contador1 = contador1 + 1;
    contador2 = contador2 - 1;

    //orden de trama
    appDataSize = 4         //AppDataSize max value is 64
    appData[0] = contador1; //0x01;
    appData[1] = contador2;
    appData[2] = highByte(unalectura);
    appData[3] = lowByte(unalectura);

    // mostrar en puerto USB
    Serial.println(contador1);
    Serial.println(contador2);
    Serial.println(unalectura);
}

2.4 ChirpStack – Añadir un Gateway

Los pasos de las secciones anteriores permiten habilitar una página web donde se pueden añadir los gateways que se van a gestionar.

Inicicialmente al abrir la página en la dirección asignada, se mostrarán todos los elementos vacios:

Es necesario añadir una configuración básica para activar y ordenar los gateways.

1.  Organización

Se asigna un nombre a la organización o empresa que usa ChirpStack

completar los datos requeridos para la organización y al final usar «update organization»

2. Servidor de Red: Network Server

Use los parámetros indicados en el archivo de configuración de la sección de ChirpStack – network-server

con los parámetros usados en la instalación, complete las casillas:

Para configurar otros parámetros del network-server, revisar el enlace:

https://www.chirpstack.io/network-server/install/config/

3. Perfiles de Gateway: Gateway-profiles

Se requiere disponer de un perfil de gateway, se indica los canales que usa el gateway, asi como el network-server indicado en la sección anterior.

se muestra un ejemplo de la configuración:

Se pueden añadir usauarios y llaves API, para la configuración básica no se realizará esta actividad.

4. Perfiles de Servicio: Service-profile

Es necesario crear un perfil de servicios para los gateways de la organización:

con el que se indica a que network-server se conectará el gateway, y si se añadirán parámetros de estado de la señal.

con lo que se puede añadir un Gateway:

para crear el gateway se requiere el parámetro de «gateway_id» de la sección:

LoRaWAN – Gestor de paquetes / Packet forwarder

siguiente parte de la ventana:

De completar el proceso de registro es posible observar el estado de «last seen» en hace pocos segundos «a few seconds ago».

Terminando así el proceso de añadir un gateway a ChirpStack.

Tambien es posible observar en el tablero principal de la organización:

El siguiente paso es añadir un dispositivo que se conecta al gateway.

 

 

 

 

 

 

2.3 ChirpStack – application-server

Componente encargado de administrar el inventario de dispositivos, solicitudes nuevas de conexiónn, encriptación y datos de aplicación.

Añade una interfase tipo web para administrar usuarios, organizaciones, aplicaciones y dispositivos.

Base de datos de mensajes

Esta sección requiere su propia base de datos:

sudo -u postgres psql
create role chirpstack_as with login password 'dbpassword';
create database chirpstack_as with owner chirpstack_as;
\c chirpstack_as
create extension pg_trgm;
create extension hstore;
\q

verifique que el usuario de la base de datos funciona:

psql -h localhost -U chirpstack_as -W chirpstack_as

Instalación de ChirpStack-application-server

Se añaden las referencias del repositorio de los archivos de instalación para ejecutar luego el proceso de instalación.

sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 1CE2AFD36DBCCA00
sudo echo "deb https://artifacts.chirpstack.io/packages/3.x/deb stable main" | sudo tee /etc/apt/sources.list.d/chirpstack.list
sudo apt-get update
sudo apt-get install chirpstack-application-server

Configuración de ChirpStack-application-server

El archivo de configuración requiere actualizar la información de usuario y password de la base de datos antes configurada.

Uno de los parámetros es jwt, que se genera con la instrucción:

openssl rand -base64 32

mantenga una copia del resultado para ser usado en el parámetro «jwt» al editar el archivo siguiente:

sudo nano /etc/chirpstack-application-server/chirpstack-application-server.toml

por ejemplo:

dsn="postgres://chirpstack_as:dbpassword@localhost/chirpstack_as?sslmode=disable"

marshaler="json"<

# JWT secret used for api authentication / authorization
# You could generate this by executing 'openssl rand -base64 32' for example
jwt_secret="------------------"

Para revisar el estado o reiniciar el componente, se usa el la instrucción:

sudo systemctl status chirpstack-application-server

sudo systemctl restart chirpstack-application-server

De encontrarse todo en funcionamiento, debe ser posible acceder a la versión web de Chirpstack en la dirección IP y puerto (8080)

Referencia: https://www.chirpstack.io/application-server/install/debian/

 

 

2.2 ChirpStack – network-server

El network-server es el componente que se dedica a revisar los mensajes dupolicados en la red, ya sea por reintentos de transmisión desde un mismo dispositivo o por recepción de mensajes en más de un gateway.

Además de encargarse de la atenticación , capac MAC, comunicación con el componente de aplicaciones y gestión de colas de mensajes de envió hacia dispositivos.

Base de datos de mensajes

Para manejar los mensajes es necesario  disponer de una base de datos. PostgreSQL es la base de datos predeterminada.

En caso de no disponer de la base de datos, la puede instalar siguiendo las instrucciones en:

https://www.postgresql.org/download/linux/debian/

sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
sudo apt-get update

sudo apt-get -y install postgresql

Creación de usuario, password y base de datos

Se inicia el programa de la base de datos con la primera instruccion, luego el usuario y contraseña.

sudo -u postgres psql
create role chirpstack_ns with login password 'dbpassword';
create database chirpstack_ns with owner chirpstack_ns;
\q

para verificar el usuario se realiza un intento de conexión a la base con :

psql -h localhost -U chirpstack_ns -W chirpstack_ns

Instalación base de datos Redis

Usada para guardar los datos de cada sesión , datos no persistentes, de duplicación y meta-data.

sudo apt install redis-server

Instalación de ChirpStack-network-server

Semejante al componente anterior, se añaden las referencias del repositorio de los archivos de instalación para ejecutar luego el proceso de instalación.

sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 1CE2AFD36DBCCA00
sudo echo "deb https://artifacts.chirpstack.io/packages/3.x/deb stable main" | sudo tee /etc/apt/sources.list.d/chirpstack.list
sudo apt update
sudo apt install chirpstack-network-server

Configuración de ChirpStack-network-server

El archivo de configuración requiere actualizar la información de usuario y password de la base de datos antes configurada.

Ademas revisar los parámetros de: postgresql.dsn, postgresql.automigrate, network_server.net_id, network_server.band.name, metrics.timezone.

sudo nano /etc/chirpstack-network-server/chirpstack-network-server.toml

Por ejemplo:

[general]
log_level=4

[postgresql]
dsn="postgres://chirpstack_ns:dbpassword@localhost/chirpstack_ns?sslmode=disable"

[network_server.band]
name="US915"

cambiar a comentario la seccion: 
# Extra channel configuration.

Revisar el detalle de la línea dsn, pues el usuario al final de la línea vienen escrito con doble _ns_ns.

Añadir al final del archivo los datos de usuario y contraseña para el servicio MQTT

Para revisar el estado del componente se usa el la instrucción:

sudo systemctl status chirpstack-network-server
sudo systemctl restart chirpstack-network-server

debiendo obtener una respuesta semejante a

Para revisar el historial de actividad (log) y verificar operatividad

journalctl -u chirpstack-network-server -f -n 50

Referencia: https://www.chirpstack.io/network-server/install/debian/