华荣三照明、合信、荣欣八组合馈电
This commit is contained in:
218
mqtt_device.py
Normal file
218
mqtt_device.py
Normal file
@ -0,0 +1,218 @@
|
||||
import threading
|
||||
import time
|
||||
import string
|
||||
from threading import Thread
|
||||
import menu_utils as utils
|
||||
import paho.mqtt.client as mqtt
|
||||
from print_color import *
|
||||
|
||||
|
||||
#mqtt 消息处理基类, mqtt消息处理
|
||||
class class_comm_mqtt_interface :
|
||||
def __init__(self, name = "mqtt handler"):
|
||||
self.name = name
|
||||
|
||||
def on_message(self, mqtt_thread, topic, message) :
|
||||
return
|
||||
|
||||
def on_connect(self, mqtt_thread, userdata, flags, rc) :
|
||||
return
|
||||
|
||||
#mqtt服务器连接处理
|
||||
def mqtt_on_connect(client, userdata, flags, rc):
|
||||
if rc == 0:
|
||||
# 连接成功
|
||||
print_normal_msg("Mqtt 服务器连接成功")
|
||||
elif rc == 1:
|
||||
# 协议版本错误
|
||||
print_error_msg("协议版本错误")
|
||||
elif rc == 2:
|
||||
# 无效的客户端标识
|
||||
print_error_msg("无效的客户端标识")
|
||||
elif rc == 3:
|
||||
# 服务器无法使用
|
||||
print_error_msg("Mqtt 服务器无法使用")
|
||||
elif rc == 4:
|
||||
# 错误的用户名或密码
|
||||
print_error_msg("错误的用户名或密码")
|
||||
elif rc == 5:
|
||||
# 未经授权
|
||||
print_error_msg("未经授权")
|
||||
|
||||
#获取线程类 (class_comm_mqtt_thread)
|
||||
mqtt_thread : class_comm_mqtt_thread= userdata
|
||||
unique_object : class_comm_mqtt_interface = None
|
||||
|
||||
#遍历所有unique_object, 通知其 on_connect 事件
|
||||
for unique_object in mqtt_thread.unique_object_dict.values() :
|
||||
if isinstance(unique_object, list) : #unique_object 可能是列表, 所以需要遍历
|
||||
for each_object in unique_object:
|
||||
if hasattr(each_object, "on_connect") :
|
||||
each_object.on_connect(mqtt_thread, userdata, flags, rc)
|
||||
elif hasattr(unique_object, "on_connect") :
|
||||
unique_object.on_connect(mqtt_thread, userdata, flags, rc)
|
||||
|
||||
#mqtt接收到主题, 通过主题中包含的 unique_name, 定位到 uniuqe_object, 并调用 unique_object.on_message 函数
|
||||
def mqtt_on_message(client, userdata, message):
|
||||
#print("mqtt message:", message.topic, message.payload.decode("utf-8"))
|
||||
|
||||
#获取线程类 (class_comm_mqtt_thread)
|
||||
mqtt_thread : class_comm_mqtt_thread= userdata
|
||||
|
||||
unique_object : class_comm_mqtt_interface = None
|
||||
for unique_name, search_unique_object in mqtt_thread.unique_object_dict.items() :
|
||||
if unique_name in message.topic :
|
||||
unique_object = search_unique_object
|
||||
break
|
||||
|
||||
#mqtt线程本身无法处理对应的主题消息, 由mqtt 所对应的unique_object处理
|
||||
if unique_object != None :
|
||||
if isinstance(unique_object, list) : #unique_object 可能是列表, 所以需要遍历
|
||||
for each_object in unique_object:
|
||||
if hasattr(each_object, "on_message") :
|
||||
each_object.on_message(mqtt_thread, message.topic, message.payload)
|
||||
elif hasattr(unique_object, "on_message") :
|
||||
unique_object.on_message(mqtt_thread, message.topic, message.payload)
|
||||
|
||||
class class_comm_mqtt_thread(Thread):
|
||||
def __init__(self, user_name = "admin", password = "admin") :
|
||||
Thread.__init__(self)
|
||||
self.client = None
|
||||
|
||||
self.subscribe_list = []
|
||||
self.publish_list = []
|
||||
self.publish_list_lock = threading.Lock()
|
||||
self.condition = threading.Condition()
|
||||
self.stop_request = False
|
||||
|
||||
self.server = "127.0.0.1"
|
||||
self.port = 1883
|
||||
self.user_name = user_name
|
||||
self.password = password
|
||||
self.keepalive = 60
|
||||
|
||||
self.unique_object_dict = {} #key = unique_name, value = device_object
|
||||
return
|
||||
|
||||
#unique_object: 为unique_object_subscribe_name对应的object, 在回调
|
||||
def add_unique_object(self, unique_name : string, unique_object : class_comm_mqtt_interface) :
|
||||
self.unique_object_dict[unique_name] = unique_object
|
||||
|
||||
#topic 中 需要包含
|
||||
def subscribe(self, topic : string) :
|
||||
if self.is_connect() and self.client:
|
||||
if topic not in self.subscribe_list :
|
||||
self.subscribe_list.append(topic)
|
||||
self.client.subscribe(topic)
|
||||
|
||||
def set_mqtt_server(self, server = "127.0.0.1", port = 1883, keep_alive = 60.0, user_name = "admin", password = "admin") :
|
||||
self.server = server
|
||||
self.port = port
|
||||
self.user_name = user_name
|
||||
self.password = password
|
||||
self.keepalive = keep_alive
|
||||
|
||||
#用于判断 mqtt_thread是否已经连接
|
||||
def is_connect(self) :
|
||||
if self.client == None :
|
||||
return False
|
||||
return self.client.is_connected()
|
||||
|
||||
def open(self):
|
||||
try :
|
||||
self.client = mqtt.Client()
|
||||
self.client.user_data_set(self)
|
||||
self.client.on_connect = mqtt_on_connect
|
||||
self.client.on_message = mqtt_on_message
|
||||
self.client.username_pw_set(self.user_name, self.password)
|
||||
self.client.connect(self.server, self.port, self.keepalive)
|
||||
except Exception as e :
|
||||
print_error_msg(str(e) + "mqtt_server: ip=%s, port = %d"%(self.server, self.port))
|
||||
if self.client: # 如果self.client已经被初始化了,则断开连接
|
||||
self.client.disconnect()
|
||||
self.client = None
|
||||
return None # 添加返回语句,告知调用者连接失败
|
||||
return self.client
|
||||
|
||||
def close(self):
|
||||
self.stop_request = True
|
||||
|
||||
def publish(self, topic, message) :
|
||||
if self.is_connect :
|
||||
self.publish_list_lock.acquire()
|
||||
self.publish_list.append([topic, message])
|
||||
self.publish_list_lock.release()
|
||||
|
||||
self.condition.acquire()
|
||||
self.condition.notify()
|
||||
self.condition.release()
|
||||
return
|
||||
|
||||
def publish_wait(self, topic, message, timeout) :
|
||||
if self.is_connect :
|
||||
self.publish_list_lock.acquire()
|
||||
self.publish_list.insert(0, [topic, message])
|
||||
self.publish_list_lock.release()
|
||||
self.condition.acquire()
|
||||
self.condition.notify()
|
||||
self.condition.release()
|
||||
return
|
||||
|
||||
def run(self):
|
||||
while self.stop_request == False :
|
||||
print_warning_msg("mqtt 线程启动, 服务器端口:server = %s:%d"%(self.server, self.port))
|
||||
|
||||
wait_open_timeout = 0
|
||||
self.subscribe_list = [] #取消订阅列表, 连接后重新订阅
|
||||
|
||||
while self.client == None and self.stop_request == False:
|
||||
if wait_open_timeout == 0 :
|
||||
print_warning_msg("mqtt连接中, 服务器端口:server = %s:%d"%(self.server, self.port))
|
||||
self.open()
|
||||
|
||||
if self.client == None :
|
||||
time.sleep(0.1)
|
||||
wait_open_timeout += 0.1
|
||||
if wait_open_timeout >= 5.0 :
|
||||
wait_open_timeout = 0
|
||||
|
||||
time.sleep(0.2)
|
||||
|
||||
if self.client :
|
||||
self.client.loop_start()
|
||||
time.sleep(0.2)
|
||||
|
||||
while self.stop_request == False and self.client.is_connected() :
|
||||
topic = None
|
||||
topic_message = None
|
||||
|
||||
self.publish_list_lock.acquire()
|
||||
if len(self.publish_list) > 0 :
|
||||
topic_message = self.publish_list.pop(0)
|
||||
topic = topic_message[0]
|
||||
message = topic_message[1]
|
||||
self.publish_list_lock.release()
|
||||
|
||||
if topic != None and message != None :
|
||||
self.client.publish(topic, message)
|
||||
|
||||
self.condition.acquire()
|
||||
if len(self.publish_list) == 0:
|
||||
self.condition.wait(timeout = 0.1)
|
||||
self.condition.release()
|
||||
|
||||
self.client.loop_stop()
|
||||
self.client.disconnect()
|
||||
self.client = None
|
||||
|
||||
print_warning_msg("mqtt连接断开, 准备重启mqtt连接")
|
||||
print_error_msg("mqtt 线程停止")
|
||||
|
||||
if __name__ == "__main__":
|
||||
object_mqtt1 = class_comm_mqtt_interface("object1 handler")
|
||||
object_mqtt2 = class_comm_mqtt_interface("object2 handler")
|
||||
global_mqtt_thread = class_comm_mqtt_thread()
|
||||
global_mqtt_thread.set_mqtt_server(server = "127.0.0.1", port = 1883, keep_alive = 60, user_name="admin", password="admin")
|
||||
global_mqtt_thread.add_unique_object("object1", object_mqtt1)
|
||||
global_mqtt_thread.add_unique_object("object2", object_mqtt2)
|
||||
global_mqtt_thread.start()
|
||||
Reference in New Issue
Block a user