shuhao před 5 měsíci
rodič
revize
4e644a0827

+ 1 - 0
package.json

@@ -33,6 +33,7 @@
     "jsts": "^2.9.3",
     "mitt": "^3.0.1",
     "moment": "^2.29.4",
+    "mqtt": "5.10.1",
     "normalize.css": "^8.0.1",
     "npm": "^9.2.0",
     "nprogress": "^0.2.0",

+ 1 - 0
src/api/config.js

@@ -23,6 +23,7 @@ module.exports = {
     //需要忽略成功提示的请求
     igSuccessUrl:[
         "update",
+        "autoFlow",
         "home",
         "get",
         "page",

+ 8 - 0
src/api/modules/home.js

@@ -4438,4 +4438,12 @@ module.exports = {
       })
     }
   },
+  startFightTask:{
+    url: config.base_url + "autoFlow/flightTasks/{farmId}",
+    type: "get",
+  },
+  getSampleShowTime:{
+    url: config.base_url + "autoFlow/getSampleShowTime",
+    type: "get",
+  }
 };

+ 85 - 0
src/mqtt/MqttClient.js

@@ -0,0 +1,85 @@
+import mqtt from 'mqtt';
+
+class MqttClient {
+  constructor(topics, onMessageCallback) {
+    // 固定参数
+    this.MQTT_MQTTIP = 'wss://ws.emqx.sysuimars.cn/mqtt';
+    this.MQTT_USERNAME = 'admin';
+    this.MQTT_PASSWORD = 'admin';
+    this.topics = topics; // 订阅的主题数组
+    this.onMessageCallback = onMessageCallback; // 接收数据的回调函数
+    this.client = null;
+  }
+
+  connect() {
+    const options = {
+      connectTimeout: 40000,
+      clientId: `clientid-${this.generateClientId()}`, // 生成唯一的客户端 ID
+      username: this.MQTT_USERNAME,
+      password: this.MQTT_PASSWORD,
+      clean: false
+    };
+
+    // 连接 MQTT
+    this.client = mqtt.connect(this.MQTT_MQTTIP, options);
+
+    // 监听连接成功事件
+    this.client.on('connect', () => {
+      console.log('连接成功');
+      this.subscribeToTopics(); // 订阅主题
+    });
+
+    // 监听消息事件
+    this.client.on('message', (topic, message) => {
+      this.onMessageCallback(topic, message.toString()); // 调用回调函数处理消息
+    });
+
+    // 监听重连事件
+    this.client.on('reconnect', (error) => {
+      console.log('正在重连...', error);
+    });
+
+    // 监听错误事件
+    this.client.on('error', (error) => {
+      console.log('连接失败...', error);
+    });
+  }
+
+  // 订阅主题
+  subscribeToTopics() {
+    if (this.topics && this.topics.length > 0) {
+      this.topics.forEach((topic) => {
+        this.client.subscribe(topic, (err) => {
+          if (!err) {
+            console.log(`订阅成功: ${topic}`);
+          } else {
+            console.log(`订阅失败: ${topic}`, err);
+          }
+        });
+      });
+    } else {
+      console.log('未提供订阅主题');
+    }
+  }
+
+  // 生成唯一的客户端 ID
+  generateClientId() {
+    const S4 = () => (((1 + Math.random()) * 0x10000) | 0).toString(32).substring(1);
+    return `${S4()}${S4()}-${S4()}-${S4()}-${S4()}-${S4()}${S4()}${S4()}`;
+  }
+
+  //取消订阅
+  unsubscribe() {
+    this.topics.forEach((topic) => {
+      this.client.unsubscribe(topic, (err) => {
+        if (!err) {
+          console.log(`订阅成功: ${topic}`);
+        } else {
+          console.log(`订阅失败: ${topic}`, err);
+        }
+      });
+    });
+  }
+}
+
+export default MqttClient;

+ 179 - 0
src/views/home/components/farmFightTask.vue

