I am Flask server enabled with Paho Mqtt with Python feature.
Various mqtt messages per second are send to the mqtt broker which are then stored in the database as soon as I am recieving messages but after some time mqtt broker fails to respond and slows down
Some messages are not recieved when inserting messages to database, as while inserting if some messages come, it doesn't catch.
3.My flask server is busy collecting mqtt messages, which slows down the website
here is the implementation part-
app.config['MQTT_BROKER_URL'] = 'xxxxxx'
app.config['MQTT_BROKER_PORT'] = 1883
app.config['MQTT_REFRESH_TIME'] = 1.0
mqtt = Mqtt(app)
socketio = SocketIO(app)
#socketio.on('publish')
def handle_publish(json_str):
data = json.loads(json_str)
mqtt.publish(data['topic'], data['message'])
#mqtt.on_connect()
def handle_connect(client, userdata, flags, rc):
mqtt.subscribe('topic1_name')
mqtt.subscribe('topic2_name')
#mqtt.on_message()
def handle_mqtt_message(client, userdata, message):
insert message to database
#app.route('/')
def index():
return render_template('new.html')
Is there anyway to seperate the script for collecting mqtt message and insertion to database to reduce the load? What could be done to make the mqtt broker more responsive?
Related
I'm using paho-MQTT and I can receive messages and I can display the data in a template(html), but I can't update the message in realtime in the template(html). I want to update the value in the template when I get a new message from the mosquitto/topic.
from django.shortcuts import render
import paho.mqtt.client as mqtt
import json
valor_mqtt = 0
def on_connect(client, userdata, flags, rc):
print("Connected with result code "+str(rc))
client.subscribe("mhub/hr")
def on_message(client, userdata, msg):
global valor_mqtt
valor_mqtt = (msg.payload)
print(valor_mqtt)
def print_on_m(request):
global valor_mqtt
message = str(valor_mqtt)
return render(request, 'home/index.html',{'context':message})
client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.connect("mqtt.eclipseprojects.io", 1883, 60)
I'm passing print_on_m in urls.py to use {{context}} in home/index.html to show the data
PS: I don't want to use functions like "setInterval(function() {" or ".load(window.location.href" to update part of the web page after some time, I want to update only when I get new message from mosquitto/topic
The short answer is you don't do it in django.
The template is only rendered once on the server side then sent to the client, it can't be updated once sent.
What you can do is if your broker supports MQTT over WebSockets then you can use either the Paho JavaScript client or the MQTT.js client to subscribe to the broker from within the page running in the browser and get updates directly then update the page accordingly.
I want to test the mosquitto MQTT Python client ports.
import json
import paho.mqtt.client as mqtt
def on_connect(client, userdata, flags, rc):
"""Called when connected to MQTT broker."""
client.subscribe("hermes/intent/#")
client.subscribe("hermes/nlu/intentNotRecognized")
print("Connected. Waiting for intents.")
def on_disconnect(client, userdata, flags, rc):
"""Called when disconnected from MQTT broker."""
client.reconnect()
def on_message(client, userdata, msg):
"""Called each time a message is received on a subscribed topic."""
nlu_payload = json.loads(msg.payload)
if msg.topic == "hermes/nlu/intentNotRecognized":
sentence = "Unrecognized command!"
print("Recognition failure")
else:
# Intent
print("Got intent:", nlu_payload["intent"]["intentName"])
# Speak the text from the intent
sentence = nlu_payload["input"]
site_id = nlu_payload["siteId"]
client.publish("hermes/tts/say", json.dumps({"text": sentence, "siteId": site_id}))
# Create MQTT client and connect to broker
client = mqtt.Client()
client.on_connect = on_connect
client.on_disconnect = on_disconnect
client.on_message = on_message
client.connect("localhost", 1883)
client.loop_forever()
I run it with the command
$ python script.py`
Connected. Waiting for intents.
Does mosquitto send a POST request? or do I have to start a request with mosquitto? How should I create a request so that I get
Got intent: SetTimer
MQTT is not HTTP, POST is a HTTP verb that has no meaning in a MQTT context.
MQTT is a pub/sub protocol, where as HTTP is a request/response protocol.
The code you have posted only subscribes to 2 topics, it doesn't publish anything (until it receives a message). So unless you have another application that will publish a message to 1 of the 2 topics the python code has subscribed to it will just sit there and wait for a message.
You can use the mosquitto command line tools to send a message if needed. e.g.
mosquitto_pub -t hermes/intent/foo -m '{"intent": { "intentName": "SetTimer"}}'
I'm having a problem with subscribing to MQTT broker (using test.mosquitto.org with port 1883) with paho mqtt library. When I use mosquitto_sub client, I'm getting messages normally, but when I subscribe to the same topic in my Python script, callback never gets executed.
import paho.mqtt.client as mqtt
client_get = mqtt.Client(client_id='my_client', protocol=mqtt.MQTTv31)
client_get.connect('test.mosquitto.org', 1883)
client_get.loop_start()
def callback(client, userdata, message):
print(str(message.payload.decode("utf-8")))
client_get.on_message = callback
client_get.subscribe(topic, qos=1)
Try the following:
import paho.mqtt.client as mqtt
client_get = mqtt.Client(client_id='my_client', protocol=mqtt.MQTTv31)
client_get.connect('test.mosquitto.org', 1883)
def callback(client, userdata, message):
print(str(message.payload.decode("utf-8")))
client_get.on_message = callback
client_get.subscribe(topic, qos=1)
client_get.loop_forever()
I've moved the start_loop() to the end and changed it to loop_forever() which will block and keep the script running.
I am using aiokafka==0.5.2 as python lib for kafka
I have just the code form the example:
async def consume():
consumer = AIOKafkaConsumer(
'my_topic', 'my_other_topic',
loop=loop, bootstrap_servers='localhost:9092',
group_id="my-group")
await consumer.start()
try:
# Consume messages
async for msg in consumer:
#...
When I run it - it works fine. But when I stop Kafka server - my app proceed hanging waiting for messages. And, I guess, when prod server exclude Kafka node from balancing - my app know nothing about this. How could I have listener on Kafka connection inside my app?
I am writing a django application which should act as MQTT publisher and as a subscriber.
Where should I start the paho client and run loop_forever() function.
Should it be in wsgi.py ?
Update:
If you need Django running in multiple threads then to publish messages from your Django app you can use helper functions from Publish module of Paho - https://eclipse.org/paho/clients/python/docs/#id17
You don't need to create an instance of mqtt client and start a loop in this case. And to subscribe to some topic consider running mqtt client as a standalone script and import there needed modules of your Django app (and don't forget to setup the Django environment in the script).
The answer below is good only if you run Django in a single thread, which is not usual in production.
Create mqtt.py in your application folder and put all related code there. For example:
import paho.mqtt.client as mqtt
def on_connect(client, userdata, rc):
client.subscribe("$SYS/#")
def on_message(client, userdata, msg):
# Do something
pass
client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.connect("iot.eclipse.org", 1883, 60)
Don't call loop_forever() here!
Then in your application __init__.py call loop_start():
from . import mqtt
mqtt.client.loop_start()
Using loop_start() instead of loop_forever() will give you not blocking background thread.
If you are using ASGI in your Django application you can use MQTTAsgi.
It's a complete protocol server for Django and MQTT.
Edit: Full disclosure I'm the author of MQTTAsgi.
Edit 2: To utilize the mqtt protocol server you can run your application, first you need to create a MQTT consumer:
from mqttasgi.consumers import MqttConsumer
class MyMqttConsumer(MqttConsumer):
async def connect(self):
await self.subscribe('my/testing/topic', 2)
async def receive(self, mqtt_message):
print('Received a message at topic:', mqtt_mesage['topic'])
print('With payload', mqtt_message['payload'])
print('And QOS:', mqtt_message['qos'])
pass
async def disconnect(self):
await self.unsubscribe('my/testing/topic')
Then you should add this protocol to the protocol router:
application = ProtocolTypeRouter({
'websocket': AllowedHostsOriginValidator(URLRouter([
url('.*', WebsocketConsumer)
])),
'mqtt': MyMqttConsumer,
....
})
Then you can run the mqtt protocol server with*:
mqttasgi -H localhost -p 1883 my_application.asgi:application
*Assuming the broker is in localhost and port 1883.
Thanks for the comments!