From 5fe703946fa7bd708e58039980a84a13cf28de59 Mon Sep 17 00:00:00 2001 From: xiaohuozi <1093565302@qq.com> Date: Thu, 11 Jul 2024 20:43:43 +0800 Subject: [PATCH] mqtt push --- icons/Mqtt_A.png | Bin 0 -> 16159 bytes plugins/mqttpush/__init__.py | 291 +++++++++++++++++++++++++++++++++++ 2 files changed, 291 insertions(+) create mode 100755 icons/Mqtt_A.png create mode 100755 plugins/mqttpush/__init__.py diff --git a/icons/Mqtt_A.png b/icons/Mqtt_A.png new file mode 100755 index 0000000000000000000000000000000000000000..ccbf11b8a0426f430d9ccf7b505ee9af247fbd9b GIT binary patch literal 16159 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 literal 0 HcmV?d00001 diff --git a/plugins/mqttpush/__init__.py b/plugins/mqttpush/__init__.py new file mode 100755 index 0000000..28d1d8a --- /dev/null +++ b/plugins/mqttpush/__init__.py @@ -0,0 +1,291 @@ +import json +import paho.mqtt.client as mqtt + +from typing import Any, List, Dict, Tuple + +from app.core.event import eventmanager, Event +from app.log import logger +from app.plugins import _PluginBase +from app.schemas.types import EventType, NotificationType + +class MqttClient: + + def __init__(self, broker: str, port: int, topic: str, username: str = None, password: str = None): + self._broker = broker + self._port = port + self._topic = topic + self._username = username + self._password = password + self._client = mqtt.Client() + if username and password: + self._client.username_pw_set(username, password) + self._client.connect(broker, port, 60) + + def send(self, message: str, qos: int = 0, retain: bool = False): + result = self._client.publish(self._topic, message, qos, retain) + return result + +class MqttMsg(_PluginBase): + # 插件名称 + plugin_name = "MQTT 消息通知" + # 插件描述 + plugin_desc = "支持使用 MQTT 发送消息通知。" + # 插件图标 + plugin_icon = "Mqtt_A.png" + # 插件版本 + plugin_version = "1.0" + # 插件作者 + plugin_author = "lethargicScribe" + # 作者主页 + author_url = "https://github.com/lethargicScribe" + # 插件配置项ID前缀 + plugin_config_prefix = "mqttmsg_" + # 加载顺序 + plugin_order = 27 + # 可使用的用户级别 + auth_level = 1 + + # 私有属性 + _enabled = False + _broker = None + _port = None + _topic = None + _username = None + _password = None + _msgtypes = [] + + def init_plugin(self, config: dict = None): + if config: + self._enabled = config.get("enabled") + self._msgtypes = config.get("msgtypes") or [] + self._broker = config.get("broker") + self._port = config.get("port") + self._topic = config.get("topic") + self._username = config.get("username") + self._password = config.get("password") + + def get_state(self) -> bool: + return self._enabled and (True if self._broker and self._port and self._topic else False) + + @staticmethod + def get_command() -> List[Dict[str, Any]]: + pass + + def get_api(self) -> List[Dict[str, Any]]: + pass + + def get_form(self) -> Tuple[List[dict], Dict[str, Any]]: + """ + 拼装插件配置页面,需要返回两块数据:1、页面配置;2、数据结构 + """ + MsgTypeOptions = [] + for item in NotificationType: + MsgTypeOptions.append({ + "title": item.value, + "value": item.name + }) + return [ + { + 'component': 'VForm', + 'content': [ + { + 'component': 'VRow', + 'content': [ + { + 'component': 'VCol', + 'props': { + 'cols': 12, + 'md': 6 + }, + 'content': [ + { + 'component': 'VSwitch', + 'props': { + 'model': 'enabled', + 'label': '启用插件', + } + } + ] + } + ] + }, + { + 'component': 'VRow', + 'content': [ + { + 'component': 'VCol', + 'props': { + 'cols': 12, + 'md': 6 + }, + 'content': [ + { + 'component': 'VTextField', + 'props': { + 'model': 'broker', + 'label': 'MQTT Broker', + 'placeholder': 'broker.example.com', + } + } + ] + }, + { + 'component': 'VCol', + 'props': { + 'cols': 12, + 'md': 6 + }, + 'content': [ + { + 'component': 'VTextField', + 'props': { + 'model': 'port', + 'label': '端口', + 'placeholder': '1883', + } + } + ] + }, + { + 'component': 'VCol', + 'props': { + 'cols': 12, + 'md': 6 + }, + 'content': [ + { + 'component': 'VTextField', + 'props': { + 'model': 'topic', + 'label': '主题', + 'placeholder': 'example/topic', + } + } + ] + }, + { + 'component': 'VCol', + 'props': { + 'cols': 12, + 'md': 6 + }, + 'content': [ + { + 'component': 'VTextField', + 'props': { + 'model': 'username', + 'label': '用户名', + 'placeholder': 'mqttuser', + } + } + ] + }, + { + 'component': 'VCol', + 'props': { + 'cols': 12, + 'md': 6 + }, + 'content': [ + { + 'component': 'VTextField', + 'props': { + 'model': 'password', + 'label': '密码', + 'placeholder': 'mqttpassword', + } + } + ] + } + ] + }, + { + 'component': 'VRow', + 'content': [ + { + 'component': 'VCol', + 'props': { + 'cols': 12 + }, + 'content': [ + { + 'component': 'VSelect', + 'props': { + 'multiple': True, + 'chips': True, + 'model': 'msgtypes', + 'label': '消息类型', + 'items': MsgTypeOptions + } + } + ] + } + ] + }, + ] + } + ], { + "enabled": False, + 'msgtypes': [], + 'broker': 'broker.example.com', + 'port': 1883, + 'topic': 'example/topic', + 'username': '', + 'password': '', + } + + def get_page(self) -> List[dict]: + pass + + @eventmanager.register(EventType.NoticeMessage) + def send(self, event: Event): + """ + 消息发送事件 + """ + if not self.get_state(): + return + + if not event.event_data: + return + + msg_body = event.event_data + # 渠道 + channel = msg_body.get("channel") + if channel: + return + # 类型 + msg_type: NotificationType = msg_body.get("type") + # 标题 + title = msg_body.get("title") + # 文本 + text = msg_body.get("text") + + if not title and not text: + logger.warn("标题和内容不能同时为空") + return + + if (msg_type and self._msgtypes + and msg_type.name not in self._msgtypes): + logger.info(f"消息类型 {msg_type.value} 未开启消息发送") + return + + try: + if not self._broker or not self._port or not self._topic: + return False, "参数未配置" + mqtt_client = MqttClient( + broker=self._broker, + port=self._port, + topic=self._topic, + username=self._username, + password=self._password + ) + mqtt_client.send(message=text) + + except Exception as msg_e: + logger.error(f"MQTT消息发送失败,错误信息:{str(msg_e)}") + + def stop_service(self): + """ + 退出插件 + """ + pass