@@ -0,0 +1,179 @@
+<template>
+  <div v-if="currentTask" class="container">
+    <div  class="task-info">
+      <p class="task-name">当前任务: {{ currentTask.name }}</p>
+      <p class="status-message">{{ statusMsg }}</p>
+      <div class="progress-container">
+        <progress :value="list.length" :max="sum" class="custom-progress"></progress>
+        <span class="percentage">{{ (list.length / sum * 100).toFixed(2) }}%</span>
+      </div>
+      <button class="close-button" @click="closeTask">x</button>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import {ref, onMounted, onUnmounted} from 'vue';
+import MqttClient from '@/mqtt/MqttClient';
+import axios from 'axios';
+import {ElMessage, ElMessageBox} from "element-plus";
+import eventBus from "@/api/eventBus";
+let props = defineProps({
+  farmId:{
+    type:Number,
+    required:true
+  }
+})
+
+// 定义响应式状态
+const currentTask = ref(null);
+let list = ref([])
+let sum = ref(100)
+let statusMsg = ref('')
+
+let mqttClient = null;
+
+function onMqttMessage(topic, message) {
+  console.log('收到MQTT消息:', topic, message);
+  let data = JSON.parse(message)
+  if(data.status === "0"){
+    //待开始
+    getTask(data.task_id)
+    statusMsg.value = '待开始'
+  }else if(data.status === "2"){
+    statusMsg.value = '执行中'
+    getTask(data.task_id, data.status)
+  }else if(data.status === "5"){
+    //已完成
+    ElMessageBox.confirm(
+        '任务已完成?',
+        '提醒',
+        {
+          confirmButtonText: '确定',
+          type: 'success',
+        }
+    ).then(() => {
+      console.log('已完成');
+      currentTask.value = false;
+    }).catch(() => {
+      console.log('取消执行任务');
+    })
+  }
+}
+
+function getTask(taskId,status) {
+  //执行中
+  VE_API.home.getSampleShowTime({taskId}).then((res)=>{
+    currentTask.value = res.data.task
+    sum.value = res.data.sum
+    list.value = res.data.list
+    if(status === '2'){
+      changeShowStatus(list.value)
+    }
+  })
+}
+
+function changeShowStatus(list){
+  eventBus.emit('farmFightTask:changeShowStatus',list)
+}
+
+function closeTask() {
+  currentTask.value = null;
+  list.value = [];
+  sum.value = 100;
+  statusMsg.value = '';
+}
+
+// 组件挂载时,检查无人机和任务状态
+onMounted(() => {
+  mqttClient = new MqttClient([`farm/fight/task/${props.farmId}`],onMqttMessage);
+  mqttClient.connect();
+});
+
+onUnmounted(() => {
+  if(mqttClient) {
+    mqttClient.unsubscribe();
+  }
+});
+</script>
+
+<style scoped>
+.container {
+  width: 100%; /* 调整宽度 */
+  max-width: 400px; /* 添加最大宽度 */
+  margin: 20px auto; /* 水平居中并添加上下边距 */
+  background: #f4f4f4; /* 调整背景颜色为灰色系 */
+  padding: 20px; /* 添加内边距 */
+  border-radius: 8px; /* 添加圆角 */
+  box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); /* 添加阴影 */
+}
+
+.task-info {
+  text-align: center; /* 文本居中 */
+}
+
+.task-name {
+  font-size: 1.5em; /* 调整字体大小 */
+  margin-bottom: 10px; /* 添加下边距 */
+  color: #333; /* 调整字体颜色 */
+}
+
+.status-message {
+  font-size: 1.2em; /* 调整字体大小 */
+  margin-bottom: 20px; /* 添加下边距 */
+  color: #666; /* 调整字体颜色 */
+}
+
+.progress-container {
+  display: flex;
+  justify-content: space-between; /* 调整子元素间距 */
+  align-items: center;
+}
+
+.custom-progress {
+  width: 80%; /* 调整进度条宽度 */
+  height: 10px; /* 调整进度条高度 */
+  appearance: none; /* 移除默认样式 */
+  background-color: #ddd;
+  border-radius: 5px;
+}
+
+.custom-progress::-webkit-progress-bar {
+  background-color: #ddd;
+  border-radius: 5px;
+}
+
+.custom-progress::-webkit-progress-value {
+  background-color: #888; /* 调整进度条颜色为灰色系 */
+  border-radius: 5px;
+}
+
+.custom-progress::-moz-progress-bar {
+  background-color: #888; /* 调整进度条颜色为灰色系 */
+  border-radius: 5px;
+}
+
+.percentage {
+  font-size: 1em; /* 调整字体大小 */
+  color: #555; /* 调整字体颜色 */
+}
+
+.close-button {
+  position: absolute; /* 绝对定位 */
+  top: 10px; /* 调整关闭按钮位置 */
+  right: 10px; /* 调整关闭按钮位置 */
+  background-color: #ddd; /* 调整背景颜色 */
+  border: none; /* 去掉边框 */
+  border-radius: 50%; /* 圆形按钮 */
+  width: 24px; /* 调整按钮大小 */
+  height: 24px; /* 调整按钮大小 */
+  font-size: 1em; /* 调整字体大小 */
+  color: #555; /* 调整字体颜色 */
+  cursor: pointer; /* 改变鼠标悬停样式 */
+}
+
+.close-button:hover {
+  background-color: #ccc; /* 鼠标悬停时的背景颜色 */
+  color: #333; /* 鼠标悬停时的字体颜色 */
+}
+</style>

