MQTT Made Simple [Websocket]

Hello everyone, I have been working on this module to simplify my development of websockets using the Paho MQTT module.

I have basically translated the whole JS Paho library to a python class that can easily be used in Anvil Apps.

To demonstrate this I have built a simple messenger app that allows you to chat with the OpenAI GPT-3 Friendly Chat.

Not every method in this has been fully tested, so if you find any issues or have suggestions, please let me know!

Hope you enjoy!

https://anvil.works/build#clone:WXTLZNU354EXKBYF=TVM3W3A7GLPGKKN6XZIOQVTO

6 Likes

I saw “websocket” on the subject and I thought “that’s impossible with Anvil”.

Is the websocket connected to the Anvil server or to a third MQTT server?

1 Like

It’s a third party broker. The example is using a public broker, but you can setup your own at HiveMQ for free

1 Like

That’s very cool!

It looks like MQTTClient can be used to publish messages. That’d need some thought in any app that needed some sort of validation of messages (an online game, for example), to keep someone from tinkering with the client code to send valid but illegal messages. Maybe some sort of signing of messages sent by the server. That’d be app specific, of course.

I guess that brings up the question about why the sample app uses the server to send messages, rather than using MQTTClient’s publish method instead?

2 Likes

Really appreciate your effort. Great work

1 Like

Very valid points. I had considered that too but decided that since I was going to share this I wanted to try and include everything. However, in my use cases, I plan to use the MQTT publish only on the server-side.

To increase security this is what I am planning to try:

  1. Server has something new it want’s the client to know about. and it saves a token and name of the callable server function in a warehouse table.
app_tables.mqtt_tokens.add_row(function="my_server_func", token="lsgi9042")
  1. Server uses MQTTServer to publish a message containing a dict with the token and name of the callable server function.
my_mqtt = MQTTServer() 
data = {"function": "my_server_func", "token": "lsgi9042"}
my_mqtt.mqtt_publish_simple("my_topic", data)
  1. Client receives the message and calls the function listed in the message.
anvil.server.call("my_server_func", token="lsgi9042")
  1. Server function searches warehouse table to validate it is authorized to perform the work.
@anvil.server.callable
def my_server_func(token):
  token_row = None
  user = anvil.users.get_user()
  if user != None:
    user_id = user.get("user_id")
    if user_id:
      # to make this faster I'd likely put just the user id in a simple object as opposed to linking the row
      token_row = app_tables.mqtt_tokens.get(token=token, used_by=q.none_of(["user_id"]))

  if token_row != None:
    # code to do work
  1. Function logs user ID or some other identifiable variable in the token row of warehouse table to prevent the malicious calling of that token
def log_token_user(token, user_id):
  token_row = app_tables.mqtt_tokens.get(token=token) 
  used_by = token_row.get("used_by") or [] 
  used_by += [user_id] 
  token_row["used_by"] = user_by

I know this is a bit more traffic but it’s better than using a background task and constantly polling the server.

Concerning your question about not using the client to publish instead of the server. This is really twofold. One, I wanted to demonstrate how to use the MQTTServer class. Two, I personally intend to try and use the MQTT as little as possible as it becomes another service that needs to be paid for when used at scale. So the lower traffic on it and with Anvil, the lower the financial obligation.

Of course, I am open to any ideas anyone might have to improve this process!

3 Likes

Thank you for the great contribution! I am trying to implement this method currently and found a library we have access to if you are on the personal plan and above:

paho

developed by eclipse, you might be interested in.

1 Like

Thanks, I appreciate it.

Actually, Paho is what this module is built on. I basically just translated it from javascript into a more pythonic version for simple use in Anvil.

1 Like

right, I guess I meant there is a paho-mqtt python library that is apart of anvil’s list of packages and the link above is a document on how to use that library that might have some extra functionality you want.

Yeah, but that is server-side only I believe.

1 Like

you are totally right…thank you!

1 Like

A post was merged into an existing topic: How to implement Email and chat room systems for users of an application