Device profile region configuration issue

Hello Everyone,

I am having an issue connecting a new device where the only way it will connect is if I specify the incorrect bands in region configuration of the device profile.

I have been using Chirpstack for a few months and have multiple different devices connected to a couple gateways all working as expected. The issue occurred when I tried to add a new device (Digital Matter Yabby3), I configured the Yabby3 to use US915 (ch. 0-7, 64) and in Chirpstack set the device profile to be the same. When the device tried to connect I would get an error in the Chirpstack logs:

ERROR up{deduplication_id=e9352c79-4c9f-4220-8ef6-445cb90de6c4}: chirpstack::uplink::data: Handle uplink error error=rx_info_set is empty

Which from this forum post, I believe to be a mismatch in the band configuration.

After much trial and error, the only way I could get the Yabby3 connected was to configure the device to US915 (ch. 0-7, 64) but in Chirpstack set the device profile’s region configuration to US915 (ch. 8-15 + 65). Using this band mismatch the device works exactly as expected.

Now that the device has been running for a few days I can see under “Recieved / frequency” that the device is indeed using US915_0, despite the device profile being set for US915_1. Which makes me think the issue is on the Chirpstack side and not the device side, as the device is broadcasting on the sub-band I set it to.

I have been trying to find the reason for this but am out of my depth, any help would be much appreciated.

Notes:

I am using Chirpstack docker on a Ubuntu machine

The only modifications I have made to the US915_0 and US915_1 .toml files is emptying enabled_uplink_channels=[] as discussed in this forum post. Those are the only two regions I have enabled in the main chirpstack.toml file.

Unlike the Yabby3, none of the other devices I am using require configuring the specific bands within 915 to broadcast on, so it’s possible there is a larger issue with my region configuration I have been oblivious to so far.

There is a mismatch where the Yabby3 configuration software says (ch. 0-7, 64) is sub-band 1, whereas in Chirpstack (ch. 0-7, 64) is sub-band 0, but I assume this is simply a mismatch in naming convention and not in the actual bands used.

Images:

Yabby3 Device Profile:

Yabby3 Provisioning Tool (these are the settings I configure onto the device itself):

Yabby3 Recieved / frequency:

Screenshot 2024-01-18 at 11.25.04 AM

Files:

chirpstack.toml

# Logging.
[logging]

  # Log level.
  #
  # Options are: trace, debug, info, warn error.
  level="info"


# PostgreSQL configuration.
[postgresql]

  # PostgreSQL DSN.
  #
  # Format example: postgres://<USERNAME>:<PASSWORD>@<HOSTNAME>/<DATABASE>?sslmode=<SSLMODE>.
  #
  # SSL mode options:
  #  * disable - no SSL
  #  * require - Always SSL (skip verification)
  #  * verify-ca - Always SSL (verify that the certificate presented by the server was signed by a trusted CA)
  #  * verify-full - Always SSL (verify that the certification presented by the server was signed by a trusted CA and the serv>
  dsn="postgres://chirpstack:*mypassword*@$POSTGRESQL_HOST/chirpstack?sslmode=disable"

  # Max open connections.
  #
  # This sets the max. number of open connections that are allowed in the
  # PostgreSQL connection pool.
  max_open_connections=10

  # Min idle connections.
  #
  # This sets the min. number of idle connections in the PostgreSQL connection
  # pool (0 = equal to max_open_connections).
  min_idle_connections=0


# Redis configuration.
[redis]

  # Server address or addresses.
  #
  # Set multiple addresses when connecting to a cluster.
  servers=[
    "redis://$REDIS_HOST/",
  ]

  # TLS enabled.
  tls_enabled=false

  # Redis Cluster.
  #
  # Set this to true when the provided URLs are pointing to a Redis Cluster
  # instance.
  cluster=false


# Network related configuration.
[network]

  # Network identifier (NetID, 3 bytes) encoded as HEX (e.g. 010203).
  net_id="000000"

  # Enabled regions.
  #
  # Multiple regions can be enabled simultaneously. Each region must match
  # the 'name' parameter of the region configuration in '[[regions]]'.
  enabled_regions=[
    "us915_0",
    "us915_1"
  ]