+ 27 - 1
src/views/home/components/homePage.vue

@@ -59,6 +59,9 @@
       <chart-box name="生态指标">
         <template #title-right>
           <tabs :list="ecologyObj.btnGroup" keyStr="生态指标" :active="activeKey"></tabs>
+          <div class="button-group">
+            <div class="button zb" @click="fightTask">一键飞巡</div>
+          </div>
         </template>
         <bar-chart
             class="bar-chart"
@@ -132,7 +135,7 @@
 </template>
 <script setup>
 import { ref, onMounted, onUnmounted } from "vue";
-import { ElMessage } from 'element-plus'
+import { ElMessage, ElMessageBox } from 'element-plus'
 import chartBox from "@/components/chartBox.vue";
 import tabs from "./tabs.vue";
 import LivePlayer from '@liveqing/liveplayer-v3'
@@ -290,6 +293,29 @@ const gybg = () => {
   });
 };
 
+const fightTask = ()=> {
+  ElMessageBox.confirm(
+      '是否确认执行一键飞巡任务?',
+      '提醒',
+      {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning',
+      }
+  ).then(() => {
+        VE_API.home.startFightTask({farmId:sessionStorage.getItem("farmId")}).then((res)=>{
+          if(res.code === 0){
+            ElMessage.success('一键飞巡成功')
+          }else{
+            ElMessage.error('一键飞巡失败')
+          }
+        })
+      })
+      .catch(() => {
+
+      })
+}
+
 const showVideo = ref(false)
 const flvURL = ref('')
 const converterId = ref('')

+ 12 - 1
src/views/home/index.vue

@@ -140,7 +140,10 @@
                 </div>
             </div>
         </div>
+
     </div>
+    <FarmFightTask class="farm-fight-task" :farmId="currentFarm.id"></FarmFightTask>
+
 </template>
 
 <script setup>
@@ -170,6 +173,8 @@ import compareDialog from "./album_compoents/compareDialog.vue";
 import album from "./album/index.vue";
 import PdfDialog from "../../components/PdfDialog";
 import StaticMapLayers from "@/components/static_map_change/Layers.js"
+import FarmFightTask from "./components/farmFightTask";
+
 let store = useStore();
 const components = {
     homePage,
@@ -178,7 +183,7 @@ const components = {
 };
 //当前农场
 const currentFarm = {
-    id: store.getters.userinfo.curFarmId,
+    id: sessionStorage.getItem("farmId"),
     name: store.getters.userinfo.curFarmName,
 };
 //当前区域
@@ -1074,4 +1079,10 @@ const photoList = ref([
         }
     }
 }
+.farm-fight-task{
+    position: fixed;
+    top: 100px;
+    left: 25%;
+    z-index: 1000;
+}
 </style>

+ 19 - 0
src/views/home/map/samplePointLayer.js

@@ -59,6 +59,19 @@ class SamplePointLayer {
       }
     })
 
+    this.figghtStatusStyle = vectorStyle.getPointSimpleStyle(5,"#eebd0a", "#f5efef", 1)
+    eventBus.on('farmFightTask:changeShowStatus',function(list){
+      if(that.features && that.features.length > 0){
+        that.features.forEach(item => {
+          let index =list.findIndex((geohash)=> geohash === item.get('geoHashSample'))
+          if(index!== -1){
+            item.set("showFightStatus", 1)
+          }
+        })
+        that.treeClusterLayer.layer.changed()
+      }
+    })
+
     // 果园档案
     that.fileLegend = []
     eventBus.off("change:mapPoint")
