ABP: Disable mac sending of commands


After migrating from TTNv2 to v3 my devices constantly receive the following downlink:

This is supposed to be a command indicating the frequencies the device can use.
This command is replacing the downlinks that i have scheduled myself. I want to stop this behaviour

I found the following topic and tried every solution i could find there:

  • I entered the factory settings of my device in the console, but this does not stop the command from being sent
  • I set the ‘mac-settings.status-count-periodicity’ to 0 and ‘mac-settings.status-time-periodicity’ to 0s
  • I tried to change the desired parameters of my device to match the current parameters using the ttn-lw-cli, but while the command succeeds the desired parameters are never changed.

Is there any other method of stopping this command from being sent? or at the very least give my own scheduled downlink priority over this command?

Kind Regards,


Have you read the official guide from the developer?

Yes i have. My devcie is configured exactly like described in the guide and my gateway is connected to ttnv3

Off the top of my head, I haven’t set the Rx2 settings as they are in my nodes firmware already, that’s the only immediate difference I can see.

What is the device & firmware & revision you are using.

Have you tried decrypting/decoding the MAC command to confirm if it’s a channel setup?

Please double check the RX2 settings.
I’ve had the same issue and here it was related to the RX2 frequency which is wrong in almost all preset vendor definitions as it is wrong in the example which anyone copied.

In your screenshot the frequency at least seems OK, but perhaps one of the other settings there isn’t right?

N.B. for the RX2 frequency issue, I opened an issue on GitHub for it as I really don’t know how it should be fixed as either fix is a bad one.

1 Like

I just noticed you have the RX1 delay set to 1 second.
Since v3 this should be 5 seconds.
You may also have a look at the used delay on your node.

Not necessarily - the standard built-in delay for TTS is 5 seconds. But if your node is running ABP pre-TTS it will have Rx1 set to 1 second and there is no way for the server to update that figure, so it is set on the server to match the device.

OTAA updates it as part of the join-accept so old or new firmware, that’s sorted.

Without decyrypting the MAC command it’s a bit fuzzy, but it may be that the device isn’t acting on the MAC command so it keep being sent. Hopefully the OP will report back with what the device, firmware & version is.

I have tried to decode the package using the Lora Packet Decoder. https://github.com/anthonykirby/lora-packet
But it doesn’t make any sense. It says it’s a Join request with the completely wrong AppEUI and DevEUI.

decoding from Hex:  0503D2AD84060703184F84500704E85684500705B85E84500706886684500707586E84500350FF00030805
Decoded packet
          Message Type = Join Request
            PHYPayload = 0503D2AD84060703184F84500704E85684500705B85E84500706886684500707586E84500350FF00030805

          ( PHYPayload = MHDR[1] | MACPayload[..] | MIC[4] )
                  MHDR = 05
            MACPayload = 03D2AD84060703184F84500704E85684500705B85E84500706886684500707586E84500350FF
                   MIC = 00030805

          ( MACPayload = AppEUI[8] | DevEUI[8] | DevNonce[2] )
                AppEUI = 1803070684ADD203
                DevEUI = 8456E8040750844F
              DevNonce = 0750

I am using a HopeRF RFM95W module. With the 1.5.0 version of the LMIC library.
It seems that whatever the commmand is our software is not handling it. The problem is that this concerns devices that are already in use and cannot be modified. Therefore i’m really hoping there is some way to prevent this command from being sent without any changes to the end device.

I have checked the RX2 frequency and it looks to be alright. I have also tried to remove it from the settings, but this doesn’t make a difference.

A version that knows what a MAC is but can only really process ADR requests.

Try the MCCI LMIC 3.1.0 or above - that is declared as being actually compliant - I’ve been using 3.2.0 for non-critical devices with no issues and using 4.0.0 on the bench.

Leave the Rx2 settings alone for now, getting “a stack that can mac” is the priority here.

Try this for packet decoding, it makes using the Kirby code base simpler and has lots more explanations:


Thank you for your help, but that is not an option right now unfortunately. In the next iteration i’ll be sure to update my software to something that is completely compliant to prevent these kind of issues.
My current pilot devices can however not be updated with new software.

I’ve also tried the online packet decoder. This gives me the same response:

Assuming hex-encoded packet

Message Type = Join Request
  PHYPayload = 0503D2AD84060703184F84500704E85684500705B85E84500706886684500707586E84500350FF00030805

( PHYPayload = MHDR[1] | MACPayload[..] | MIC[4] )
        MHDR = 05
  MACPayload = 03D2AD84060703184F84500704E85684500705B85E84500706886684500707586E84500350FF
         MIC = 00030805 (from packet) INVALID (tried MSB 0000-FFFF)
             = 57AF86F3 (expected, assuming 32 bits frame counter with MSB 0000)