# API interface configuration.
[api]

  # interface:port to bind the API interface to.
  bind="0.0.0.0:8081"

  # Secret.
  #
  # This secret is used for generating login and API tokens, make sure this
  # is never exposed. Changing this secret will invalidate all login and API
  # tokens. The following command can be used to generate a random secret:
  #   openssl rand -base64 32
  secret="*mysecret*"


[integration]
  enabled=["mqtt"]

  [integration.mqtt]
    server="tcp://$MQTT_BROKER_HOST:1883/"
    json=true

    [integration.mqtt.client]
      client_cert_lifetime="12months"
      ca_cert="/etc/chirpstack/certs/ca.pem"
      ca_key="/etc/chirpstack/certs/ca-key.pem"

[gateway]
  client_cert_lifetime="12months"
  ca_cert="/etc/chirpstack/certs/ca.pem"
  ca_key="/etc/chirpstack/certs/ca-key.pem"

region_us915_0.toml

# This file contains an example US915 example (channels 0-7 + 64).
[[regions]]

  # ID is an use-defined identifier for this region.
  id="us915_0"

  # Description is a short description for this region.
  description="US915 (channels 0-7 + 64)"

  # Common-name refers to the common-name of this region as defined by
  # the LoRa Alliance.
  common_name="US915"


  # Gateway configuration.
  [regions.gateway]

    # Force gateways as private.
    #
    # If enabled, gateways can only be used by devices under the same tenant.
    force_gws_private=false


    # Gateway backend configuration.
    [regions.gateway.backend]

      # The enabled backend type.
      enabled="mqtt"

      # MQTT configuration.
      [regions.gateway.backend.mqtt]

        # Topic prefix.
        #
        # The topic prefix can be used to define the region of the gateway.
        # Note, there is no need to add a trailing '/' to the prefix. The trailing
        # '/' is automatically added to the prefix if it is configured.
        topic_prefix="us915_0"

        # MQTT server (e.g. scheme://host:port where scheme is tcp, ssl or ws)
        server="tcp://$MQTT_BROKER_HOST:1883"

        # Connect with the given username (optional)
        username=""

        # Connect with the given password (optional)
        password=""

        # Quality of service level
        #
        # 0: at most once
        # 1: at least once
        # 2: exactly once
        #
        # Note: an increase of this value will decrease the performance.
        # For more information: https://www.hivemq.com/blog/mqtt-essentials-part-6-mqtt-quality-of-service-levels
        qos=0

        # Clean session
        #
        # Set the "clean session" flag in the connect message when this client
        # connects to an MQTT broker. By setting this flag you are indicating
        # that no messages saved by the broker for this client should be delivered.
        clean_session=false

        # Client ID
        #
        # Set the client id to be used by this client when connecting to the MQTT
        # broker. A client id must be no longer than 23 characters. If left blank,
        # a random id will be generated by ChirpStack.
        client_id=""

        # Keep alive interval.
        #
        # This defines the maximum time that that should pass without communication
        # between the client and server.
        keep_alive_interval="30s"

        # CA certificate file (optional)
        #
        # Use this when setting up a secure connection (when server uses ssl://...)
        # but the certificate used by the server is not trusted by any CA certificate
        # on the server (e.g. when self generated).
        ca_cert=""

        # TLS certificate file (optional)
        tls_cert=""

        # TLS key file (optional)
        tls_key=""


    # Gateway channel configuration.
    #
    # Note: this configuration is only used in case the gateway is using the
    # ChirpStack Concentratord daemon. In any other case, this configuration 
    # is ignored.
    [[regions.gateway.channels]]
      frequency=902300000
      bandwidth=125000
      modulation="LORA"
      spreading_factors=[7, 8, 9, 10]

    [[regions.gateway.channels]]
      frequency=902500000
      bandwidth=125000
      modulation="LORA"
      spreading_factors=[7, 8, 9, 10]

    [[regions.gateway.channels]]
      frequency=902700000
      bandwidth=125000
      modulation="LORA"
      spreading_factors=[7, 8, 9, 10]

    [[regions.gateway.channels]]
      frequency=902900000
      bandwidth=125000
      modulation="LORA"
      spreading_factors=[7, 8, 9, 10]

    [[regions.gateway.channels]]
      frequency=903100000
      bandwidth=125000
      modulation="LORA"
      spreading_factors=[7, 8, 9, 10]

    [[regions.gateway.channels]]
      frequency=903300000
      bandwidth=125000
      modulation="LORA"
      spreading_factors=[7, 8, 9, 10]

    [[regions.gateway.channels]]
      frequency=903500000
      bandwidth=125000
      modulation="LORA"
      spreading_factors=[7, 8, 9, 10]

    [[regions.gateway.channels]]
      frequency=903700000
      bandwidth=125000
      modulation="LORA"
      spreading_factors=[7, 8, 9, 10]

    [[regions.gateway.channels]]
      frequency=903000000
      bandwidth=500000
      modulation="LORA"
      spreading_factors=[8]


  # Region specific network configuration.
  [regions.network]

    # Installation margin (dB) used by the ADR engine.
    #
    # A higher number means that the network-server will keep more margin,
    # resulting in a lower data-rate but decreasing the chance that the
    # device gets disconnected because it is unable to reach one of the
    # surrounded gateways.
    installation_margin=10

    # RX window (Class-A).
    #
    # Set this to:
    # 0: RX1 / RX2
    # 1: RX1 only
    # 2: RX2 only
    rx_window=0

    # RX1 delay (1 - 15 seconds).
    rx1_delay=1

    # RX1 data-rate offset
    rx1_dr_offset=0

    # RX2 data-rate
    rx2_dr=8

    # RX2 frequency (Hz)
    rx2_frequency=923300000

    # Prefer RX2 on RX1 data-rate less than.
    #
    # Prefer RX2 over RX1 based on the RX1 data-rate. When the RX1 data-rate
    # is smaller than the configured value, then the Network Server will
    # first try to schedule the downlink for RX2, failing that (e.g. the gateway
    # has already a payload scheduled at the RX2 timing) it will try RX1.
    rx2_prefer_on_rx1_dr_lt=0

    # Prefer RX2 on link budget.
    #
    # When the link-budget is better for RX2 than for RX1, the Network Server will first
    # try to schedule the downlink in RX2, failing that it will try RX1.
    rx2_prefer_on_link_budget=false

    # Downlink TX Power (dBm)
    #
    # When set to -1, the downlink TX Power from the configured band will
    # be used.
    #
    # Please consult the LoRaWAN Regional Parameters and local regulations
    # for valid and legal options. Note that the configured TX Power must be
    # supported by your gateway(s).
    downlink_tx_power=-1

    # ADR is disabled.
    adr_disabled=false

    # Minimum data-rate.
    min_dr=0

    # Maximum data-rate.
    max_dr=3

    # Enabled uplink channels.
    #
    # Use this when ony a sub-set of the by default enabled channels are being
    # used. For example when only using the first 8 channels of the US band.
    # Note: when left blank / empty array, all channels will be enabled.
    enabled_uplink_channels=[]
    #enabled_uplink_channels=[]

    # Rejoin-request configuration (LoRaWAN 1.1)
    [regions.network.rejoin_request]

      # Request devices to periodically send rejoin-requests.
      enabled=false

      # The device must send a rejoin-request type 0 at least every 2^(max_count_n + 4)
      # uplink messages. Valid values are 0 to 15.
      max_count_n=0

      # The device must send a rejoin-request type 0 at least every 2^(max_time_n + 10)
      # seconds. Valid values are 0 to 15.
      #
      # 0  = roughly 17 minutes
      # 15 = about 1 year
      max_time_n=0


    # Class-B configuration.
    [regions.network.class_b]

      # Ping-slot data-rate. 
      ping_slot_dr=8

      # Ping-slot frequency (Hz)
      #
      # set this to 0 to use the default frequency plan for the configured region
      # (which could be frequency hopping).
      ping_slot_frequency=0

