Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Info
titleMOVED

https://docs.lobaro.com/xwiki/bin/view/Main/LoRaWAN%20Modbus%20Gateway/


The Lobaro LoRaWAN Modbus Gateway is a LoRaWAN Gateway with integrated LoRaWAN Network Server providing sensor data via Modbus.

Hardware Components

LoRaWAN Gateway
  • External SSD for storage
  • USB-Modbus Adapter
  • IMST VersionRAK Version

    Image Added

    Image Added

    Currently not available

    • LoRaWAN
    • Connectivity: LAN
    • Order number: 8000101
    • Type: LOB-GW-MODBUS-LW-IMST

    New Version based on RAK Wireless

    • LoRaWAN
    • Connectivity: LTE / LAN / WLAN
    • Order number: 8000202
    • Type: LOB-GW-MODBUS-LW-RAK


    USB-Modbus Adapter

    Image Added


    Software Components

    • Chirpstack Network Server
      • Semtech Packet Forwarder
      • Chirpstack Gateway Bridge
      • Chirpstack Network Server
      • Chirpstack

    The internal SD-Card is write protected. All variable data is stored on the external SSD to avoid SD-Card damage over time.

    Software Components

    • Chirpstack Network Server
      • Semtech Packet Forwarder
      • Chirpstack Gateway Bridge
      • Chirpstack Network Server
      • Chirpstack Application Server
      • Postgres
      • Redis
    • Lobaro Modbus Server

    Usually you will not need to change anything inside the Chirpstack Application Server. All devices are managed by the Lobaro Modbus Server.

    Remote access

    Per default the gateway obtains the IP address via DHCP. If configured with a fixed IP address, the gateway has a label with the configured IP address and subnet.

    SSH Access

    The gateway can be accessed via SSH on port 22. Default login credentials are:

    • User: pi
    • Password: lobarogw

    Lobaro Modbus Server

    The Lobaro Modbus Server (lobaro-modbus-server) is responsible for fetching data from the local LoRaWAN Network Server and provides received data via modbus.

    To change any filed on the SD Card (including all config files) you need to execute the script:

    No Format
    ~/enableWriteAccess.sh

    To disable write access, restart the gateway or execute:

    No Format
    ~/disableWriteAccess.sh

    For editing files vim is installed.

    Open or change configuration of the Lobaro Modbus Server:

    No Format
    sudo vim /etc/lobaro-modbus-server/lobaro-modbus-server.yml

    After editing the configuration lobaro-modbus-server must be restarted:

    No Format
    sudo systemctl restart lobaro-modbus-server

    Check the status with

    No Format
    sudo systemctl status lobaro-modbus-server

    Check the logs with

    No Format
    sudo journalctl --no-pager -e -u lobaro-modbus-server

    Debugging

    Beside checking the logs, you can also analyze the files in the dataDir (see config).

    There are two files that help writing the config and checking the results.

    • device-data.json - contains raw json received from Chirpstack. Can be used to verify mapping[].register.value configuration.
    • register-map.json - contains all register values provided via modbus. All values are formatted as int.

    Example device-data.json:

    • IP: DHCP with fallback to 192.168.0.1/24 (IMST) or 192.168.0.1/24 (RAK)
      • On RAK with latest image also possible via WLAN AP:
        • Default SSID "RAKMBG_XXYY" (XX and YY last bytes of WLAN adapter MAC) and password "lobarowireless", RAK IP 192.168.230.1

    Management UI

    Chirpstack


    SD Card write protection

    Note

    Write protection on the SD card was removed in current firmware releases

    To change any filed on the SD Card (including all config files) you need to execute the script:

    No Format
    ~/enableWriteAccess.sh

    To disable write access, restart the gateway or execute:

    No Format
    ~/disableWriteAccess.sh


    Lobaro Modbus Server

    The Lobaro Modbus Server (lobaro-modbus-server) is responsible for fetching data from the local LoRaWAN Network Server and provides received data via modbus.

    Info

    vim can be used to edit files.


    To use WinSCP with the user "pi" the files need write access:

    Code Block
    sudo chmod o+wr /etc/lobaro-modbus-server/lobaro-modbus-server.yml


    Open or change configuration of the Lobaro Modbus Server:

    No Format
    sudo vim /etc/lobaro-modbus-server/lobaro-modbus-server.yml

    After editing the configuration lobaro-modbus-server must be restarted:

    No Format
    sudo systemctl restart lobaro-modbus-server

    Check the status with

    No Format
    sudo systemctl status lobaro-modbus-server

    Check the logs with

    No Format
    sudo journalctl --no-pager -e -u lobaro-modbus-server

    Weitere Services

    There are other services running to operate the gateway.

    • lobaro-modbus-server
    • redis-server
    • postgresql / postgresql@9.6-main.service
    • mosquitto
    • IoTSemtech
    • chirpstack-gateway-bridge
    • chirpstack-network-server
    • chirpstack-application-server


    Useful commands:

    Code Block
    # Status:
    sudo systemctl status <service-name>
    # Start / Stop / Restart
    sudo systemctl start <service-name>
    sudo systemctl stop <service-name>
    sudo systemctl restart <service-name>
    # Logs
    sudo journalctl --no-pager -e -u <service-name>


    Debugging

    Beside checking the logs, you can also analyze the files in the dataDir (see config).

    There are two files that help writing the config and checking the results.

    • device-data.json - contains raw json received from Chirpstack. Can be used to verify mapping[].register.value configuration.
    • register-map.json - contains all register values provided via modbus. All values are formatted as int.

    Example device-data.json:

    Code Block
    languagejs
    themeConfluence
    linenumberstrue
    {
      "0000000000000000-1": {
        "adr": true,
        "applicationID": "1",
        "applicationName": "default",
        "data": "AAMEAOQN1g==",
        "devEUI": "0000000000000000",
        "deviceName": "0000000000000000",
        "fCnt": 1,
        "fPort": 1,
        "object": {
          "temp": 22.8,
          "vBat": 3.542,
          "version": "v0.3.4"
        },
        "rxInfo": [
          {
    Code Block
    languagejs
    themeConfluence
    linenumberstrue
    {
      "0000000000000000-1": {
        "adr": true,
        "applicationID": "1",
        "applicationName": "default",
        "data": "AAMEAOQN1g==",
        "devEUI": "0000000000000000",
        "deviceName": "0000000000000000",
        "fCnt": 1,
        "fPort": 1,
        "object": {
          "temp": 22.8,
          "vBat": 3.542,
          "version": "v0.3.4"
        },
        "rxInfo": [
          {
            "gatewayID": "0000000000000000",
            "loRaSNR": 8.8,
            "location": {
              "altitude": 0,
              "latitude": 0,
              "longitude": 0
            },
            "name": "default",
            "rssi": -36,
            "uplinkIDgatewayID": "ce2e086a-d747-4813-9428-b7a4a45abcc8"
    0000000000000000",
             }"loRaSNR": 8.8,
        ],
        "txInfolocation": {
              "draltitude": 0,
              "frequencylatitude": 868300000
    0,
             } "longitude": 0
            }
    }
    
    

    Example register-map.json:

    Code Block
    languagejs
    themeConfluence
    linenumberstrue
    {
      "Register": {
    ,
            "100name": {
          "Valdefault": 0,
            "Typerssi": 1-36,
            "UpdatedAtuplinkID": "2020-02-07T13:44:03.39750918Zce2e086a-d747-4813-9428-b7a4a45abcc8"
        }
      }
    }

    Configuration file

    Example config:

        ],
        "txInfo": {
          "dr": 0,
          "frequency": 868300000
        }
      }
    }
    
    

    Example register-map.json:

    Code Block
    languagejs
    themeConfluence
    linenumberstrue
    {
      "Register": {
        "100": {
          "Val": 0,
          "Type": 1,
          "UpdatedAt": "2020-02-07T13:44:03.39750918Z"
        }
      }
    }

    Configuration file

    Register Types

    For mapping.[device].register.type the following types are valid:

    "type" ParameterRegister Count
    int161
    uint161
    uint322
    int322
    float322
    downlink1


    Code Block
    languageyml
    themeConfluence
    titleExample Configuration
    linenumberstrue
    # The application stores persistent data at this path
    dataDir: /mnt/ssd/var/data/lobaro-modbus-server/
    
    # Chipstack configuration. Required to manage configured LoRaWAN devices.
    chirpstack:
      server: http://localhost:8080
      broker: localhost
      appId: 1
      username: admin
      password: admin
    
    # Modbus configuration. 
    # <v1.2.0: Serial mode is fixed at: 8 Data bits, Even Parity, 1 Stop bit (8E1)
    modbus:
      baud: 19200
      dataBits: 8 # since v1.2.0
      parity: "even" # no, even (default), odd - since v1.2.0
      stopBits: 1 # 1 (default), 1.5, 2 - since v1.2.0
      slaveId: 1
      port: /dev/ttyUSB0
    
    # Mapping from LoRaWAN Sensors to Modbus Registers
    mapping:
      # LoRaWAN Sensor parameters
      - devEUI: 0000000000000000
        appKey: 00000000000000000000000000000000
        # Chirpstack Device Profile to use. Includes the Payload Parser.
        devProfile: lobaro-environment
        devName: "name of device in chirpstack"
        # Register mapping for this device
        # One device can fill any number of registers.
        # The server will check for overlapping definitions on start.
        register
    Code Block
    languagejs
    themeConfluence
    linenumberstrue
    # The application stores persistent data at this path
    dataDir: /mnt/ssd/var/data/lobaro-modbus-server/
    
    # Chipstack configuration. Required to manage configured LoRaWAN devices.
    chirpstack:
      server: http://localhost:8080
      broker: localhost
      appId: 1
      username: admin
      password: admin
    
    # Modbus configuration. 
    # <v1.2.0: Serial mode is fixed at: 8 Data bits, Even Parity, 1 Stop bit (8E1)
    modbus:
      baud: 19200
      dataBits: 8 # since v1.2.0
      parity: "even" # no, even (default), odd - since v1.2.0
      stopBits: 1 # 1 (default), 1.5, 2 - since v1.2.0
      slaveId: 1
      port: /dev/ttyUSB0
    
    # Mapping from LoRaWAN Sensors to Modbus Registers
    mapping:
      # LoRaWAN Sensor parameters
      - devEUI: 0000000000000000
        appKey: 00000000000000000000000000000000
        # Chirpstack Device Profile to use. Includes the Payload Parser.
        devProfile: lobaro-environment
        devName: "name of device in chirpstack"
        # Register mapping for this device
        # One device can fill any number of registers.
        # The server will check for overlapping definitions on start.
        register:
            # Modbus Address (do NOT prefix with 0, else it's octal)
          - addr: 1
            # The value to be mapped.
            # Usually the value is taken from the Chirpstack Parser result JSON
            # and can be selected via JSON Path as handled by https://github.com/tidwall/gjson
            # There are some special values:
            # @ageModbus -Address age(do ofNOT lastprefix updatewith in0, minutes (for any register of this device)
        else it's octal)
          - addr: 1
        # @now - Current time# asThe Unixvalue Timestamp
    to be mapped.
          value: "@age" # ageUsually ofthe lastvalue updateis intaken minutesfrom (forthe anyChirpstack registerParser of this device)result JSON
            # and Datacan typebe ofselected thevia value.JSON DefaultPath byteas orderhandled is LittleEndianby https://github.com/tidwall/gjson
            # SupportedThere types are: int16, uint16 (more will come in future versions)
            type: int16some special values:
            # @age - age of last update in minutes (for any register of this device)
            # The@now value- isCurrent onlytime foras messagesUnix onTimestamp
     the specified port, 0 for "every". Default: 0
            port: 0
         value: "@age" # age of last update in minutes (for any register of this device)
         # The register value# isData multipliedtype withof the value. givenDefault factor,byte 0order is irgnored.LittleEndian
     Default: 1
          # Supported factor: 1
    
    types are: int16, uint16 (more will come in future versions)
           - addrtype: 2int16
            port:# 1The #value statusis packet
    only for messages on the specified port, 0 value:for "every"object.vBat". Default: 0
            type: int16port: 0
            # The register value is multiplied with the given factor, 0 is irgnored. Default: 1
            factor: 10001
    
          - addr: 32
            port: 2 1 # status packet
            value: "object.temperaturevBat"
            type: int16
            factor: 101000
          - addr: 43
            port: 2
            value: "object.humiditytemperature"
            type: int16
            factor: 10
          - addr: 54
            port: 2
            value: "object.pressurehumidity"
            type: int16
            factor: 10
          - addr: 65
            port: 2
            value: "rxInfoobject.0.rssipressure"
            type: int16
            factor: 10
          - addr: 76
            port: 2
            value: "txInforxInfo.0.drrssi"
            type: int16
    
       # A second device- asaddr: example7
      - devEUI: 0000000000000000
        appKeyport: 000000000000000000000000000000002
          devProfile  value: lobaro-one-wire
    "txInfo.dr"
         register:
       type: int16
    	  - addr: 1008
            		port: 128
    		value: "@age0x0102" # agevalue ofto lastbe updatesent inas minutesdownlink, (foreither anyas registerhex of(prefixed thiswith device"0x")
     or base64 string
    		type: downlink
    
      # A type:second int16
    device as   example
      - addrdevEUI: 1010000000000000000
        appKey: 00000000000000000000000000000000
        port: 1 # status packetdevProfile: lobaro-one-wire
        register:
          -  valueaddr: "object.vBat"100
            type: int16value: "@age" # age of last update in minutes (for any register of this device)
            factortype: 1000int16
          - addr: 102101
            port: 2 1 # status packet
            value: "object.sensors.0.tempvBat"
            type: int16
            factor: 101000
          - addr: 103102
            port: 2
            value: "rxInfoobject.sensors.0.rssitemp"
            type: int16
            factor: 10
          - addr: 104103
            port: 2
            value: "txInforxInfo.0.drrssi"
            type: int16

    Chirpstack

    The gateway uses a local Chirpstack server. Access management interface on https://<gw-ip>:8080.

    Documentation can be found on Chripstack.io.

    For each type of device the lobaro-modbus-server needs to reference a Device Profile. See: Chirpstack Device Profile Management. The Device Profile of each LoRaWAN device must be referenced by its name or UUID in the lobaro-modbus-server.yml config file.

    Gateway administration

    When ever any file on the SD-Card need to change make sure to execute 

    No Format
    ~/enableWriteAccess.sh

    Change password

    Login via SSH (see: 4195483)

    No Format
    passwd

    Change IP address

    No Format
    sudo vim /etc/network/interfaces
    No Format
    pi@LoRaGateway:~ $ cat /etc/network/interfaces
    # interfaces(5) file used by ifup(8) and ifdown(8)
    
    # Please note that this file is written to be used with dhcpcd
    # For static IP, consult /etc/dhcpcd.conf and 'man dhcpcd.conf'
    
    # Include files from /etc/network/interfaces.d:
    source-directory /etc/network/interfaces.d
    
    auto lo
    iface lo inet loopback
    
    # DHCP (Default, comment line to disable DHCP)
    iface eth0 inet manual
    
    # Fixed IP (Uncomment to enable or use /etc/dhcpcd.conf)
    #auto eth0
    #iface eth0 inet static
    #    address 10.0.0.42/24
    #    gateway 10.0.0.1

    Changelog (lobaro-modbus-server)

    
          - addr: 104
            port: 2
            value: "txInfo.dr"
            type: int16
          - addr: 105
    		port: 128
    		value: "dGVzdF9kb3dubGluaw==" # value to be sent as downlink, either as hex (prefixed with "0x") or base64 string
    		type: downlink
    	  - addr: 106
            type: downlink-var
            len: 5 # 107-111

    Send a predefined downlink packet to a configures port to a LoRaWAN device with a single write to a modbus register.

    Code Block
    languageyml
    titleConfiguration
    mapping:
        register:
          - addr: 8
            port: 128
            value: "0x0102" # value to be sent as downlink, either as hex (prefixed with "0x") or base64 string
            type: downlink

    Set the register to type "downlink" to allow sending the "value" via LoRaWAN to the deivce.

    With the example above:

    • Write any value to modbus register with address 8
    • A downlink "0x0102" will be queued on port 128
    • The register will keep the written value in case of success. In case of error the value will be 0.

    Send variable downlinks to a variable ports. Payload must be written to a set of defined modbus registers per LoRaWAN Device.

    First, specify a new register under the device of your choice with type downlink-var. Then, set the following options for it:

    • Len: How many modbus registers (following this register) should be assigned as storage for the variable downlink.
    • Confirm: Whether to ask the device for acknowledgement of reception of the sent downlink (false or true)


    Code Block
    languageyml
    titleConfiguration
    mapping:
    	register:
    	  - addr: 123
            type: downlink-var
            len: 7 # storing in registers 124-130
            confirm: true


    The resulting structure at the configured address addr will be:

    Downlink TriggerDownlink data...Downlink data
    addraddr+1...addr+len

    After (re-)starting the modbus server to apply the new config:

    1. Write your desired downlink (bytes) to the downlink data registers, starting at addr+1.
      1. You can only write 2 * len bytes at maximum! Extra bytes will be discarded.
    2. Optional: Write 0x0000 to the downlink trigger register at addr to clear the register (no downlink will be queued!)
    3. Write <port><length> to the downlink trigger register at addr, using 1 byte each for the designated FPort and downlink length in bytes.
      1. Example: Send downlink to port 128 (0x80), 10 (0x0A) bytes long: Write value 0x800A to register addr.


    To check if the downlink was successful, read the trigger register and check its value:

    • Register value = <port><length>: The downlink was successfully queued. 
    • Register value = 0: The downlink couldn't be queued for your device. Check the server log for more details.


    Chirpstack

    The gateway uses a local Chirpstack server. Access management interface on https://<gw-ip>:8080.

    Documentation can be found on Chripstack.io.

    For each type of device the lobaro-modbus-server needs to reference a Device Profile. See: Chirpstack Device Profile Management. The Device Profile of each LoRaWAN device must be referenced by its name or UUID in the lobaro-modbus-server.yml config file.

    Gateway administration

    When ever any file on the SD-Card need to change make sure to execute 

    No Format
    ~/enableWriteAccess.sh

    Change password

    Login via SSH (see: Remote access)

    No Format
    passwd

    Change IP address

    IMST

    No Format
    sudo vim /etc/network/interfaces

    No Format
    pi@LoRaGateway:~ $ cat /etc/network/interfaces
    # interfaces(5) file used by ifup(8) and ifdown(8)
    
    # Please note that this file is written to be used with dhcpcd
    # For static IP, consult /etc/dhcpcd.conf and 'man dhcpcd.conf'
    
    # Include files from /etc/network/interfaces.d:
    source-directory /etc/network/interfaces.d
    
    auto lo
    iface lo inet loopback
    
    # DHCP (Default, comment line to disable DHCP)
    iface eth0 inet manual
    
    # Fixed IP (Uncomment to enable or use /etc/dhcpcd.conf)
    #auto eth0
    #iface eth0 inet static
    #    address 10.0.0.42/24
    #    gateway 10.0.0.1


    RAK

    Code Block
    sudo vim /etc/dhcpcd.conf


    Edit last lines to:

    Code Block
    # RAK_eth0_IP
    profile static_eth0
    static ip_address=192.168.0.1/24
    static routers=192.168.0.1
    
    interface eth0
    fallback static_eth0
    Markdown
    ## 1.2.1
    
    ### Added
    - devName config parameter to specify an optional device name
    
    ### Fixed
    - modbus "disabled" config parameter was always true
    
    ## 1.2.0
    
    ### Added
    - Allow to configure modbus serial connection parameters
      - modbus.dataBits: 8
      - modbus.parity: "even" # no, even (default), odd
      - modbus.stopBits: 1 # 1 (default), 1.5, 2
    
    ## 1.1.1
    
    ### Added
    - Support int32, uint32, float32 register types
    
    ### Fixed
    - Bug where register data is not saved
    
    ## 1.0.7
    
    ### Fixed
    
    - Allow async access on modbus registers. Might solve invalid value read-out. 
    - Persist data only once per minute
    - Persist data on exit
    
    ## 1.0.6
    
    ### Fixed
    
    - Reconnect to MQTT on disconnect
    - possible endless loop on MQTT receive
    
    ## 1.0.3
    
    ### Fixed
    - modbus register readout (was always 0)



    Table of Contents