( MACPayload = AppEUI[8] | DevEUI[8] | DevNonce[2] )
      AppEUI = 1803070684ADD203
      DevEUI = 8456E8040750844F
    DevNonce = 0750

LMIC I can do, decoding MAC commands not so much. But just checking, is this an encrypted packet or have you got it from the web console?

The hex-encoded packet does not look to be a valid LoRaWAN frame.

We can say this by just looking at first byte on the hex-encoded packet.

The LoRaWAN specification describes the first byte as follows

This means that 0x05 corresponds to the MHDR field.
The MHDR field decodes to the following:

0x05 -> 0b0000_0101
FType[7:5]: 000
RFU  [4:2]: 001
Major[1:0]: 01

Has per LoRaWAN specification RFU fields must be set to 000 (001 in this case) and the Major field has always a value of 00 (01 in this case).

RFU field definition:

Major field definition:

Another indication telling us that this is not a valid packet is the length of it. A JoinReq has always a size of 23 bytes => MHDR(1)+JoinEUI(8)+DevEUI(8)+DevNonce(2)+MIC(4) = 23
The hex-encoded packet has a size of 45 bytes.

It has to be noted as well that the JoinReq packet is not encrypted. This packet is only authenticated by the MIC computed using the AppKey.

Therefore the possibilities to have this happening are:

  1. This packet has been transmitted by a LoRa (Not LoRaWAN) device. There is nothing that can be done. Just ignore this packet.
  2. The Gateway is setup to forward all received packets including the ones having a wrong CRC.
    The Gateways should be setup to only forward valid packets.
  3. The end-device stack is not correctly implemented. As you say that LMIC is the used stack I doubt this to be the case. The JoinReq packet definition is the same since LoRaWAN 1.0.0

The OP implies that this is from his gateway - if it was a LoRa packet surely it’s preamble, id code and inversion bit or what not (this area of LoRaWAN I’m still learning as you can tell) would be totally wrong. And very co-incidental that it be transmitted dead on the start of an Rx window.

He says it’s a downlink.

He says it is a downlink after a join.

Hopefully Mr @577e4e6de7caf50f0070 will answer my question regarding if it’s an encrypted packet or if it’s taken from the web console.

But given that he’s using a very old un-compliant version of LMIC, anything could be happening!

Even if this is a downlink the MHDR field is always transmitted not encrypted. Which means that this downlink is not a LoRaWAN packet.

In case this packet is a downlink I don’t think this issue to be related to the end-device.
I would more suspect a gateway setup issue.

It would be helpful if @577e4e6de7caf50f0070 could provide the gateway log as well as the Network Server log in order to identify what could be the cause for this issue.
With such gateway log we can see if this packet has been received from the Network Server or if it is something received on the RF interface.

I have doubts that the TTN network server would send to a gateway a non LoRaWAN packet.

My packet is a downlink i receive immediatly after sending an uplink. Not after a join.
I got the string directly from my arduino which prints the exact bytes it receives in the downlink.

I’ve been trying to decrypt the message using this go library lorawan package - github.com/brocaar/lorawan - pkg.go.dev, but i’m really not sure if its encrytped or not since i don’t exactly understand what it’s supposed to be.

When i change the gateway to use the V2 implementation or a private lora backend i do not have these problems. The only thing i change about the gateway is the forwarder address.

I will let you know if i have any succes getting more information out of the packet.

If I understand well the hex-decode packet is what your end-device receives (end-device log would be helpful).
Then this may mean that the problem is on the end-device side. Maybe a wrong handling of the end-device radio reception buffer.

As @descartes indicated maybe the only way to fix this would be to upgrade your firmware to use a more compliant stack implementation.

Would it be possible for you to check what the gateway really transmits (gateway log would be useful)?

Like this we can compare what has been transmitted and what has been received.

So, not encrypted then. Is there any chance you sent a confirmed downlink at some point? Because if it’s never ACKd, the v3 stack is very very persistent (as I found out).

So if the device is on v3 but you change the gateway back to v2, this problem goes away?

Ah, OK. Really must fill in the blanks on the bit between “send this” and the app server. :smile:

Maybe write a device stack of my own - I mean, how hard can it be! :wink:

As I don’t recall 1.5 printing any MAC commands as standard, unless this has been added by Mr577, it will take a bit of testing to figure out what it might actually mean.

As @mluis says, an actual gateway log would be good, even better run the gateway and device web consoles and capture the exchange in verbose mode (screen shot) and give us the full JSON of the downlink (text) and even better, both!

@577e4e6de7caf50f0070 Can you also post the end-device source code excerpt where you execute the print of the log?

