Welcome to the Pycom forum Forum
    • \[\[global:header.categories\]\]
    • \[\[global:header.recent\]\]
    • \[\[global:header.tags\]\]
    • \[\[global:header.popular\]\]
    • Login

    Explore Pybytes | Official Documentation | Report a Firmware Bug/Issue | GitHub

    How to implement downlink messages

    Scheduled Pinned Locked Moved LoPy
    lopylorawandownlinkapi
    16 Posts 5 Posters 6.2k Views 7 Watching
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • D Offline
      dbrgn
      last edited by

      I had some trouble getting downlink messages to work reliably.

      Some things that I did not find in the documentation:

      • When a downlink is received, is there a way to know what port it was sent to?
      • Is a downlink receive event triggered if no socket is bound to that port?
      • How do confirmed downlinks work? Is the downlink confirmed automatically? When does that happen, when the packet is received, or when the callback is called, or when the data is read from the socket?
      • Does it matter whether sockets on downlink ports are blocking or non-blocking?

      In my case sometimes I received the downlinks (just after sending a packet myself), sometimes I didn't. And I don't really know what the criteria are, or how this is supposed to work.

      How do downlinks work? A real-world example with LoRaWAN downlinks would be really useful.

      J 1 Reply Last reply Reply Quote 0
      • bmarkusB Offline
        bmarkus
        last edited by

        You are not specifiying

        • gateway type

        • network server type

        • sample code to demonstrate usage

        Are you expecting help or just telling your story?

        D 1 Reply Last reply Reply Quote 0
        • D Offline
          dbrgn @bmarkus
          last edited by

          • gateway type

          iC880A concentrator board

          • network server type

          The Things Network

          Are you expecting help or just telling your story?

          No reason for that derogatory tone. I had some clear questions in my original post. Additionally, i was stating that there is currently no high level documentation or sample code on receiving / handling downlink messages. (Counterexample: Joining via OTAA/ABP is well documented with an introduction and a code example.)

          1 Reply Last reply Reply Quote 0
          • D Offline
            dbrgn
            last edited by

            Some more experiments due to lack of documentation and feedback. The base is this script:

            import binascii
            from network import LoRa
            import usocket
            import ustruct
            import utime
            import pycom
            
            DEV_ADDR = ''
            NWK_SKEY = ''
            APP_SKEY = ''
            
            # Disable LoPy heartbeat
            pycom.heartbeat(False)
            
            # Join LoRaWAN network
            lr = LoRa(mode=LoRa.LORAWAN)
            auth = (
                ustruct.unpack('>l', binascii.unhexlify(DEV_ADDR.replace(' ', '')))[0],
                binascii.unhexlify(NWK_SKEY.replace(' ', '')),
                binascii.unhexlify(APP_SKEY.replace(' ', '')),
            )
            print('Joining')
            lr.join(activation=LoRa.ABP, auth=auth)
            while not lr.has_joined():
                utime.sleep_ms(1000)
                print('Not yet joined...')
            print('Joined')
            
            # Set callback
            def lora_callback(lora):
                print('A LoRa event occured: ', end='')
                events = lora.events()
                if events & LoRa.RX_PACKET_EVENT:
                    print('Lora packet received')
                elif events & LoRa.TX_PACKET_EVENT:
                    print('Lora packet sent')
                else:
                    print('Other event: %s' % events)
            
            lr.callback(LoRa.RX_PACKET_EVENT | LoRa.TX_PACKET_EVENT, lora_callback)
            
            # Initialize socket
            s_out = usocket.socket(usocket.AF_LORA, usocket.SOCK_RAW)
            s_out.setsockopt(usocket.SOL_LORA, usocket.SO_DR, 5)
            s_out.setsockopt(usocket.SOL_LORA, usocket.SO_CONFIRMED, False)
            s_out.setblocking(False)
            s_out.bind(100)
            
            # Main loop
            counter = 0
            while True:
                print('Sending packet %d...' % counter)
                s_out.send(bytes([counter]))
                counter += 1
                utime.sleep_ms(10000)
            

            With this, a packet is sent out every 10 seconds on FPort 100. I scheduled a downlink to FPort 200, between packet 2 and 3:

            screenshot

            This is the log:

            Sending packet 0...
            A LoRa event occured: Lora packet sent
            Sending packet 1...
            A LoRa event occured: Lora packet sent
            Sending packet 2...
            A LoRa event occured: Lora packet sent
            Sending packet 3...
            A LoRa event occured: Lora packet sent

            As it can be seen from the screenshot and the log, the downlink was scheduled and delivered, but no event was raised on the LoPy. From that, I'd interpret that if there's no socket initialized on the port, nothing happens.

            So I sent the downlink on FPort 100 instead:

            screenshot

            The downlink was seemingly delivered, yet no message in the events callback.

            Ok, maybe there needs to be a socket that hasn't been used for transmitting yet? Let's try this:

            # Initialize incoming socket
            s_in = usocket.socket(usocket.AF_LORA, usocket.SOCK_RAW)
            s_in.bind(150)
            

            Now I'll send a downlink to port 150:

            screenshot

            Again, downlink sent, no event happened in the callback.

            What am I doing wrong?

            I'm on firmware version 1.7.8.b1. I'm connected to The Things Network. The gateway is 10 meters from here with very good signal strength.

            J J 2 Replies Last reply Reply Quote 0
            • J Offline
              jcaron @dbrgn
              last edited by

              @dbrgn what happens if instead of listening for events you actually try to receive data on the socket right after sending?

              1 Reply Last reply Reply Quote 0
              • J Offline
                jmarcelino @dbrgn
                last edited by jmarcelino

                Hi @dbrgn,

                I feel your original post is spreading into too many topics: your problems with downlinks, downlink port numbers, confirmed downlinks and blocking vs non-blocking. Makes it hard for someone to help out and thus it becomes less likely to get an answer at all.

                I'd recommend limiting to one or two questions per post.

                Let's start with the difficulties with downlinks. You say you get some occasionally but not all. I see from your code your appear to be using a single channel gateway? Is this another LoPy running the nano gateway code?

                Can you post a screenshot of the TTN "Gateway Traffic" page for your gateway, showing the frequencies and transmission times?

                1 Reply Last reply Reply Quote 0
                • D Offline
                  dbrgn
                  last edited by

                  Thanks for your answers, @jmarcelino and @jcaron :)

                  @dbrgn what happens if instead of listening for events you actually try to receive data on the socket right after sending?

                  Good idea. Does not seem to work though :(

                  Sending packet 3...
                  Try to receive on port 150...
                  Timeout
                  A LoRa event occured: Lora packet sent
                  Sending packet 4...
                  Try to receive on port 150...
                  Timeout
                  A LoRa event occured: Lora packet sent

                  This is the code I used:

                  # Initialize incoming socket
                  s_in = usocket.socket(usocket.AF_LORA, usocket.SOCK_RAW)
                  s_in.setblocking(False)
                  s_in.settimeout(1)
                  s_in.bind(150)
                  
                  # Main loop
                  counter = 0
                  while True:
                      print('Sending packet %d...' % counter)
                      s_out.send(bytes([counter]))
                      counter += 1
                      print('Try to receive on port 150...')
                      try:
                          received = s_in.recv(64)
                          print('Received: %r' % received)
                      except:
                          print('Timeout')
                      utime.sleep_ms(10000)
                  

                  I feel your original post is spreading into too many topics

                  You might be right. On the other hand, a single known-to-be-working example by Pycom could probably cover all those areas :)

                  I see from your code your appear to be using a single channel gateway?

                  No, it's an iC880A board with the poly packet forwarder that a lot of other people run in production. Joining via OTAA works, so it's definitely capable of doing downlinks.

                  Can you post a screenshot of the TTN "Gateway Traffic" page for your gateway, showing the frequencies and transmission times?

                  Great idea. Here's the screenshot of four uplinks and one downlink:

                  screenshot

                  I also tried to send a confirmed downlink. According to the gateway stats it was only sent down once, but I can't see any flag whether it was confirmed or not by the LoPy. Not sure how TTN handles the displaying of confirmed downlinks.

                  J 1 Reply Last reply Reply Quote 1
                  • D Offline
                    dbrgn
                    last edited by

                    Also, here's an excerpt from the gateway logs, after sending two downlinks:

                    Jul 28 20:54:15 ttn-gw-test ttn-gateway[2881]: ### [DOWNSTREAM] ###
                    Jul 28 20:54:15 ttn-gw-test ttn-gateway[2881]: # PULL_DATA sent: 3 (100.00% acknowledged)
                    Jul 28 20:54:15 ttn-gw-test ttn-gateway[2881]: # PULL_RESP(onse) datagrams received: 2 (346 bytes)
                    Jul 28 20:54:15 ttn-gw-test ttn-gateway[2881]: # RF packets sent to concentrator: 2 (28 bytes)
                    Jul 28 20:54:15 ttn-gw-test ttn-gateway[2881]: # TX errors: 0
                    

                    I'm not sure I read this correctly, but I think that means that 2 downlink packets were sent over the air from the gateway to the node.

                    1 Reply Last reply Reply Quote 0
                    • J Offline
                      jmarcelino @dbrgn
                      last edited by

                      @dbrgn
                      OK since you're using ABP how are you handling the frame counters? Resetting them through the TTN console?

                      I see in your example your uplink counter seems to have started back from 1 when the first downlink counter there is 7.

                      TTN's console display of confirmed downlinks is a bit buggy AFAIK so you might not see it in the browser.

                      1 Reply Last reply Reply Quote 0
                      • D Offline
                        dbrgn
                        last edited by dbrgn

                        @jmarcelino said in How to implement downlink messages:

                        OK since you're using ABP how are you handling the frame counters? Resetting them through the TTN console?

                        I use relaxed frame counters for development.

                        I see in your example your uplink counter seems to have started back from 1 when the first downlink counter there is 7.

                        I think that makes sense, since the uplink frame counters are managed by the device (and reset when the device resets) while the downlinks are managed by the server, where the counter can be stored properly.

                        To make sure that nothing is wrong with the configuration, I deleted and re-created the device in the TTN backend. Then I re-did the same example script with OTAA instead of ABP. Joining worked (so downlink transmission seems to work fine in principle). But the downlinks did not arrive.

                        Maybe I'll get the possibility to test with a different network in the next days (not sure if I have coverage). But I haven't heard of downlink issues with TTN so far.

                        J J 2 Replies Last reply Reply Quote 0
                        • J Offline
                          jmarcelino @dbrgn
                          last edited by jmarcelino

                          @dbrgn said in How to implement downlink messages:

                          I use relaxed frame counters for development.

                          Ok I asked because "relaxed frame counters" means TTN disregards uplink counters when authenticating incoming messages but it doesn't mean the LoPy will disregard frame counters on downlinks: TTN's counter must always be higher than what the LoPy expects (up to a "max frame counter gap" ...). But yes that is happening and not the problem in this case.

                          @dbrgn said in How to implement downlink messages:

                          Maybe I'll get the possibility to test with a different network in the next days (not sure if I have coverage). But I haven't heard of downlink issues with TTN so far.

                          Downlinks in general should work. What I meant is there are reported issues with the display of confirmed downlinks on TTN's console.

                          All my LoPy are tied up at the moment so I can't test this, but what happens if you do uplinks and downlinks using the same port number instead of different as you're doing? It may be that you really only have one LoRa socket for the whole system so the uplink and downlink port numbers must match.

                          1 Reply Last reply Reply Quote 0
                          • J Offline
                            jcaron @dbrgn
                            last edited by

                            @dbrgn Just to be sure, you are aware of the 10 downlink messages per day limitation on TTN? Note that this includes confirmed uplink ACKs. Basically downlinks are unusable on LoRaWAN, at least in the ETSI region.

                            Not quite sure how this would appear in logs though.

                            D 1 Reply Last reply Reply Quote 0
                            • D Offline
                              dbrgn @jcaron
                              last edited by

                              @jcaron said in How to implement downlink messages:

                              @dbrgn Just to be sure, you are aware of the 10 downlink messages per day limitation on TTN? Note that this includes confirmed uplink ACKs. Basically downlinks are unusable on LoRaWAN, at least in the ETSI region.

                              Yes, but I think so far that's just a soft limit. I won't do that many downlinks in production, but I think it's fair if I occasionally go over the limit while testing as long as I don't exceed the 1% duty cycle, especially since both gateways in my area are provided by me :)

                              @jmarcelino said in How to implement downlink messages:

                              but what happens if you do uplinks and downlinks using the same port number instead of different as you're doing?

                              I think I tried that too, without better results.

                              It may be that you really only have one LoRa socket for the whole system so the uplink and downlink port numbers must match.

                              If that would the case, the LoRaWAN stack would be pretty useless :) But I don't think it's the case. At least sending on different ports works properly.

                              1 Reply Last reply Reply Quote 0
                              • J Offline
                                jmarcelino @dbrgn
                                last edited by

                                @dbrgn
                                I came across this one today and found there is a problem in the current implementation, only downlinks to ports 1 and 2 are being accepted.

                                https://github.com/pycom/pycom-micropython-sigfox/issues/46

                                May explain your problems.

                                B D 2 Replies Last reply Reply Quote 2
                                • B Offline
                                  Brick @jmarcelino
                                  last edited by

                                  @jmarcelino Thanks. I was trying to get downlink messages for about a week now without success.
                                  Changing port to 1 helped.

                                  1 Reply Last reply Reply Quote 1
                                  • D Offline
                                    dbrgn @jmarcelino
                                    last edited by

                                    @jmarcelino wow, thanks a lot for that find. explains the headaches I've been having :)

                                    1 Reply Last reply Reply Quote 0

                                    Hello! It looks like you're interested in this conversation, but you don't have an account yet.

                                    Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.

                                    With your input, this post could be even better 💗

                                    Register Login
                                    • 1 / 1
                                    • First post
                                      Last post

                                    Pycom on Twitter

                                    Pycom