region_us915_1.toml

# This file contains an example US915 example (channels 8-15 + 65).
[[regions]]

  # ID is an use-defined identifier for this region.
  id="us915_1"

  # Description is a short description for this region.
  description="US915 (channels 8-15 + 65)"

  # Common-name refers to the common-name of this region as defined by
  # the LoRa Alliance.
  common_name="US915"


  # Gateway configuration.
  [regions.gateway]

    # Force gateways as private.
    #
    # If enabled, gateways can only be used by devices under the same tenant.
    force_gws_private=false


    # Gateway backend configuration.
    [regions.gateway.backend]

      # The enabled backend type.
      enabled="mqtt"

      # MQTT configuration.
      [regions.gateway.backend.mqtt]

        # Topic prefix.
        #
        # The topic prefix can be used to define the region of the gateway.
        # Note, there is no need to add a trailing '/' to the prefix. The trailing
        # '/' is automatically added to the prefix if it is configured.
        topic_prefix="us915_1"

        # MQTT server (e.g. scheme://host:port where scheme is tcp, ssl or ws)
        server="tcp://$MQTT_BROKER_HOST:1883"

        # Connect with the given username (optional)
        username=""

        # Connect with the given password (optional)
        password=""

        # Quality of service level
        #
        # 0: at most once
        # 1: at least once
        # 2: exactly once
        #
        # Note: an increase of this value will decrease the performance.
        # For more information: https://www.hivemq.com/blog/mqtt-essentials-part-6-mqtt-quality-of-service-levels
        qos=0

        # Clean session
        #
        # Set the "clean session" flag in the connect message when this client
        # connects to an MQTT broker. By setting this flag you are indicating
        # that no messages saved by the broker for this client should be delivered.
        clean_session=false

        # Client ID
        #
        # Set the client id to be used by this client when connecting to the MQTT
        # broker. A client id must be no longer than 23 characters. If left blank,
        # a random id will be generated by ChirpStack.
        client_id=""

        # Keep alive interval.
        #
        # This defines the maximum time that that should pass without communication
        # between the client and server.
        keep_alive_interval="30s"

        # CA certificate file (optional)
        #
        # Use this when setting up a secure connection (when server uses ssl://...)
        # but the certificate used by the server is not trusted by any CA certificate
        # on the server (e.g. when self generated).
        ca_cert=""

        # TLS certificate file (optional)
        tls_cert=""

        # TLS key file (optional)
        tls_key=""


    # Gateway channel configuration.
    #
    # Note: this configuration is only used in case the gateway is using the
    # ChirpStack Concentratord daemon. In any other case, this configuration 
    # is ignored.
    [[regions.gateway.channels]]
      frequency=903900000
      bandwidth=125000
      modulation="LORA"
      spreading_factors=[7, 8, 9, 10]

    [[regions.gateway.channels]]
      frequency=904100000
      bandwidth=125000
      modulation="LORA"
      spreading_factors=[7, 8, 9, 10]

    [[regions.gateway.channels]]
      frequency=904300000
      bandwidth=125000
      modulation="LORA"
      spreading_factors=[7, 8, 9, 10]

    [[regions.gateway.channels]]
      frequency=904500000
      bandwidth=125000
      modulation="LORA"
      spreading_factors=[7, 8, 9, 10]

    [[regions.gateway.channels]]
      frequency=904700000
      bandwidth=125000
      modulation="LORA"
      spreading_factors=[7, 8, 9, 10]

    [[regions.gateway.channels]]
      frequency=904900000
      bandwidth=125000
      modulation="LORA"
      spreading_factors=[7, 8, 9, 10]

    [[regions.gateway.channels]]
      frequency=905100000
      bandwidth=125000
      modulation="LORA"
      spreading_factors=[7, 8, 9, 10]

    [[regions.gateway.channels]]
      frequency=905300000
      bandwidth=125000
      modulation="LORA"
      spreading_factors=[7, 8, 9, 10]

    [[regions.gateway.channels]]
      frequency=904600000
      bandwidth=500000
      modulation="LORA"
      spreading_factors=[8]


  # Region specific network configuration.
  [regions.network]

    # Installation margin (dB) used by the ADR engine.
    #
    # A higher number means that the network-server will keep more margin,
    # resulting in a lower data-rate but decreasing the chance that the
    # device gets disconnected because it is unable to reach one of the
    # surrounded gateways.
    installation_margin=10

    # RX window (Class-A).
    #
    # Set this to:
    # 0: RX1 / RX2
    # 1: RX1 only
    # 2: RX2 only
    rx_window=0

    # RX1 delay (1 - 15 seconds).
    rx1_delay=1

    # RX1 data-rate offset
    rx1_dr_offset=0

    # RX2 data-rate
    rx2_dr=8

    # RX2 frequency (Hz)
    rx2_frequency=923300000

    # Prefer RX2 on RX1 data-rate less than.
    #
    # Prefer RX2 over RX1 based on the RX1 data-rate. When the RX1 data-rate
    # is smaller than the configured value, then the Network Server will
    # first try to schedule the downlink for RX2, failing that (e.g. the gateway
    # has already a payload scheduled at the RX2 timing) it will try RX1.
    rx2_prefer_on_rx1_dr_lt=0

    # Prefer RX2 on link budget.
    #
    # When the link-budget is better for RX2 than for RX1, the Network Server will first
    # try to schedule the downlink in RX2, failing that it will try RX1.
    rx2_prefer_on_link_budget=false

    # Downlink TX Power (dBm)
    #
    # When set to -1, the downlink TX Power from the configured band will
    # be used.
    #
    # Please consult the LoRaWAN Regional Parameters and local regulations
    # for valid and legal options. Note that the configured TX Power must be
    # supported by your gateway(s).
    downlink_tx_power=-1

    # ADR is disabled.
    adr_disabled=false

    # Minimum data-rate.
    min_dr=0

    # Maximum data-rate.
    max_dr=3

    # Enabled uplink channels.
    #
    # Use this when ony a sub-set of the by default enabled channels are being
    # used. For example when only using the first 8 channels of the US band.
    # Note: when left blank / empty array, all channels will be enabled.
    #enabled_uplink_channels=[8, 9, 10, 11, 12, 13, 14, 15, 65]
    enabled_uplink_channels=[]

    # Rejoin-request configuration (LoRaWAN 1.1)
    [regions.network.rejoin_request]

      # Request devices to periodically send rejoin-requests.
      enabled=false

      # The device must send a rejoin-request type 0 at least every 2^(max_count_n + 4)
      # uplink messages. Valid values are 0 to 15.
      max_count_n=0

      # The device must send a rejoin-request type 0 at least every 2^(max_time_n + 10)
      # seconds. Valid values are 0 to 15.
      #
      # 0  = roughly 17 minutes
      # 15 = about 1 year
      max_time_n=0


    # Class-B configuration.
    [regions.network.class_b]

      # Ping-slot data-rate. 
      ping_slot_dr=8

      # Ping-slot frequency (Hz)
      #
      # set this to 0 to use the default frequency plan for the configured region
      # (which could be frequency hopping).
      ping_slot_frequency=0

Are your gateways forwarding to the correct MQTT topic-prefix? A common mistake is that for example gateways configured for channels 0 - 7 and channels 8 - 15 both forward to the same topic prefix.

1 Like

Thanks for the reply @brocaar, I have two Multitech gateways with the GW bridge installed on them and both are configured for us915_1 as the MQTT topic-prefix.

After looking deeper now, I realize the frequency sub-band in the mPower UI is also set to 1, but that list is from 1-8 compared to Chirpstack’s 0-7, so the gateway is listening on us915_0 in Chirpstack terms but is sending us915_1 MQTT topic-prefixes. I’m away at the moment so I don’t have the Yabby3 with me but I’m fairly certain this was the issue, I’ll report back when I have tested it. Thank you for pointing me in the right direction.

What is the reason behind Chirpstack using the 0-7 sub-band list as opposed to the typical 1-8?

I’m used to 0-based indexing, I guess that is where it comes from.

2 Likes

Fair enough, and to confirm my Yabby3 is now working as expected. A few other oddities I was running into got fixed as well.

Thanks again @brocaar, Chirpstack is an awesome project!

1 Like