[英]Issue running self objects in mqtt paho callback function
我正在嘗試編寫一個腳本來保存 mqtt 數據並將其發送到 influxDB。 我遇到的問題是 mqtt-paho 模塊的回調函數不斷給出錯誤: AttributeError: 'Client' object has no attribute 'write_api'
。 我想,這是因為的self
內部“客戶”類MQTT -泛美衛生組織。 我的完整腳本可以在下面找到:
# Imported modules
# standard time module
from datetime import datetime
import time
# InfluxDB specific modules
from influxdb_client import InfluxDBClient, Point, WritePrecision
from influxdb_client.client.write_api import SYNCHRONOUS
#MQTT paho specific modules
import paho.mqtt.client as mqtt
class data_handler(): # Default namespaces are just for all the ESPs.
def __init__(self, namespace_list=["ESP01","ESP02","ESP03","ESP04","ESP05","ESP06","ESP07","ESP08"]):
# initialize influxdb client and define access token and data bucket
token = "XXXXXXXXXX" # robotlab's token
self.org = "Home"
self.bucket = "HomeSensors"
self.flux_client = InfluxDBClient(url="http://localhost:8086", token=token)
self.write_api = self.flux_client.write_api(write_options=SYNCHRONOUS)
# Initialize and establish connection to MQTT broker
broker_address="XXX.XXX.XXX.XXX"
self.mqtt_client = mqtt.Client("influx_client") #create new instance
self.mqtt_client.on_message=data_handler.mqtt_message #attach function to callback
self.mqtt_client.connect(broker_address) #connect to broker
# Define list of namespaces
self.namespace_list = namespace_list
print(self.namespace_list)
def mqtt_message(self, client, message):
print("message received " ,str(message.payload.decode("utf-8")))
print("message topic=",message.topic)
print("message qos=",message.qos)
print("message retain flag=",message.retain)
sequence = [message.topic, message.payload.decode("utf-8")]
self.write_api.write(self.bucket, self.org, sequence)
def mqtt_listener(self):
for namespace in self.namespace_list:
self.mqtt_client.loop_start() #start the loop
print("Subscribing to topics!")
message = namespace+"/#"
self.mqtt_client.subscribe(message, 0)
time.sleep(4) # wait
self.mqtt_client.loop_stop() #stop the loop
def main():
influxHandler = data_handler(["ESP07"])
influxHandler.mqtt_listener()
if __name__ == '__main__':
main()
代碼工作正常,直到我在回調函數中添加self.someVariable
。 什么是解決這個問題的好方法? 我真的不想創建全局變量,因此我選擇使用一個類。
提前致謝!
當涉及多個類時處理self
可能會令人困惑。 paho 庫調用on_message
如下:
on_message(self, self._userdata, message)
所以傳遞的第一個參數是Client
的實例,所以你看到的是預期的(在沒有任何類的情況下)。
如果回調是一個 方法對象(這似乎是你的目標)“實例對象作為函數的第一個參數傳遞”。 這意味着您的函數將采用四個參數,定義為:
mqtt_message(self, client, userdata, msg)
基於此,您可能希望您的應用程序比它更早失敗,但讓我們看看您如何設置回調:
self.mqtt_client.on_message=data_handler.mqtt_message
datahandler
是類本身,而不是類的實例。 這意味着您有效地將回調設置為靜態函數(沒有綁定到類的任何實例 -這個答案可能會有所幫助)。 您需要將其更改為:
self.mqtt_client.on_message=self.mqtt_message
但是,這不起作用,因為該方法目前只需要三個參數; 將定義更新為:
def mqtt_message(self, client, userdata, msg)
有了這些改變,我相信這會奏效(或者至少你會發現另一個問題:-))。
一個例子可能是解釋這一點的更好方法:
class mqtt_sim():
def __init__(self):
self._on_message = None
@property
def on_message(self):
return self._on_message
@on_message.setter
def on_message(self, func):
self._on_message = func
# This is what you are doing
class data_handler1(): # Default namespaces are just for all the ESPs.
def __init__(self):
self.mqtt = mqtt_sim()
self.mqtt.on_message = data_handler1.mqtt_message # xxxxx
def mqtt_message(self, client, message):
print("mqtt_message1", self, client, message)
# This is what you should be doing
class data_handler2(): # Default namespaces are just for all the ESPs.
def __init__(self):
self.mqtt = mqtt_sim()
self.mqtt.on_message = self.mqtt_message #attach function to callback
def mqtt_message(self, mqttself, client, message):
print("mqtt_message2", self, mqttself, client, message)
# Lets try using both of the above
d = data_handler1()
d.mqtt._on_message("self", "userdata", "message")
d = data_handler2()
d.mqtt._on_message("self", "userdata", "message")
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.