Etiqueta: LoRaWAN

  • 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 instrucciones 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 convertidor 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.

    Chirpstack codec

    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:

    Chirpstack  device data

    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:

    mqtt tramas

    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 v3 - 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á.

    Chirpstack service profile create

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

    Chirpstack service profile add gateway meta-data

    2. Device Profile

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

    Chirpstack device profile create

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

    Chirpstack device-profiles general

    para conexión OTAA/ABP

    Chirpstack device-profiles OTTAA

    soporte de dispositivos clase B

    Chirpstack device-profiles Class-B

    soporte de dispositivos clase C

    Chirpstack device-profile class-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.

    Chirpstack applications create

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

    Chirpstack application create

    para finalmente registrar la aplicación

    Chirpstack applications service profile

    4. Añadir dispositivos a la aplicación

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

    Chirpstack leerRssiSNR

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

    Chirpstack applications device general

    El identificador único de dispositivo: Device EUI es primordial para la conexión por OTAA. El Device EUI se puede generar con el botón 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 botón para visualizar el que se esté usando, o en otro caso se puede generar para usar en la programación del dispositivo.

    Chirpstack applications device KEYS OTAA

    Si el dispositivo no ha sido conectado al menos una vez, la pestaña de activación aparece vacía. 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 botón de visualización en la parte derecha de la ventana.

    Chirpstack applications activation

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

    Chirpstack applications devices lorawan frames

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

    Chirpstack applications 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 v3 - 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:

    chirpstack organizacion

    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

    Chirpstack organizarions create

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

    chirpstack organization configuration

    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

    Chirpstack network servers add

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

    Chirpstack network-servers general

    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, así como el network-server indicado en la sección anterior.

    Gateway.profiles create

    se muestra un ejemplo de la configuración:

    Chirpstack gateway-profiles create

    Se pueden añadir usuarios 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:

    Chirpstack service-profiles

    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.

    Chirpstack servive profile update

    con lo que se puede añadir un Gateway:

    Chirpstack gateway create

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

    LoRaWAN – Gestor de paquetes / Packet forwarder

    Chirpstack gateway create

    siguiente parte de la ventana:

    Chirpstack gateway create

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

    Chirpstack gateways seen

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

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

    Chirpstack active gateways

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

     

     

     

     

     

     

  • 2.3 ChirpStack v3 - 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 v3 - network-server

    El network-server es el componente que se dedica a revisar los mensajes duplicados en la red, ya sea por re-intentos 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 autenticación , capa 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/

    Según la versión publicada a Agosto de 2025, solo se requiere una instrucción:

    apt install postgresql

    Instrucciones anteriores, desactualizadas

    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 instrucción, 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/package
    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/

  • 2.1 ChirpStack v3 - gateway-bridge

    Es el componente que convierte el protocolo LoRa-packet-forwarder en el formato de datos de ChirpStack-network-server que es el siguiente componente.

    Para la gestión de mensajes se usa un servidor MQTT existente y previamente configurado. Si no se dispone de uno, se puede instalar y configurar siguiendo las instrucciones de MQTT – Mosquitto instalar


    Instalación de ChirpStack-gateway-bridge v4.x

    Las instrucciones para Raspberry OS se encuentran simplificadas, las primeras son para acceder al repositorio de instalación y la siguiente para instalar el componente.

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

    Configuración gateway-bridge

    La configuración del componente se refiere principalmente al formato de reenvío del mensaje hacia el servidor MQTT.

    El archivo de configuración se lo puede editar con la instrucción:

    sudo nano /etc/chirpstack-gateway-bridge/chirpstack-gateway-bridge.toml
    

    La conexión al servidor MQTT se configura en el archivo, para el ejemplo se ha mantenido la simplicidad al no requerir usuario y contraseña para interactuar con Mosquitto. Recuerde cambiar esta situación una vez que esten terminadas todas las configuraciones y se ha probado la operatividad del mismo.

    # Integration configuration.
    [integration]
    # Payload marshaler.
    #
    # This defines how the MQTT payloads are encoded. Valid options are:
    # * protobuf:  Protobuf encoding
    # * json:      JSON encoding (easier for debugging, but less compact than 'protobuf')
    marshaler="json"
    
      # MQTT integration configuration.
      [integration.mqtt]
      # Event topic template.
      event_topic_template="gateway/{{ .GatewayID }}/event/{{ .EventType }}"
    
      # Command topic template.
      command_topic_template="gateway/{{ .GatewayID }}/command/#"
    
      # MQTT authentication.
      [integration.mqtt.auth]
      # Type defines the MQTT authentication type to use.
      #
      # Set this to the name of one of the sections below.
      type="generic"
    
        # Generic MQTT authentication.
        [integration.mqtt.auth.generic]
        # MQTT server (e.g. scheme://host:port where scheme is tcp, ssl or ws)
        server= "tcp:///127.0.0.1:1883"
        #"tcp://127.0.0.1:1883"
    
        # Connect with the given username (optional)
        username=""
    
        # Connect with the given password (optional)
        password=""
    

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

    sudo systemctl status chirpstack-gateway-bridge
    

    en el caso de que se requiera reiniciar el componente

    sudo systemctl restart chirpstack-gateway-bridge
    

    El estado del gateway-bridge será semejante a:

    CS gateway bridge Status 02

    Mensajes en MQTT-Mosquitto

    Los eventos y mensajes MQTT son semejantes a lo mostrado, revisando todos los mensajes que llegan a Mosquitto: se puede usar la instrucción.

    Para leer los contenidos de la configuración desde MQTT será necesario cambiar al formato a "json" en el archivo de configuración del gateway bridge.

    Los estados de los mensajes en formato json se observan en la imagen.

    CS gateway bridge MQTT 03

    mientras en formato "protobuf" se observa de la siguiente manera:

    CS gateway bridge MQTT 04

    Observe que en ambas situaciones es posible leer solo los valores correspondientes a los parámetros de transmisión, sin embargo los datos de usuario permanecen ilegibles.

    Referencia: version 4.x  https://www.chirpstack.io/docs/chirpstack-gateway-bridge/install/raspberry-pi.html

    version 3.x https://www.chirpstack.io/gateway-bridge/install/debian/