Has anyone used mqtt paho python library to send downlink message to the end device?

Most of the sources use MQTT Paho python library for uplink messages. I want to know whether I can send the downlink messages using this library.

Yes. See the source code of the (deprecated) Python SDK; https://github.com/TheThingsNetwork/python-app-sdk/blob/master/ttn/ttnmqtt.py

3 Likes

By the way: you might want to define the logging callback, as Paho tends to swallow many exceptions in callbacks.

When looking at the (deprecated) TTN SDK, add something like:

import logging
import paho.mqtt.client as mqtt
...
class MQTTClient:
    ...
    def connect(self):
        self.__client.on_log = self._on_log
        ...

    def _on_log(self, client, userdata, level, buf):
        """
        Log all MQTT protocol events, including the exceptions
        in callbacks that are caught by Paho.
        """
        logging_level = mqtt.LOGGING_LEVEL[level]
        logging.log(logging_level, buf)

Also, you might want to use TLS (and port 8883 rather than the non-TLS 1883). Just adding the following at some point before invoking self.__client.connect will do:

# By default, on Python 2.7.9+ or 3.4+, the default certification
# authority of the system is used.
self.__client.tls_set()

Alternatively, explicitly refer to the Certificate Authority chain as used by the Let’s Encrypt server certificate, which is available in https://console.thethingsnetwork.org/mqtt-ca.pem:

self.__client.tls_set(ca_certs="mqtt-ca.pem")

I’ve never used the TTN SDK, and maybe the full SDK somehow actually supports TLS already (like given its reference to GRPC_SSL_CIPHER_SUITES in its MQTT code, which given the name GRPC might very well be the result of some copy-paste though). But when looking at the Paho documentation I doubt that, and for a plain Paho client you’ll need to enable it explicitly.

Finally: beware that you’re actually scheduling downlinks, not sending them. Timing is critical, and a downlink scheduled as the result of an uplink might very well only be transmitted after receiving the next uplink. (The TTN community network only supports Class A devices, which only allow for downlinks as a response to an uplink.)

2 Likes

Thanks Arjan. Concerning the downlinks. In order for me to work with Class C devices that means I have to setup the private network since, it is not supported on public network? Would be the same library still be compatible?

Do you already have your downlinks working with MQTT? since the ttn sdk for python is discontinued if there is a good way to create downlinks with something like paho, receiving uplinks works fine, but I can’t seem to find a way to create downlinks.

Welcome, but please don’t bump multiple old topics with the same question. I’ve removed your other post. Also, a link to a reference solution (in the code of the deprecated SDK) has been provided in this very topic.

So: what is not working for you?

See also a simpler (but quite specific) working example in Time synchronisation of a Node.

Hello Arjan, sorry for the multiple bumps but I found the other topic later and maybe it had more in common with my “issue”. It is fairly simple I guess but I can’t seem to get a downlink on my TTN application data, when I simulate an uplink I will get it in my python application using paho, but I can’t find an example for sending downlinks to the application. And since the ttn sdk was discontinued I thought paho should be the way for python applications nowadays.

Edit: I basically just want to publish a message.

Hello Arjan,

I think what i’m just wandering if it is possible and how is it possible to publish a message on my ttn application schedule ready for being downlinked.

I’m not very familiar with Python and even less so with TTN but what I want to do is a mosquitto like operation like:
mqttc.publish(’((app-id))r/devices/((dev-id))/down’, payload=“AA”)

if that is in any way possible? I dont completely understand how to use the example you sent in the link with my basic knowledge of Python.

I know this is an old thread but since it took me a while to figure it out - here my solution:

!/usr/bin/python3 -u                                                                                                                      

import paho.mqtt.client as mqtt
import json
import time
import datetime
import sys
import base64

broker = "us-west.thethings.network" 
port   = 8883
APPID  = "your appid" 
DEVID  = "your dev id"
PSW    = "your key"
topic  = APPID + "/devices/" + DEVID + "/down"

try: 
     str(sys.argv[1])
except IndexError:
     print("empty input")
     exit(1)
     
command  = str(sys.argv[1])
message  = '{"port":1,"payload_raw":"' + base64.b64encode(command.encode("ascii")).decode("ascii") + '"}' 

print('starting up ...')
def on_connect(client, userdata, flags, rc): 
     if rc==0:
         client.connected_flag=True #set flag
         print("connected OK")
         client.subscribe('+/devices/+/up')
     else:
         print("Bad connection Returned code=",rc)
         exit(1)

def on_publish(client,userdata,result):
     print("command:",command," userdata:",userdata," result:",result)
     print("data published \n")
     pass

client = mqtt.Client()
client.on_connect = on_connect 
client.on_publish = on_publish
#client.on_message = on_message
client.tls_set()
client.username_pw_set(APPID, PSW)
 
client.connect(broker, port, 60) 
client.publish(topic,message)
 
client.loop_start()
client.loop_stop()
client.disconnect()

Please take a moment to properly format your post!

better?

Yep, for a programming language that depends on indentation the code makes a lot more sense now :laughing: