Downlink scheduled but never delivered -- Feature request?

I have a class C device that issued a join request and was sent an accept, but never sends data. This is probably an application level issue on the device, and the device was previously sending data as expected.

However, in trying to schedule a downlink message, I get the following in the log:

2025-01-16T16:09:05.684385Z  INFO schedule{dev_eui=xxxxx1117184e83f downlink_id=11212030}: chirpstack::storage::device: Device partially updated dev_eui=xxxxx1117184e83f

This repeats every 5 seconds and the message is never delivered.

A successful downlink looks like this:

2025-01-16T16:15:24.443992Z  INFO schedule{dev_eui=xxxxx1f58184e845 downlink_id=894962255}: chirpstack::storage::device: Device partially updated dev_eui=xxxxx1f58184e845
2025-01-16T16:15:24.452717Z  INFO schedule{dev_eui=xxxxx1f58184e845 downlink_id=894962255}: chirpstack::storage::device_queue: Device queue-item updated id=7ee52afb-7cb0-42c6-9c15-f1425a7246c1 dev_eui=xxxxx1f58184e845
2025-01-16T16:15:24.453250Z  INFO schedule{dev_eui=xxxxx1f58184e845 downlink_id=894962255}: chirpstack::storage::downlink_frame: Downlink-frame saved downlink_id=894962255
2025-01-16T16:15:24.453326Z  INFO schedule{dev_eui=xxxxx1f58184e845 downlink_id=894962255}: chirpstack::gateway::backend::mqtt: Sending downlink frame region_id=us915_1 gateway_id=xxxxx9fffe0e0695 topic=us915_1/gateway/xxxxx9fffe0e0695/command/down json=false
2025-01-16T16:15:24.502436Z  INFO chirpstack::gateway::backend::mqtt: Message received from gateway region_id="us915_1" topic=us915_1/gateway/xxxxx9fffe0e0695/event/ack qos=AtMostOnce json=false
2025-01-16T16:15:24.512767Z  INFO tx_ack{downlink_id=894962255}: chirpstack::storage::device_queue: Device queue-item deleted id=7ee52afb-7cb0-42c6-9c15-f1425a7246c1
2025-01-16T16:15:24.516047Z  INFO chirpstack::integration::mqtt: Publishing event topic=application/09802e61-c194-45f9-9310-09ad419a9574/device/xxxxx1f58184e845/event/txack
2025-01-16T16:15:24.518295Z  INFO tx_ack{downlink_id=894962255}: chirpstack::storage::device: Device partially updated dev_eui=xxxxx1f58184e845
2025-01-16T16:15:24.518340Z  INFO tx_ack{downlink_id=894962255}: chirpstack::downlink::tx_ack: Log downlink-frame for gateway gateway_id=xxxxx9fffe0e0695
2025-01-16T16:15:24.519446Z  INFO tx_ack{downlink_id=894962255}: chirpstack::downlink::tx_ack: Log downlink-frame for device device_eui=xxxxx1f58184e845

It was only after I turned on trace level logging (although debug would have been enough) that I discovered the first message is not being sent due to

Device must send its first uplink first

2025-01-16T16:28:24.888057Z TRACE chirpstack::downlink::scheduler: Starting class_b_c_scheduler_loop run
2025-01-16T16:28:24.888077Z TRACE chirpstack::downlink::scheduler: Getting devices that have schedulable queue-items
2025-01-16T16:28:24.894999Z TRACE chirpstack::downlink::scheduler: Got this number of devices with schedulable queue-items device_count=1
2025-01-16T16:28:24.895073Z TRACE schedule{dev_eui=xxxxx1117184e83f downlink_id=2494981993}: chirpstack::downlink::data: Handle schedule next-queue item flow
2025-01-16T16:28:24.898085Z TRACE schedule{dev_eui=xxxxx1117184e83f downlink_id=2494981993}: chirpstack::downlink::data: Selecting downlink gateway
2025-01-16T16:28:24.898124Z TRACE schedule{dev_eui=xxxxx1117184e83f downlink_id=2494981993}: chirpstack::downlink::data: Updating scheduler_run_after_ts for Class-C
2025-01-16T16:28:24.903022Z  INFO schedule{dev_eui=xxxxx1117184e83f downlink_id=2494981993}: chirpstack::storage::device: Device partially updated dev_eui=xxxxx1117184e83f
2025-01-16T16:28:24.903064Z TRACE schedule{dev_eui=xxxxx1117184e83f downlink_id=2494981993}: chirpstack::downlink::data: Checking if device has sent its first uplink already
2025-01-16T16:28:24.903073Z DEBUG schedule{dev_eui=xxxxx1117184e83f downlink_id=2494981993}: chirpstack::downlink::data: Device must send its first uplink first
2025-01-16T16:28:24.903194Z TRACE chirpstack::downlink::scheduler: class_b_c_scheduler_loop completed successfully

@brocaar Could this type of message bubble up to the UI? Is this something that warrants an official feature request? Possibly it it common knowledge that a device must send an uplink message after joining before a downlink message can be sent. I have never seen this requirement for a class C device downlink message, and I can think of reasons this requirement might exist.

The undelivered message remains in the queue forever, trying to send every 5 seconds. This seems correct if the device is expected to send an uplink message eventually, as in the case of a very infrequent uplink from a class A device. Is there an eventual timeout when ChirpStack determines this message might never be delivered, especially in the case of a class C device?

This happens because of the downlink gateway selection logic. When a downlink is queued, it is sent to the gateway that has the best RSSI from uplinks from the device. This is so then if there are multiple gateways in the area of the device, it selects the one that has the best signal strength to maximize the chance the device receives the downlink.

I guess join-requests do not count towards the RSSI for this logic (likely because data-rates, subbands, etc have not been negotiated yet), and hence Chirpstack requires a single uplink from the device before it can decide what gateway to send any downlinks through.

As for setting a TTL for downlinks, you can set the queue-item expiration in newer chirpstack versions:

Thanks for the response and the explanation. I actually said I can think of reasons for this requirement to exist. I don’t know why this quote is incorrect.

I did not know about the queue item expiration in 4.10.1, as I am running an older version of ChirpStack. Upgrading is on my short list.

Lol sorry, thought that was a typo and took the liberty of editing it

It’s rather funny that it’s an option.

Ha!

Requires a bit of discipline at times. :wink:

1 Like