|
@@ -0,0 +1,323 @@
|
|
|
+# -*- coding: utf-8 -*-
|
|
|
+# @Author: privacy
|
|
|
+# @Date: 2024-06-20 11:40:45
|
|
|
+# @Last Modified by: privacy
|
|
|
+# @Last Modified time: 2024-06-24 14:54:31
|
|
|
+from abc import ABC, abstractmethod
|
|
|
+import logging
|
|
|
+from queue import Queue
|
|
|
+
|
|
|
+import paho.mqtt.client as mqtt
|
|
|
+
|
|
|
+
|
|
|
+class ReflexArc(ABC):
|
|
|
+ """反射弧类"""
|
|
|
+ def __init__(self):
|
|
|
+ pass
|
|
|
+
|
|
|
+ @abstractmethod
|
|
|
+ def receptor(self):
|
|
|
+ """感受器
|
|
|
+ """
|
|
|
+ pass
|
|
|
+
|
|
|
+ @abstractmethod
|
|
|
+ def neure(self):
|
|
|
+ """神经元
|
|
|
+ """
|
|
|
+ pass
|
|
|
+
|
|
|
+ @abstractmethod
|
|
|
+ def effector(self):
|
|
|
+ """效应器,
|
|
|
+ """
|
|
|
+ pass
|
|
|
+
|
|
|
+
|
|
|
+class MqttCell(ReflexArc):
|
|
|
+ def __init__(self):
|
|
|
+ super().__init__()
|
|
|
+ self.client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2)
|
|
|
+
|
|
|
+ def on_connect(self, userdata, flags, reason_code, properties):
|
|
|
+ if reason_code.is_failure:
|
|
|
+ print(f"Failed to connect: {reason_code}. loop_forever() will retry connection")
|
|
|
+ else:
|
|
|
+ self.client.subscribe("test")
|
|
|
+
|
|
|
+ def receptor(self):
|
|
|
+ """感受器
|
|
|
+ """
|
|
|
+ self.client.on_connect = on_connect
|
|
|
+
|
|
|
+ def nerue(self):
|
|
|
+ pass
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+class MqttClient(object):
|
|
|
+ """发布订阅类"""
|
|
|
+ def __init__(self, mqtt_host: str = "localhost", mqtt_port: int = 1883, mqtt_keepalive: int = 60):
|
|
|
+ super(MqttClient, self).__init__()
|
|
|
+ self.client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2)
|
|
|
+ self.client.on_connect = self.on_connect
|
|
|
+ self.client.on_message = self.on_message
|
|
|
+ self.client.username_message = self.username_message
|
|
|
+ self.client.on_publish = self.on_publish
|
|
|
+ self.client.connect(mqtt_host, mqtt_port, mqtt_keepalive) # 600 为 keepalive 的时间间隔
|
|
|
+ self.client.loop_forever() # 保持连接
|
|
|
+
|
|
|
+ def on_connect(self, userdata, flags, rc):
|
|
|
+ """连接主题(成功,失败)都会调用此函数
|
|
|
+ @userdata => 在Client()或userdata_set()中设置的私有用户数据
|
|
|
+ @flags => 代理发送的响应标志
|
|
|
+ @rc => 连接结果
|
|
|
+ 0:连接成功
|
|
|
+ 1:连接被拒绝-协议版本不正确
|
|
|
+ 2:连接被拒绝-客户端标识符无效
|
|
|
+ 3:连接被拒绝-服务器不可用
|
|
|
+ 4:连接被拒绝-用户名或密码错误
|
|
|
+ 5:连接被拒绝-未授权
|
|
|
+ @reasonCode => mqttv5.0原因码:reasonCode类的实例。
|
|
|
+ @properties => 从代理返回的mqttv5.0属性
|
|
|
+ """
|
|
|
+ print("Connected with result code: " + str(rc))
|
|
|
+ # 订阅
|
|
|
+ self.client.subscribe("mqtt11")
|
|
|
+
|
|
|
+ def on_subscribe(self, userdata, mid, granted_qos):
|
|
|
+ """订阅回调
|
|
|
+ @mid => 匹配从相应的subscribe()调用
|
|
|
+ @grated_qos => 给出代理的qos级别的整数列表,为每个不同的订阅请求授予。
|
|
|
+ """
|
|
|
+ print("On Subscribed: qos = %d" % granted_qos)
|
|
|
+ pass
|
|
|
+
|
|
|
+ def on_message(self, userdata, msg):
|
|
|
+ """消息回调
|
|
|
+ @msg => MQTTMessage的实例。这是一个包含成员主题、负载、qos和保留的类
|
|
|
+ 使用message_callback_add()定义将调用的多个回调,用于特定主题筛选器
|
|
|
+ """
|
|
|
+ print("on_message topic:" + msg.topic + " message:" + str(msg.payload.decode('utf-8')))
|
|
|
+
|
|
|
+ def message_callback_add(self, sub, callback):
|
|
|
+ """注册特定主题消息回调
|
|
|
+ @sub => sub即subscribe, 也就是client.subscribe() 方法中的订阅的topic,可以是通配符匹配订阅
|
|
|
+ @callback => 自定义回调函数,回调参数与on_message()相同即可,参数的意义也是一样的。
|
|
|
+ """
|
|
|
+ pass
|
|
|
+
|
|
|
+ def username_message(self, userdata, msg):
|
|
|
+ """自定义回调函数
|
|
|
+ """
|
|
|
+ print("username_message topic:" + msg.topic)
|
|
|
+
|
|
|
+ def message_callback_remove(self, sub):
|
|
|
+ """删除注册的特定回调
|
|
|
+ """
|
|
|
+ pass
|
|
|
+
|
|
|
+ def on_publish(self, userdata, mid):
|
|
|
+ """发布消息
|
|
|
+ @mid => 匹配从相应的publish()调用,以允许跟踪传出消息。
|
|
|
+ """
|
|
|
+ print("On onPublish: qos = %d" % mid)
|
|
|
+ # self.client.publish(topic='mqtt11', payload='amazing', qos=0, retain=False)
|
|
|
+
|
|
|
+ def on_unsubscribe(self, userdata, mid):
|
|
|
+ """取消订阅
|
|
|
+ @mid => 匹配从相应的unsubscribe()调用。
|
|
|
+ """
|
|
|
+ print("On unSubscribed: qos = %d" % mid)
|
|
|
+ pass
|
|
|
+
|
|
|
+ def on_disconnect(self, userdata, rc):
|
|
|
+ """断开链接
|
|
|
+ @rc => 断开连接的结果
|
|
|
+ """
|
|
|
+ print("Unexpected disconnection rc = " + str(rc))
|
|
|
+ pass
|
|
|
+
|
|
|
+ def on_socket_open(self, userdata, socket):
|
|
|
+ """套接字打开
|
|
|
+ @socket => 刚打开的socket
|
|
|
+ """
|
|
|
+ pass
|
|
|
+
|
|
|
+ def on_socket_close(self, userdata, socket):
|
|
|
+ """套接字关闭
|
|
|
+ """
|
|
|
+ pass
|
|
|
+
|
|
|
+ def on_socket_register_write(self, userdata, socket):
|
|
|
+ """套接字写入
|
|
|
+ """
|
|
|
+ pass
|
|
|
+
|
|
|
+ def on_socket_unregister_write(self, userdata, socket):
|
|
|
+ """套接字注销写入
|
|
|
+ """
|
|
|
+ pass
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+class Neuro(object):
|
|
|
+ def __init__(self):
|
|
|
+ super(Neuro, self).__init__()
|
|
|
+
|
|
|
+ def run(self):
|
|
|
+ pass
|
|
|
+
|
|
|
+
|
|
|
+class Brain(object):
|
|
|
+ def __init__(self):
|
|
|
+ super(Brain, self).__init__()
|
|
|
+
|
|
|
+ def run(self):
|
|
|
+ pass
|
|
|
+
|
|
|
+
|
|
|
+class Texture(MqttClient):
|
|
|
+ def __init__(self):
|
|
|
+ super().__init__()
|
|
|
+
|
|
|
+ def run(self):
|
|
|
+ self.client.publish(topic='mqtt11', payload='amazing', qos=0, retain=False)
|
|
|
+
|
|
|
+
|
|
|
+class Version(object):
|
|
|
+ def __init__(self):
|
|
|
+ super(Version, self).__init__()
|
|
|
+
|
|
|
+ def run(self, src: str = 'udp://127.0.0.1:5600', dst: str = 'rtmp://192.168.1.150:1935/hls/test'):
|
|
|
+ process = (
|
|
|
+ ffmpeg
|
|
|
+ .input(
|
|
|
+ src
|
|
|
+ )
|
|
|
+ .output(
|
|
|
+ dst,
|
|
|
+ c='copy',
|
|
|
+ format='flv',
|
|
|
+ )
|
|
|
+ .run_async(pipe_stdout=True, pipe_stderr=True)
|
|
|
+ )
|
|
|
+ stdout, stderr = process.communicate()
|
|
|
+ print(stdout.decode())
|
|
|
+ print(stderr.decode())
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+import datetime
|
|
|
+import functools
|
|
|
+import json
|
|
|
+import time
|
|
|
+import traceback
|
|
|
+import paho.mqtt.client as mqclient
|
|
|
+import threading
|
|
|
+from dataclasses import dataclass
|
|
|
+
|
|
|
+@dataclass
|
|
|
+class MQTTClientInfoX:
|
|
|
+ brokerIP: str
|
|
|
+ brokerPort: int
|
|
|
+ clientId: str
|
|
|
+ user: str
|
|
|
+ pwd: str
|
|
|
+
|
|
|
+
|
|
|
+class SimpleMqttClientTest(threading.Thread):
|
|
|
+ def __init__(self, mqttClientInfo: MQTTClientInfoX, clientId):
|
|
|
+ threading.Thread.__init__(self, name="mqttElevClient_{}".format(time.time()))
|
|
|
+ self.mqsCI = mqttClientInfo
|
|
|
+ self.connectedCB = None
|
|
|
+ self.disconnectedCB = None
|
|
|
+ self.mqttMsgRecvCB = None
|
|
|
+ self.keepAliveInterval = None
|
|
|
+ self.clientId = clientId
|
|
|
+ self._isConnected = False
|
|
|
+ self.sn = 1
|
|
|
+
|
|
|
+ def setKeepAlive(self, keepAliveInterval: int):
|
|
|
+ self.keepAliveInterval = keepAliveInterval
|
|
|
+
|
|
|
+ def publishE(self, topic, payload, qos=0, retain=False):
|
|
|
+ self.clientConn.publish(topic, payload, qos=qos, retain=False)
|
|
|
+
|
|
|
+ def setCallback(self, connectedCB, un, mqttMsgRecvCB):
|
|
|
+ self.on_subscribe = connectedCB
|
|
|
+ self.mqttMsgRecvCB = mqttMsgRecvCB
|
|
|
+
|
|
|
+ def on_connect(self, client, userdata, flags, rc):
|
|
|
+ """一旦连接成功, 回调此方法"""
|
|
|
+ rc_status = ["连接成功", "协议版本不正确", "客户端标识符无效", "服务器不可用", "用户名或密码不正确", "未经授权"]
|
|
|
+ print("connect:", rc_status[rc])
|
|
|
+
|
|
|
+ def run(self):
|
|
|
+ self.startClient(self.clientId)
|
|
|
+
|
|
|
+ def startClient(self, clientId):
|
|
|
+
|
|
|
+ print("starting mqttElevClient...")
|
|
|
+ self.clientConn = mqclient.Client(client_id=clientId, clean_session=False)
|
|
|
+ self.clientConn.username_pw_set(self.mqsCI.user, self.mqsCI.pwd)
|
|
|
+ print("MQTT u:p -> {}:{}".format(self.mqsCI.user, '*' * len(self.mqsCI.pwd)))
|
|
|
+
|
|
|
+ self.clientConn.on_connect = functools.partial(self.on_connect)
|
|
|
+ self.clientConn.on_subscribe = functools.partial(self.on_subscribe)
|
|
|
+ self.clientConn.on_message = functools.partial(self.mqttMsgRecvCB)
|
|
|
+ # self.clientConn.on_disconnect = functools.partial(self.on_disconnect)
|
|
|
+ # self.clientConn.on_log = functools.partial(self.on_log)
|
|
|
+ keepAliveTime = 30 if self.keepAliveInterval is None or self.keepAliveInterval < 0 else self.keepAliveInterval
|
|
|
+
|
|
|
+ # -----------------------------------------------------------------------------
|
|
|
+ while True:
|
|
|
+ try:
|
|
|
+ print(" connecting to MQTT broker: {}:{}".format(self.mqsCI.brokerIP, self.mqsCI.brokerPort))
|
|
|
+ self.clientConn.connect(self.mqsCI.brokerIP, self.mqsCI.brokerPort, keepAliveTime)
|
|
|
+ break
|
|
|
+ except Exception as e:
|
|
|
+ # traceback.print_exc()
|
|
|
+ print('startClient :{}'.format(e))
|
|
|
+ time.sleep(5)
|
|
|
+ self.clientConn.loop_forever()
|
|
|
+
|
|
|
+
|
|
|
+def mqttMsgRecvCB(client, userdata, msg):
|
|
|
+ try:
|
|
|
+ mqttMsg = json.loads(msg.payload.decode('utf-8'))
|
|
|
+ print('recv mqttMsg:{}'.format(mqttMsg))
|
|
|
+ except Exception as e:
|
|
|
+ print("mqttMsgRecvCB:{}".format(e))
|
|
|
+
|
|
|
+
|
|
|
+def connectedCB(client, userdata, topic):
|
|
|
+ sub_topic1 = topic
|
|
|
+ client.subscribe(sub_topic1)
|
|
|
+ print('connectedCB subscribe ==> {}'.format(sub_topic1))
|
|
|
+
|
|
|
+
|
|
|
+if __name__ == '__main__':
|
|
|
+ brokerIP = '127.0.0.1'
|
|
|
+ brokerPort = 1883
|
|
|
+ clientId = 'mq_test1'
|
|
|
+ user = 'hangge'
|
|
|
+ pwd = '123'
|
|
|
+ topic = '/demo/test/1'
|
|
|
+
|
|
|
+ mqCI = MQTTClientInfoX(brokerIP, brokerPort, clientId, user, pwd)
|
|
|
+ mqttClient = SimpleMqttClientTest(mqCI, clientId)
|
|
|
+ mqttClient.setCallback(functools.partial(connectedCB, topic=topic), None, mqttMsgRecvCB)
|
|
|
+ mqttClient.setKeepAlive(30)
|
|
|
+ mqttClient.start()
|
|
|
+
|
|
|
+ # while 1:
|
|
|
+ # try:
|
|
|
+ # time.sleep(1)
|
|
|
+ # cmd = {"sn": 10001, "t": datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), "f": 3, "p1": 120, }
|
|
|
+ # cmd_s = json.dumps(cmd)
|
|
|
+ # mqttClient.publishE(topic, payload=cmd_s, qos=0, retain=False)
|
|
|
+ # except Exception as e:
|
|
|
+ # print(e)
|