【问题标题】:How to implement paho python client in Django 3.1如何在 Django 3.1 中实现 paho python 客户端
【发布时间】:2021-03-01 06:54:27
【问题描述】:

来自this SO question,我在我的 Django 项目中实现了一个订阅客户端,如下所示:

mqtt.py 中,我创建一个客户端并连接到本地代理并订阅一个主题。

#myapp/mqtt.py:
import paho.mqtt.client as paho
import json
import django
django.setup()
from .models import Temperature, Turbidity, Refined_fuels, Crude_oil
from datetime import datetime

# The callback for when the client receives a CONNACK response from the server.
def on_connect(client, userdata, flags, rc):
    print("CONNACK received with code %d." % (rc))
    client.subscribe("sensor/temp", qos=0)


def on_subscribe(client, userdata, mid, granted_qos):
    print("Subscribed: "+str(mid)+" "+str(granted_qos))

# The callback for when a PUBLISH message is received from the server.
def on_message(client, userdata, msg):
    print(msg.topic+", "+'QOS: ' +str(msg.qos)+",\n"+str(msg.payload, 'utf-8'))
    message_dict = json.loads(msg.payload)
    
    now = datetime.now()
    captured_timestamp = datetime.utcfromtimestamp(int(message_dict['Timestamp'])).strftime('%Y-%m-%d %H:%M:%S')
    print('timestamp: ', captured_timestamp )
    if message_dict['Temperature'] and message_dict['D850'] and message_dict['D280']:
            
        temp = Temperature(captured_timestamp=captured_timestamp, data=message_dict['Temperature'], received_timestamp=now)
        temp.save()
        refined_fuels = Refined_fuels(captured_timestamp=captured_timestamp, data=float(message_dict['D850']), received_timestamp=now)
        refined_fuels.save()
        crude_oil = Crude_oil(captured_timestamp=captured_timestamp, data=float(message_dict['D280']), received_timestamp=now)
        crude_oil.save()

# defining client
client = paho.Client(client_id="testSubscriber",
                     clean_session=True, userdata=None,
                     protocol=paho.MQTTv311)

# adding callbacks to client
client.on_connect = on_connect
client.on_subscribe = on_subscribe
client.on_message = on_message

client.connect(host="localhost", port=1883, keepalive=60,
               bind_address="" )

__init__.py我调用客户端的loop_start()

# myapp/__init__.py
from . import mqtt

mqtt.client.loop_start()

对于 publisher 客户端,我使用了 paho C 客户端。对于 broker,我使用了 hivemq-4.5.1 企业试用版。而且,我正在 ubuntu 18.04 上运行该项目。

现在,当我运行 Django 服务器(python manage.py runserver)时,它一直调用 on_connect() 方法并继续 on_connect() 方法,但是服务器没有运行,我无法从 localhost:8000 访问项目。

这是在 on_connect()on_subscribe() 方法继续打印它们的消息之前的 django 错误:

Exception in thread django-main-thread:
Traceback (most recent call last):
  File "/usr/local/lib/python3.8/threading.py", line 932, in _bootstrap_inner
    self.run()
  File "/usr/local/lib/python3.8/threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
  File "/home/shahriar/webapp/venv/lib/python3.8/site-packages/django/utils/autoreload.py", line 53, in wrapper
    fn(*args, **kwargs)
  File "/home/shahriar/webapp/venv/lib/python3.8/site-packages/django/core/management/commands/runserver.py", line 110, in inner_run
    autoreload.raise_last_exception()
  File "/home/shahriar/webapp/venv/lib/python3.8/site-packages/django/utils/autoreload.py", line 76, in raise_last_exception
    raise _exception[1]
  File "/home/shahriar/webapp/venv/lib/python3.8/site-packages/django/core/management/__init__.py", line 357, in execute
    autoreload.check_errors(django.setup)()
  File "/home/shahriar/webapp/venv/lib/python3.8/site-packages/django/utils/autoreload.py", line 53, in wrapper
    fn(*args, **kwargs)
  File "/home/shahriar/webapp/venv/lib/python3.8/site-packages/django/__init__.py", line 24, in setup
    apps.populate(settings.INSTALLED_APPS)
  File "/home/shahriar/webapp/venv/lib/python3.8/site-packages/django/apps/registry.py", line 94, in populate
    raise ImproperlyConfigured(
django.core.exceptions.ImproperlyConfigured: Application labels aren't unique, duplicates: graphs

这是正常且未显示错误的代理日志:

2021-03-01 10:06:38,059 INFO  - Sent PUBLISH to client 'testSubscriber' on topic 'sensor/temp': Payload: '{ "Timestamp": 1609446782, "Temperature": "30.13", "D850": "102.48", "D280": "4845.83" }', QoS: '0', Retained: 'false'
2021-03-01 10:06:38,075 INFO  - Received CONNECT from client 'testSubscriber': Protocol version: 'V_3_1_1', Clean Start: 'true', Session Expiry Interval: '0'
2021-03-01 10:06:38,207 INFO  - Sent CONNACK to client 'testSubscriber': Reason Code: 'SUCCESS', Session Present: 'false'
2021-03-01 10:06:38,209 INFO  - Received SUBSCRIBE from client 'testSubscriber': Topics: { [Topic: 'sensor/temp', QoS: '0'] }
2021-03-01 10:06:38,209 INFO  - Sent SUBACK to client 'testSubscriber': Suback Reason Codes: { [Reason Code: 'GRANTED_QOS_0'] }
2021-03-01 10:06:39,056 INFO  - Received PUBREL from client 'testPublisher': Reason Code: 'SUCCESS'
2021-03-01 10:06:39,057 INFO  - Sent PUBCOMP to client 'testPublisher': Reason Code: 'SUCCESS'
2021-03-01 10:06:39,131 INFO  - Received CONNECT from client 'testSubscriber': Protocol version: 'V_3_1_1', Clean Start: 'true', Session Expiry Interval: '0'
2021-03-01 10:06:39,158 INFO  - Received PUBLISH from client 'testPublisher' for topic 'sensor/temp': Payload: '{ "Timestamp": 1609446783, "Temperature": "30.13", "D850": "102.48", "D280": "4845.83" }', QoS: '2', Retained: 'false'
2021-03-01 10:06:39,161 INFO  - Sent PUBREC to client 'testPublisher': Reason Code: 'SUCCESS'
2021-03-01 10:06:39,200 INFO  - Sent CONNACK to client 'testSubscriber': Reason Code: 'SUCCESS', Session Present: 'false'
2021-03-01 10:06:39,201 INFO  - Received SUBSCRIBE from client 'testSubscriber': Topics: { [Topic: 'sensor/temp', QoS: '0'] }
2021-03-01 10:06:39,203 INFO  - Sent SUBACK to client 'testSubscriber': Suback Reason Codes: { [Reason Code: 'GRANTED_QOS_0'] }
2021-03-01 10:06:40,162 INFO  - Received PUBREL from client 'testPublisher': Reason Code: 'SUCCESS'
2021-03-01 10:06:40,162 INFO  - Sent PUBCOMP to client 'testPublisher': Reason Code: 'SUCCESS'
2021-03-01 10:06:40,262 INFO  - Received PUBLISH from client 'testPublisher' for topic 'sensor/temp': Payload: '{ "Timestamp": 1609446784, "Temperature": "30.13", "D850": "102.48", "D280": "4845.83" }', QoS: '2', Retained: 'false'
2021-03-01 10:06:40,263 INFO  - Sent PUBREC to client 'testPublisher': Reason Code: 'NO_MATCHING_SUBSCRIBERS'
2021-03-01 10:06:41,262 INFO  - Received PUBREL from client 'testPublisher': Reason Code: 'SUCCESS'
2021-03-01 10:06:41,263 INFO  - Sent PUBCOMP to client 'testPublisher': Reason Code: 'SUCCESS'

现在的问题是,在 Django 中 paho python 客户端的实现错了吗?

由于我想将消息存储在 DB 中,我将模型导入 mqtt.py 并导致错误:

raise AppRegistryNotReady("应用尚未加载。") django.core.exceptions.AppRegistryNotReady:应用尚未加载。

克服它。我放了

import django
django.setup()

mqtt.py 中导入模型之前解决了问题。 据我所知,它会在主应用程序之前启动mqtt.py 在其中的应用程序。因此 django 看到该应用程序的两个实例并抛出此错误:

提出不当配置( django.core.exceptions.ImproperlyConfigured:应用程序标签不唯一,重复:图表

所以,我知道我的实现是错误的。但是如何纠正呢?

【问题讨论】:

标签: python django mqtt paho


【解决方案1】:

在按照与您所拥有的类似的设置后,我遇到了类似的问题,这里: https://stackoverflow.com/a/41017210/13001393

重复连接的解决是由于 MQTT 服务器上的设置,其中用户名设置为 clientid。

mosquitto.conf

# Set use_username_as_clientid to true to replace the clientid that a client
# connected with with its username. This allows authentication to be tied to
# the clientid, which means that it is possible to prevent one client
# disconnecting another by using the same clientid.
# If a client connects with no username it will be disconnected as not
# authorised when this option is set to true.
# Do not use in conjunction with clientid_prefixes.
# See also use_identity_as_username.
use_username_as_clientid true

您可能需要检查该设置。并确保您为每个 mqtt 客户端使用不同的用户名。

【讨论】:

  • 谢谢你的朋友。我通过调用 urls.py 文件中的循环函数克服了这个问题。首先使用 init.py 是错误的。而且只有一个客户端和一个用户名,所以看起来不是问题。顺便说一句,谢谢你的时间
  • @Shahriar.M 你能分享代码吗?
猜你喜欢
  • 2017-04-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-18
相关资源
最近更新 更多