I’m wondering if the hex-encoded packet that you provided is the full LoRaWAN packet or just the application payload contents.

The problem goes away when i switch to v2 yes.
Here is part of the log of my device where the message is received:

12:58:20.887 -> Pkt q(43): 860408800079EF9DE0
12:58:22.007 -> TXCMPLT
12:58:22.045 -> Dnlnk:0503D2AD84060703184F84500704E85684500705B85E84500706886684500707586E84500350FF00030805

And the gateway log at the same moment:

2021-09-08T10:58:20.930036+00:00 klk-fevo-0300E6 lorafwd[928]: <6> Received uplink message:
2021-09-08T10:58:20.930170+00:00 klk-fevo-0300E6 lorafwd[928]: <6> | lora uplink (3A100007), payload 24 B, channel 868.1 MHz, crc ok, bw 125 kHz, sf 7, cr 4/5
2021-09-08T10:58:20.930275+00:00 klk-fevo-0300E6 lorafwd[928]: <6> | Confirmed Data Up, DevAddr 26011D91, FCtrl [ADR], FCnt 43, FPort 1
2021-09-08T10:58:20.930337+00:00 klk-fevo-0300E6 lorafwd[928]: <6> |  - radio (00000105)
2021-09-08T10:58:20.930450+00:00 klk-fevo-0300E6 lorafwd[928]: <6> |   - demodulator counter 418591468, UTC time 2021-09-08T10:58:20.922835Z, rssi -41 dB, snr 5.75< 10.25 <15.25 dB
2021-09-08T10:58:20.932273+00:00 klk-fevo-0300E6 lorafwd[928]: <6> Uplink message (BA34) sent
2021-09-08T10:58:20.933165+00:00 klk-fevo-0300E6 lorad[900]: <6> Sent 1 uplink message
2021-09-08T10:58:20.981935+00:00 klk-fevo-0300E6 lorafwd[928]: <6> Uplink message (BA34) acknowledged in 49.6422 ms
2021-09-08T10:58:21.406396+00:00 klk-fevo-0300E6 lorafwd[928]: <6> Downlink message (0001) received
2021-09-08T10:58:21.406868+00:00 klk-fevo-0300E6 lorafwd[928]: <6> Received downlink message:
2021-09-08T10:58:21.407248+00:00 klk-fevo-0300E6 lorafwd[928]: <6> | lora downlink (00000001), payload 56 B, required 1, preamble 8 B, header enabled, crc disabled, polarity inverted
2021-09-08T10:58:21.407626+00:00 klk-fevo-0300E6 lorafwd[928]: <6> | Unconfirmed Data Down, DevAddr 26011D91, FCtrl [ADR] [ACK] [FPending], FCnt 19, FPort 0
2021-09-08T10:58:21.408008+00:00 klk-fevo-0300E6 lorafwd[928]: <6> |  - radio (00000000), channel 868.1 MHz, bw 125 kHz, sf 7, cr 4/5, power 14 dB
2021-09-08T10:58:21.408469+00:00 klk-fevo-0300E6 lorafwd[928]: <6> |   - transmission (00000000), priority 1, on counter 419591468
2021-09-08T10:58:21.410049+00:00 klk-fevo-0300E6 lorad[900]: <6> Received downlink message
2021-09-08T10:58:21.823255+00:00 klk-fevo-0300E6 lorafwd[928]: <6> Heartbeat (BA51) sent
2021-09-08T10:58:21.844039+00:00 klk-fevo-0300E6 lorafwd[928]: <6> Uplink message (BA35) sent
2021-09-08T10:58:21.869622+00:00 klk-fevo-0300E6 lorafwd[928]: <6> Heartbeat (BA51) acknowledged in 46.3489 ms
2021-09-08T10:58:21.892771+00:00 klk-fevo-0300E6 lorafwd[928]: <6> Uplink message (BA35) acknowledged in 48.7081 ms
2021-09-08T10:58:21.901176+00:00 klk-fevo-0300E6 lorad[900]: <6> Sent downlink message
2021-09-08T10:58:21.902138+00:00 klk-fevo-0300E6 lorafwd[928]: <6> Received uplink message: transmission event (00000001 / 00000000), status "Transmitted"
2021-09-08T10:58:21.902591+00:00 klk-fevo-0300E6 lorafwd[928]: <6> Downlink message (0001) acknowledged

Now that you mention it i did accidentally shedule a confirmed downlink at some point. I will try to clear the queue.

The entire packet is printed. Its taken from the LMIC.frame and LMIC.dataBeg fields.

process_gateway_downlink(LMIC.frame + LMIC.dataBeg, LMIC.dataLen);