@@ -76,6 +89,7 @@ class SamplePointLayer {
     that.blueRegionLayer = null
     that.pointType = ""
     that.pointArr = []
+    that.features = []
 
 
     // 切换点位图标
@@ -87,6 +101,10 @@ class SamplePointLayer {
 
   }
   getIconStyle(feature) {
+    const showFightStatus = feature.get('showFightStatus')
+    if(showFightStatus){
+      return this.figghtStatusStyle
+    }
     const color = feature.get("color")
     const noImg = feature.get("noImg")
     const activeCompare = feature.get('activeCompare')
@@ -149,6 +167,7 @@ class SamplePointLayer {
       const source = new VectorSource({
         features: features,
       });
+      that.features = features
       that.clusterSource.setSource(source)
 
 

+ 174 - 13
yarn.lock

@@ -1017,6 +1017,11 @@
   dependencies:
     regenerator-runtime "^0.13.4"
 
+"@babel/runtime@^7.23.8", "@babel/runtime@^7.24.5":
+  version "7.27.6"
+  resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.6.tgz#ec4070a04d76bae8ddbb10770ba55714a417b7c6"
+  integrity sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q==
+
 "@babel/template@^7.0.0", "@babel/template@^7.16.7":
   version "7.16.7"
   resolved "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz"
@@ -3234,6 +3239,13 @@
   resolved "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz"
   integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==
 
+"@types/readable-stream@^4.0.0", "@types/readable-stream@^4.0.5":
+  version "4.0.21"
+  resolved "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-4.0.21.tgz#716558454a5e0c3c0651520f8154efc3288f59cb"
+  integrity sha512-19eKVv9tugr03IgfXlA9UVUVRbW6IuqRO5B92Dl4a6pT7K8uaGrNS0GkxiZD0BOk6PLuXl5FhWl//eX/pzYdTQ==
+  dependencies:
+    "@types/node" "*"
+
 "@types/retry@0.12.0":
   version "0.12.0"
   resolved "https://registry.npmmirror.com/@types/retry/-/retry-0.12.0.tgz"
@@ -3278,6 +3290,13 @@
   dependencies:
     "@types/node" "*"
 
+"@types/ws@^8.5.9":
+  version "8.18.1"
+  resolved "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz#48464e4bf2ddfd17db13d845467f6070ffea4aa9"
+  integrity sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==
+  dependencies:
+    "@types/node" "*"
+
 "@vant/popperjs@^1.3.0":
   version "1.3.0"
   resolved "https://registry.npmjs.org/@vant/popperjs/-/popperjs-1.3.0.tgz"
@@ -4468,6 +4487,16 @@ bl@^4.1.0:
     inherits "^2.0.4"
     readable-stream "^3.4.0"
 
+bl@^6.0.8:
+  version "6.1.0"
+  resolved "https://registry.npmjs.org/bl/-/bl-6.1.0.tgz#cc35ce7a2e8458caa8c8fb5deeed6537b73e4504"
+  integrity sha512-ClDyJGQkc8ZtzdAAbAwBmhMSpwN/sC9HA8jxdYm6nVUbCfZbe2mgza4qh7AuEYyEPB/c4Kznf9s66bnsKMQDjw==
+  dependencies:
+    "@types/readable-stream" "^4.0.0"
+    buffer "^6.0.3"
+    inherits "^2.0.4"
+    readable-stream "^4.2.0"
+
 bluebird@^3.1.1, bluebird@^3.5.0:
   version "3.7.2"
   resolved "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz"
@@ -5105,6 +5134,11 @@ commander@~2.19.0:
   resolved "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz"
   integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==
 
+commist@^3.2.0:
+  version "3.2.0"
+  resolved "https://registry.npmjs.org/commist/-/commist-3.2.0.tgz#da9c8e5f245ac21510badc4b10c46b5bcc9b56cd"
+  integrity sha512-4PIMoPniho+LqXmpS5d3NuGYncG6XWlkBSVGiWycL22dd42OYdUGil2CWuzklaJoNxyxUSpO4MKIBU94viWNAw==
+
 common-ancestor-path@^1.0.1:
   version "1.0.1"
   resolved "https://registry.npmjs.org/common-ancestor-path/-/common-ancestor-path-1.0.1.tgz"
@@ -5153,6 +5187,16 @@ concat-map@0.0.1:
   resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz"
   integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
 
+concat-stream@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz#414cf5af790a48c60ab9be4527d56d5e41133cb1"
+  integrity sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==
+  dependencies:
+    buffer-from "^1.0.0"
+    inherits "^2.0.3"
+    readable-stream "^3.0.2"
+    typedarray "^0.0.6"
+
 concaveman@^1.2.1:
   version "1.2.1"
   resolved "https://registry.npmjs.org/concaveman/-/concaveman-1.2.1.tgz"
@@ -5539,6 +5583,13 @@ debug@^3.1.1, debug@^3.2.6:
   dependencies:
     ms "^2.1.1"
 
+debug@^4.3.1:
+  version "4.4.1"
+  resolved "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz#e5a8bc6cbc4c6cd3e64308b0693a3d4fa550189b"
+  integrity sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==
+  dependencies:
+    ms "^2.1.3"
+
 decode-uri-component@^0.2.0:
   version "0.2.2"
   resolved "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz"
@@ -6429,6 +6480,14 @@ fast-levenshtein@^2.0.6:
   resolved "https://registry.npmmirror.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz"
   integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==
 
+fast-unique-numbers@^8.0.13:
+  version "8.0.13"
+  resolved "https://registry.npmjs.org/fast-unique-numbers/-/fast-unique-numbers-8.0.13.tgz#3c87232061ff5f408a216e1f0121232f76f695d7"
+  integrity sha512-7OnTFAVPefgw2eBJ1xj2PGGR9FwYzSUso9decayHgCDX4sJkHLdcsYTytTg+tYv+wKF3U8gJuSBz2jJpQV4u/g==
+  dependencies:
+    "@babel/runtime" "^7.23.8"
+    tslib "^2.6.2"
+
 fast-uri@^3.0.1:
   version "3.0.6"
   resolved "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz"
@@ -7064,6 +7123,11 @@ he@1.2.x, he@^1.1.1, he@^1.2.0:
   resolved "https://registry.npmjs.org/he/-/he-1.2.0.tgz"
   integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
 
+help-me@^5.0.0:
+  version "5.0.0"
+  resolved "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz#b1ebe63b967b74060027c2ac61f9be12d354a6f6"
+  integrity sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==
+
 highcharts@^11.0.0:
   version "11.4.3"
   resolved "https://registry.npmjs.org/highcharts/-/highcharts-11.4.3.tgz"
@@ -7846,6 +7910,11 @@ js-message@1.0.7:
   resolved "https://registry.npmjs.org/js-message/-/js-message-1.0.7.tgz"
   integrity sha512-efJLHhLjIyKRewNS9EGZ4UpI8NguuL6fKkhRxVuMmrGV2xN/0APGdQYwLFky5w9naebSZ0OwAGp0G6/2Cg90rA==
 
+js-sdsl@4.3.0:
+  version "4.3.0"
+  resolved "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz#aeefe32a451f7af88425b11fdb5f58c90ae1d711"
+  integrity sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==
+
 js-tokens@^4.0.0:
   version "4.0.0"
   resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz"
@@ -8383,7 +8452,7 @@ lower-case@^2.0.2:
   dependencies:
     tslib "^2.0.3"
 
-lru-cache@^10.2.0:
+lru-cache@^10.0.1, lru-cache@^10.2.0:
   version "10.4.3"
   resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119"
   integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==
@@ -8720,6 +8789,11 @@ minimist@^1.1.0, minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6:
   resolved "https://registry.npmmirror.com/minimist/-/minimist-1.2.6.tgz"
   integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==
 
+minimist@^1.2.8:
+  version "1.2.8"
+  resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
+  integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
+
 minipass-collect@^1.0.2:
   version "1.0.2"
   resolved "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz"
@@ -8882,6 +8956,37 @@ mpd-parser@0.22.1, mpd-parser@^0.22.1:
     "@xmldom/xmldom" "^0.8.3"
     global "^4.4.0"
 
+mqtt-packet@^9.0.0:
+  version "9.0.2"
+  resolved "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-9.0.2.tgz#fe6ae2c36fe3f269d11b3fe663b53648f3b3700a"
+  integrity sha512-MvIY0B8/qjq7bKxdN1eD+nrljoeaai+qjLJgfRn3TiMuz0pamsIWY2bFODPZMSNmabsLANXsLl4EMoWvlaTZWA==
+  dependencies:
+    bl "^6.0.8"
+    debug "^4.3.4"
+    process-nextick-args "^2.0.1"
+
+mqtt@5.10.1:
+  version "5.10.1"
+  resolved "https://registry.npmjs.org/mqtt/-/mqtt-5.10.1.tgz#d4f45ffdd825bad331c18f08796a744dabbe16de"
+  integrity sha512-hXCOki8sANoQ7w+2OzJzg6qMBxTtrH9RlnVNV8panLZgnl+Gh0J/t4k6r8Az8+C7y3KAcyXtn0mmLixyUom8Sw==
+  dependencies:
+    "@types/readable-stream" "^4.0.5"
+    "@types/ws" "^8.5.9"
+    commist "^3.2.0"
+    concat-stream "^2.0.0"
+    debug "^4.3.4"
+    help-me "^5.0.0"
+    lru-cache "^10.0.1"
+    minimist "^1.2.8"
+    mqtt-packet "^9.0.0"
+    number-allocator "^1.0.14"
+    readable-stream "^4.4.2"
+    reinterval "^1.1.0"
+    rfdc "^1.3.0"
+    split2 "^4.2.0"
+    worker-timers "^7.1.4"
+    ws "^8.17.1"
+
 mrmime@^1.0.0:
   version "1.0.1"
   resolved "https://registry.npmmirror.com/mrmime/-/mrmime-1.0.1.tgz"
@@ -8897,7 +9002,7 @@ ms@2.1.2, ms@^2.0.0, ms@^2.1.1:
   resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz"
   integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
 
-ms@2.1.3, ms@^2.1.2:
+ms@2.1.3, ms@^2.1.2, ms@^2.1.3:
   version "2.1.3"
   resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz"
   integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
@@ -9324,6 +9429,14 @@ nth-check@^2.0.1:
   dependencies:
     boolbase "^1.0.0"
 
+number-allocator@^1.0.14:
+  version "1.0.14"
+  resolved "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz#1f2e32855498a7740dcc8c78bed54592d930ee4d"
+  integrity sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==
+  dependencies:
+    debug "^4.3.1"
+    js-sdsl "4.3.0"
+
 object-assign@^4.0.1, object-assign@^4.1.0:
   version "4.1.1"
   resolved "https://registry.npmmirror.com/object-assign/-/object-assign-4.1.1.tgz"
@@ -10261,7 +10374,7 @@ proc-log@^3.0.0:
   resolved "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz"
   integrity sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==
 
-process-nextick-args@~2.0.0:
+process-nextick-args@^2.0.1, process-nextick-args@~2.0.0:
   version "2.0.1"
   resolved "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz"
   integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
@@ -10556,25 +10669,25 @@ readable-stream@^2.3.6:
     string_decoder "~1.1.1"
     util-deprecate "~1.0.1"
 
-readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.4.0:
-  version "3.6.0"
-  resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz"
-  integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
+readable-stream@^3.0.2, readable-stream@^3.6.0:
+  version "3.6.2"
+  resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967"
+  integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==
   dependencies:
     inherits "^2.0.3"
     string_decoder "^1.1.1"
     util-deprecate "^1.0.1"
 
-readable-stream@^3.6.0:
-  version "3.6.2"
-  resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967"
-  integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==
+readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.4.0:
+  version "3.6.0"
+  resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz"
+  integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
   dependencies:
     inherits "^2.0.3"
     string_decoder "^1.1.1"
     util-deprecate "^1.0.1"
 
-readable-stream@^4.1.0:
+readable-stream@^4.1.0, readable-stream@^4.2.0, readable-stream@^4.4.2:
   version "4.7.0"
   resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz#cedbd8a1146c13dfff8dab14068028d58c15ac91"
   integrity sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==
@@ -10683,6 +10796,11 @@ regjsparser@^0.8.2:
   dependencies:
     jsesc "~0.5.0"
 
+reinterval@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz#3361ecfa3ca6c18283380dd0bb9546f390f5ece7"
+  integrity sha512-QIRet3SYrGp0HUHO88jVskiG6seqUGC5iAG7AwI/BV4ypGcuqk9Du6YQBUOUqm9c8pw1eyLoIaONifRua1lsEQ==
+
 relateurl@0.2.x, relateurl@^0.2.7:
   version "0.2.7"
   resolved "https://registry.npmmirror.com/relateurl/-/relateurl-0.2.7.tgz"
@@ -11485,6 +11603,11 @@ split-string@^3.0.1, split-string@^3.0.2:
   dependencies:
     extend-shallow "^3.0.0"
 
+split2@^4.2.0:
+  version "4.2.0"
+  resolved "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz#c9c5920904d148bab0b9f67145f245a86aadbfa4"
+  integrity sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==
+
 sprintf-js@^1.1.3:
   version "1.1.3"
   resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz#4914b903a2f8b685d17fdf78a70e917e872e444a"
@@ -12045,7 +12168,7 @@ tslib@2.3.0, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.0:
   resolved "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz"
   integrity sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==
 
-tslib@^2.8.1:
+tslib@^2.6.2, tslib@^2.8.1:
   version "2.8.1"
   resolved "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz"
   integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==
@@ -12160,6 +12283,11 @@ typedarray.prototype.slice@^1.0.3:
     typed-array-buffer "^1.0.2"
     typed-array-byte-offset "^1.0.2"
 
+typedarray@^0.0.6:
+  version "0.0.6"
+  resolved "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
+  integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==
+
 ufo@^1.1.1:
   version "1.1.1"
   resolved "https://registry.npmjs.org/ufo/-/ufo-1.1.1.tgz"
@@ -12975,6 +13103,34 @@ word-wrap@^1.2.3:
   resolved "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz"
   integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==
 
+worker-timers-broker@^6.1.8:
+  version "6.1.8"
+  resolved "https://registry.npmjs.org/worker-timers-broker/-/worker-timers-broker-6.1.8.tgz#08f64e5931b77fadc55f0c7388c077a7dd17e4c7"
+  integrity sha512-FUCJu9jlK3A8WqLTKXM9E6kAmI/dR1vAJ8dHYLMisLNB/n3GuaFIjJ7pn16ZcD1zCOf7P6H62lWIEBi+yz/zQQ==
+  dependencies:
+    "@babel/runtime" "^7.24.5"
+    fast-unique-numbers "^8.0.13"
+    tslib "^2.6.2"
+    worker-timers-worker "^7.0.71"
+
+worker-timers-worker@^7.0.71:
+  version "7.0.71"
+  resolved "https://registry.npmjs.org/worker-timers-worker/-/worker-timers-worker-7.0.71.tgz#f96138bafbcfaabea116603ce23956e05e76db6a"
+  integrity sha512-ks/5YKwZsto1c2vmljroppOKCivB/ma97g9y77MAAz2TBBjPPgpoOiS1qYQKIgvGTr2QYPT3XhJWIB6Rj2MVPQ==
+  dependencies:
+    "@babel/runtime" "^7.24.5"
+    tslib "^2.6.2"
+
+worker-timers@^7.1.4:
+  version "7.1.8"
+  resolved "https://registry.npmjs.org/worker-timers/-/worker-timers-7.1.8.tgz#f53072c396ac4264fd3027914f4ab793c92d90be"
+  integrity sha512-R54psRKYVLuzff7c1OTFcq/4Hue5Vlz4bFtNEIarpSiCYhpifHU3aIQI29S84o1j87ePCYqbmEJPqwBTf+3sfw==
+  dependencies:
+    "@babel/runtime" "^7.24.5"
+    tslib "^2.6.2"
+    worker-timers-broker "^6.1.8"
+    worker-timers-worker "^7.0.71"
+
 "wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
   version "7.0.0"
   resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
@@ -13046,6 +13202,11 @@ ws@^7.3.1:
   resolved "https://registry.npmmirror.com/ws/-/ws-7.5.8.tgz"
   integrity sha512-ri1Id1WinAX5Jqn9HejiGb8crfRio0Qgu8+MtL36rlTA6RLsMdWt1Az/19A2Qij6uSHUMphEFaTKa4WG+UNHNw==
 
+ws@^8.17.1:
+  version "8.18.2"
+  resolved "https://registry.npmjs.org/ws/-/ws-8.18.2.tgz#42738b2be57ced85f46154320aabb51ab003705a"
+  integrity sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ==
+
 ws@^8.4.2:
   version "8.8.0"
   resolved "https://registry.npmmirror.com/ws/-/ws-8.8.0.tgz"