UNIVPLMDataIntegration/Web/src/views/mqttx/index.vue
zuohuaijun 0188a41a63 😎代码优化
2024-08-04 00:55:52 +08:00

794 lines
25 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="mqtt-box">
<h1 class="header">MQTTX在线测试客户端</h1>
<el-card :model="connection">
<h1>连接参数(Configuration)</h1>
<el-form label-position="top" :model="connection">
<el-row :gutter="6">
<el-col :span="8">
<el-form-item prop="host" label="协议|主机|端口">
<el-input v-model="connection.host" :disabled="connSuccess" type="password" show-password>
<template #prepend>
<el-select v-model="connection.protocol" class="w80" :disabled="connSuccess" @change="handleProtocolChange">
<el-option label="ws://" value="ws"></el-option>
<el-option label="wss://" value="wss"></el-option>
</el-select>
</template>
<template #append>
<el-input v-model.number="connection.port" type="number" class="w80" :disabled="connSuccess" placeholder="8083/8084"></el-input>
</template>
</el-input>
</el-form-item>
</el-col>
<el-col :span="0">
<el-form-item prop="clientId" label="标识(Client ID)唯一性">
<el-input v-model="connection.clientId"> </el-input>
</el-form-item>
</el-col>
<el-col :span="0">
<el-form-item prop="username" label="账号(Username)">
<el-input v-model="connection.username"></el-input>
</el-form-item>
</el-col>
<el-col :span="0">
<el-form-item prop="password" label="密码(Password)">
<el-input v-model="connection.password" type="password" show-password></el-input>
</el-form-item>
</el-col>
<el-col :span="4">
<el-form-item prop="regpacket" label="设备包名(Regpacket)">
<el-input v-model="connection.repacket" :disabled="connSuccess" @input="syncdhtreg" @change="init_topic"></el-input>
</el-form-item>
</el-col>
<el-col :span="4">
<el-form-item prop="dhtRegpack" label="共享传感器(dhtRegpacket)">
<el-input v-model="connection.dhtRegpack" :disabled="connSuccess" @change="init_topic"></el-input>
</el-form-item>
</el-col>
<el-col :span="8" class="text-right">
<el-button
type="primary"
:icon="Setting"
class="sub-btn"
:disabled="client.connected"
@click="createConnection"
:loading="btnLoadingType === 'connect'"
:style="{ display: client.connected ? 'none' : '' }"
>
{{ client.connected ? '已连接(Connected)' : '连接(Connect)' }}
</el-button>
<el-button v-if="client.connected" class="sub-btn" type="warning" :icon="Discount" @click="destroyConnection" :loading="btnLoadingType === 'disconnect'"> 断开(Disconnect) </el-button>
</el-col>
</el-row>
</el-form>
</el-card>
<el-card shadow="hover">
<h1>订阅(Subscribe)</h1>
<el-form label-position="top" :model="subscription">
<el-row :gutter="6">
<el-col :span="12">
<el-form-item prop="topic" label="订阅主题(Topic)">
<el-input v-model="connection.subTopics" :disabled="subscribedSuccess" type="password" show-password></el-input>
</el-form-item>
</el-col>
<el-col :span="4">
<el-form-item prop="qos" label="订阅质量(QoS)">
<el-select v-model="subscription.qos" :disabled="subscribedSuccess">
<el-option v-for="qos in qosList" :key="qos" :label="qos == 0 ? '0 至多一次' : qos == 1 ? '1 至少一次' : '2 仅仅一次'" :value="qos"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8" class="text-right">
<el-button
type="primary"
:icon="Connection"
class="sub-btn"
:style="{ display: subscribedSuccess ? 'none' : '' }"
:loading="btnLoadingType === 'subscribe'"
:disabled="!client.connected || subscribedSuccess"
@click="doSubscribe"
>
{{ subscribedSuccess ? '已订阅(Subscribed)' : '订阅(Subscribe)' }}
</el-button>
<el-button v-if="subscribedSuccess" type="warning" :icon="Discount" class="sub-btn" :loading="btnLoadingType === 'unsubscribe'" :disabled="!client.connected" @click="doUnSubscribe">
取消(Unsubscribe)
</el-button>
</el-col>
</el-row>
</el-form>
</el-card>
<el-card shadow="hover">
<h1>发布(Publish)</h1>
<el-form label-position="top" :model="publish">
<el-row :gutter="6">
<el-col :span="8">
<el-form-item prop="topic" label="发布主题(Topic)">
<el-input v-model="connection.pubTopic" type="password" show-password></el-input>
</el-form-item>
</el-col>
<el-col :span="4">
<el-form-item prop="qos" label="发布质量(QoS)">
<el-select v-model="publish.qos">
<el-option v-for="qos in qosList" :key="qos" :label="qos == 0 ? '0 至多一次' : qos == 1 ? '1 至少一次' : '2 仅仅一次'" :value="qos"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="4">
<el-form-item prop="retain" label="发布保留(Retain)">
<el-select v-model="publish.retain">
<el-option value="false" label="false 不保留"></el-option>
<el-option value="true" label="true 不保留"></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="6">
<el-col :span="16">
<el-form-item prop="payload" label="操作指令(Payload)">
<el-input v-model="publish.payload" clearable maxlength="64" show-word-limit>
<!--<template #prepend>
<el-button :icon="Operation" />
</template> -->
<template #append>
<el-select v-model="publish.payload" placeholder="选择指令" style="width: 115px">
<el-option label="状态查询" value="55 AA AA AA AA 91 CF" />
<el-option label="全部打开" value="55 AA AA AA AA 81 A4 01" />
<el-option label="全部关闭" value="55 AA AA AA AA 81 A4 00" />
<el-option label="一路开关" value="55 AA AA AA AA 81 BA 01" />
<el-option label="二路开关" value="55 AA AA AA AA 81 BA 02" />
<el-option label="三路开关" value="55 AA AA AA AA 81 BA 03" />
<el-option label="四路开关" value="55 AA AA AA AA 81 BA 04" />
</el-select>
</template>
</el-input>
</el-form-item>
</el-col>
<el-col :span="8" class="text-right">
<el-button type="success" :icon="Position" class="sub-btn" :loading="btnLoadingType === 'publish'" :disabled="!client.connected" @click="doPublish(publish.payload, connection.pubTopic)">
发布(Publish)
</el-button>
</el-col>
</el-row>
</el-form>
</el-card>
<el-card shadow="hover">
<h1>
<el-button @click="clsmsg" type="success" :icon="Delete" title="点击清空历史记录">接收(Receive)</el-button>
<el-tag title="接收次数">收 {{ recvnum }}</el-tag>
<el-tag :title="dht_tm">{{ dht_wsd }}</el-tag>
<el-tag title="设备已工作时长">{{ parseInt(runSeconds) }} 秒</el-tag>
<el-button
type="success"
title="关闭一路"
:disabled="!connection.onlineStatus || !client.connected"
v-if="connection.ch1_Status"
icon="ele-Check"
id="ch1"
v-reclick="2000"
@click="switchLight('55 AA AA AA AA 81 01 00')"
>关闭</el-button
>
<el-button
type="warning"
title="打开一路"
:disabled="!connection.onlineStatus || !client.connected"
v-else="!connection.ch1_Status"
icon="ele-CloseBold"
id="ch1"
v-reclick="2000"
@click="switchLight('55 AA AA AA AA 81 01 01')"
>打开</el-button
>
<el-button
type="success"
title="关闭二路"
:disabled="!connection.onlineStatus || !client.connected"
v-if="connection.ch2_Status"
icon="ele-Check"
id="ch2"
v-reclick="2000"
@click="switchLight('55 AA AA AA AA 81 02 00')"
>关闭</el-button
>
<el-button
type="warning"
title="打开二路"
:disabled="!connection.onlineStatus || !client.connected"
v-else="!connection.ch2_Status"
icon="ele-CloseBold"
id="ch2"
v-reclick="2000"
@click="switchLight('55 AA AA AA AA 81 02 01')"
>打开</el-button
>
<el-button
type="success"
title="关闭三路"
:disabled="!connection.onlineStatus || !client.connected"
v-if="connection.ch3_Status"
icon="ele-Check"
id="ch3"
v-reclick="2000"
@click="switchLight('55 AA AA AA AA 81 03 00')"
>关闭</el-button
>
<el-button
type="warning"
title="打开三路"
:disabled="!connection.onlineStatus || !client.connected"
v-else="!connection.ch3_Status"
icon="ele-CloseBold"
id="ch3"
v-reclick="2000"
@click="switchLight('55 AA AA AA AA 81 03 01')"
>打开</el-button
>
<el-button
type="success"
title="关闭四路"
:disabled="!connection.onlineStatus || !client.connected"
v-if="connection.ch4_Status"
icon="ele-Check"
id="ch4"
v-reclick="2000"
@click="switchLight('55 AA AA AA AA 81 04 00')"
>关闭</el-button
>
<el-button
type="warning"
title="打开四路"
:disabled="!connection.onlineStatus || !client.connected"
v-else="!connection.ch4_Status"
icon="ele-CloseBold"
id="ch4"
v-reclick="2000"
@click="switchLight('55 AA AA AA AA 81 04 01')"
>打开</el-button
>
<el-button
type="danger"
title="四路全部关闭"
:disabled="!connection.onlineStatus || !client.connected"
v-if="connection.all_Status"
icon="ele-SwitchButton"
id="ch5"
@click="switchLight('55 AA AA AA AA 81 A4 00')"
>全关</el-button
>
<el-button
type="success"
title="四路全部打开"
:disabled="!connection.onlineStatus || !client.connected"
v-else="!connection.all_Status"
icon="ele-Switch"
id="ch5"
@click="switchLight('55 AA AA AA AA 81 A4 01')"
>全开</el-button
>
<el-alert v-if="!client.connected || !connection.onlineStatus" title="网络服务断开或设备离线!" center type="warning" effect="light" style="margin-top: 4px" />
</h1>
<!-- 绑定接收日志,只读 -->
<el-col :span="24">
<el-input type="textarea" :rows="8" id="recv" v-model="receivedMessages" readonly class="log"></el-input>
</el-col>
</el-card>
</div>
</template>
<script setup lang="ts" name="mqttx">
import { reactive, ref, onMounted, nextTick } from 'vue';
import { Search, ChatDotSquare, TopRight, Star, Operation, Setting, Connection, Discount, Open, Delete, Position } from '@element-plus/icons-vue';
import * as MQTT from 'mqtt/dist/mqtt.min'; // 针对4.3.7版本的引用方法5.7.x会提示错误 (import * as MQTT from "mqtt")
import mittBus from '/@/utils/mitt'; // 事件总线mitt 解决打包后错误Uncaught (in promise) ReferenceError: Cannot access 'oe' before initialization
// vue 3 + vite use MQTT.js refer to https://github.com/mqttjs/MQTT.js/issues/1269
// https://github.com/mqttjs/MQTT.js#qos
const qosList = [0, 1, 2]; // 质量
const now = new Date();
const recvnum = ref(0);
const dht_wd = ref(0); // 温度湿度
const dht_sd = ref(0);
const dht_tm = ref(''); // 同步时间
const dht_wsd = ref('温度0,湿度0%');
const runSeconds = ref(0); // 工作时长
// mqtt客户端变量 let或const
const client = ref({
connected: false, //未连接
} as MQTT.MqttClient);
const receivedMessages = ref('');
const subscribedSuccess = ref(false); //订阅成功标志
const connSuccess = ref(false); //连接成功标志
const btnLoadingType = ref('');
const retryTimes = ref(0); //重连次数
/**
* this demo uses EMQX Public MQTT Broker (https://www.emqx.com/en/mqtt/public-mqtt5-broker), here are the details:
* 参考https://github.com/emqx/MQTT-Client-Examples
* 方法https://github.com/mqttjs/MQTT.js
* Broker host: broker.emqx.io
* WebSocket port: 8083
* WebSocket over TLS/SSL port: 8084
* ws -> 8083; wss -> 8084
* By default, EMQX allows clients to connect without authentication.
* https://docs.emqx.com/en/enterprise/v4.4/advanced/auth.html#anonymous-login
* for more options and details, please refer to https://github.com/mqttjs/MQTT.js#mqttclientstreambuilder-options
*/
const connection = reactive({
protocol: 'ws',
host: 'broker.emqx.io',
// ws -> 8083; wss -> 8084
port: 8083,
clientId: 'emqx_vue3_' + Math.random().toString(16).substring(2, 8),
username: '',
password: '',
repacket: 'd1ca1ff51f04', //注册包(改为您的注册包)
dhtRegpack: 'd1ca1ff51f04', //温度注册包(可以相同可以共享传感器)
mqttToken: '0804d4c44c1f1bd11dea461481f19868', //授权TOKEN自己约定
keepalive: 30,
clean: true, //清除 clean session
connectTimeout: 30 * 1000, // ms 超时毫秒
reconnectPeriod: 5000, // ms 重连毫秒
resubscribe: true, //重新订阅
//定义您自己的主题
subTopic: 'mqtt/admintnet/#0#/out',
willTopic: 'mqtt/admintnet/#0#/will',
dhtTopic: 'mqtt/admintnet/#0#/dht',
pubTopic: 'mqtt/admintnet/#0#/into',
subTopics: [],
pubPayload: '{"msg":"hellow vue3 mqtt."}',
onlineStatus: false,
ch1_Status: false,
ch2_Status: false,
ch3_Status: false,
ch4_Status: false,
all_Status: false,
isAC: null, //强电true
});
// 初始化主题
const init_topic = () => {
let st = 'mqtt/admintnet/#0#/out'; //订阅主题
let pt = 'mqtt/admintnet/#0#/into'; //发布主题
let ptbody = '{"token":"{0}","cmd":"{1}","cmdpara":"{2}","clientid":"{3}"}';
let wt = 'mqtt/admintnet/#0#/will'; //遗嘱主题
let dh = 'mqtt/admintnet/#0#/dht'; //温湿度
connection.subTopic = st.replace('#0#', connection.repacket);
connection.willTopic = wt.replace('#0#', connection.repacket);
connection.dhtTopic = dh.replace('#0#', connection.dhtRegpack); //温湿度
connection.pubTopic = pt.replace('#0#', connection.repacket);
connection.subTopics = [connection.subTopic, connection.willTopic, connection.dhtTopic];
connection.pubPayload = ptbody;
//console.log(connection.subTopics);
};
// 默认注册包同步和传感器包名一致,反之不动
const syncdhtreg = () => {
connection.dhtRegpack = connection.repacket;
};
// 字符串替换模拟 string.format(str,ar1,arn)
const stringFormat = (formatted, args) => {
for (let i = 0; i < args.length; i++) {
let regexp = new RegExp('\\{' + i + '\\}', 'gi');
formatted = formatted.replace(regexp, args[i]);
}
return formatted;
};
onMounted(async () => {
init_topic();
nextTick(() => {});
});
// topic & QoS for MQTT subscribing 订阅主题(多个)
const subscription = ref({
topic: `$(connection.subTopics.value)`,
qos: 0 as MQTT.QoS,
});
// topic, QoS & payload for publishing message 发布主题
const publish = ref({
topic: `${connection.pubTopic}`,
qos: 0 as MQTT.QoS,
retain: false, //保留否
payload: '55 AA AA AA AA 91 CF', //'{ "msg": "Hello, I am browser." }',
});
const initData = () => {
client.value = {
connected: false,
} as MQTT.MqttClient;
retryTimes.value = 0;
btnLoadingType.value = '';
subscribedSuccess.value = false;
};
const handleOnReConnect = () => {
retryTimes.value++;
connection.clientId = 'emqx_vue3_' + Math.random().toString(16).substring(2, 8);
console.log(retryTimes.value, '重试次数');
if (retryTimes.value > 5) {
try {
client.value.end(); //重连超过5次断开
initData();
console.log('connection maxReconnectTimes limit, stop retry');
appmessage(now.toLocaleString() + '|超出重连接次数,停止重试' + retryTimes.value);
} catch (error) {
console.log('handleOnReConnect catch error:', error);
}
}
};
/**
* if protocol is "ws", connectUrl = "ws://broker.emqx.io:8083/mqtt"
* if protocol is "wss", connectUrl = "wss://broker.emqx.io:8084/mqtt"
*
* /mqtt: MQTT-WebSocket uniformly uses /path as the connection path,
* which should be specified when connecting, and the path used on EMQX is /mqtt.
*
* for more details about "mqtt.connect" method & options,
* please refer to https://github.com/mqttjs/MQTT.js#mqttconnecturl-options
*/
// create MQTT connection 创建连接
const createConnection = () => {
try {
btnLoadingType.value = 'connect';
const { protocol, host, port, ...options } = connection;
const connectUrl = `${protocol}://${host}:${port}/mqtt`; //组成新的连接字符串
console.log(connectUrl, '连接地址');
client.value = MQTT.connect(connectUrl, options);
if (client.value.on) {
// https://github.com/mqttjs/MQTT.js#event-connect
client.value.on('connect', () => {
//v5.x reconnect
btnLoadingType.value = '';
connSuccess.value = true; //client.value.connected;
console.log('connection successful', client.value.connected);
appmessage(now.toLocaleString() + '|连接服务成功');
});
// https://github.com/mqttjs/MQTT.js#event-reconnect 重连回调
client.value.on('reconnect', handleOnReConnect);
// https://github.com/mqttjs/MQTT.js#event-error
client.value.on('error', (error) => {
console.log('connection error:', error);
appmessage(now.toLocaleString() + '|发生错误:' + error);
});
// https://github.com/mqttjs/MQTT.js#event-message 接收消息,处理方法单独定义
client.value.on('message', (topic: string, message) => {
//处理方法
recvnum.value++; //接收次数累计
doAction(topic, message); //处理
receivedMessages.value = receivedMessages.value.concat(
//拼接字符串输出
now.toLocaleString() + ' ' + `${topic}\r\n` + message.toString() + '\r\n'
);
// console.log(now.toLocaleString()+`收到消息: ${message} from topic: ${topic}`);
//滚动此方法可行
nextTick(() => {
setTimeout(() => {
syncBottom(); //滚动到底部
}, 50);
});
});
}
} catch (error) {
btnLoadingType.value = '';
console.log('mqtt.connect error:', error);
}
};
// 处理事件
const doAction = (t, msg) => {
let res = JSON.parse(msg.toString()); //必须规范的json格式否则出错双引号不能是单引号后不安全但强大 eval('(' + message.toString() + ')'); //JSON.parse(message.toString());//json对象
// 消息不能带''否则错误
let regp = res.regpacket; // 接收的注册包
let regs = connection.repacket; // 订阅的注册包
let isOK = regp == regs ? true : false; // 是不是本设备的消息
if (!isOK || regp == null) {
return; // 不是丢弃
}
if (t == connection.dhtTopic) {
// 温湿度
let rp = res.regpacket;
let wd = res.temperature;
let sd = res.humidity;
let sj = res.time;
let sc = res.runsec;
if (rp != connection.dhtRegpack) {
// 来自订阅的温湿度包
return;
}
if (rp != null) {
dht_wd.value = wd; // 实际应用时替换此3个变量即可
dht_sd.value = sd;
dht_tm.value = '更新时间:' + sj;
runSeconds.value = sc;
dht_wsd.value = '温度:' + dht_wd.value + '℃,湿度:' + dht_sd.value + '%';
//state.option.title.text="实时温湿度变化趋势图(运行"+parseInt(sc)+"秒)";
//updatechart(false);//实时数据(这种方法是实时推送,如果用 定时器 是定时显示的)updatewsd_time(false)
}
}
if (t == connection.willTopic) {
// 遗嘱
if (res.redata == 'offline') {
connection.onlineStatus = false;
} else {
connection.onlineStatus = true;
}
}
if (t == connection.subTopic) {
let rp0 = res.regpacket;
if (rp0 != undefined) {
if (rp0 == regs) {
op(res.redata); // 该设备执行指令其他放弃
}
}
}
};
// 处理开关状态(自定义的指令,需要修改为您自己的指令)
const op = (cmd: any) => {
if (cmd == '55 AA AA AA AA 82 01 01') {
connection.ch1_Status = true;
}
if (cmd == '55 AA AA AA AA 82 01 00') {
connection.ch1_Status = false;
}
if (cmd == '55 AA AA AA AA 82 02 01') {
connection.ch2_Status = true;
}
if (cmd == '55 AA AA AA AA 82 02 00') {
connection.ch2_Status = false;
}
if (cmd == '55 AA AA AA AA 82 03 01') {
connection.ch3_Status = true;
}
if (cmd == '55 AA AA AA AA 82 03 00') {
connection.ch3_Status = false;
}
if (cmd == '55 AA AA AA AA 82 04 01') {
connection.ch4_Status = true;
}
if (cmd == '55 AA AA AA AA 82 04 00') {
connection.ch4_Status = false;
}
if (cmd == '55 AA AA AA AA 82 A4 01') {
connection.ch1_Status = true;
connection.ch2_Status = true;
connection.ch3_Status = true;
connection.ch4_Status = true;
}
if (cmd == '55 AA AA AA AA 82 A4 00') {
connection.ch1_Status = false;
connection.ch2_Status = false;
connection.ch3_Status = false;
connection.ch4_Status = false;
}
if (cmd == '55 AA AA AA AA 84 AC 01') {
connection.isAC = true;
}
if (cmd == '55 AA AA AA AA 84 AC 00') {
connection.isAC = false;
}
if (connection.ch1_Status && connection.ch2_Status && connection.ch3_Status && connection.ch4_Status) {
connection.all_Status = true;
}
if (!connection.ch1_Status && !connection.ch2_Status && !connection.ch3_Status && !connection.ch4_Status) {
connection.all_Status = false;
}
if (cmd == '55 AA AA AA AA 84 AC 01') {
connection.isAC = true;
}
if (cmd == '55 AA AA AA AA 84 AC 00') {
connection.isAC = false;
}
};
// 自动同步滚动建议延时执行textarea:any=null
const syncBottom = () => {
const textarea = document.getElementById('recv');
if (textarea) {
textarea.scrollTop = textarea.scrollHeight - 30;
}
};
// subscribe topic 开始订阅
// https://github.com/mqttjs/MQTT.js#mqttclientsubscribetopictopic-arraytopic-object-options-callback
const doSubscribe = () => {
btnLoadingType.value = 'subscribe';
const { topic, qos } = subscription.value;
console.log(connection.subTopics, '订阅主题');
client.value.subscribe(connection.subTopics, { qos }, (error: Error, granted: mqtt.ISubscriptionGrant[]) => {
btnLoadingType.value = '';
if (error) {
console.log('subscribe error:', error);
return;
}
subscribedSuccess.value = true; //订阅成功
// 连接成功,发布首个问询指令
switchLight('55 AA AA AA AA 91 CF'); //发送首页问询指令
console.log('订阅成功subscribe successfully:', granted);
});
};
// unsubscribe topic 取消订阅
// https://github.com/mqttjs/MQTT.js#mqttclientunsubscribetopictopic-array-options-callback
const doUnSubscribe = () => {
btnLoadingType.value = 'unsubscribe';
const { topic, qos } = subscription.value;
client.value.unsubscribe(connection.subTopics, { qos }, (error) => {
btnLoadingType.value = '';
subscribedSuccess.value = false;
if (error) {
console.log('unsubscribe error:', error);
return;
}
console.log(`unsubscribed topic: ${topic}`);
});
};
// publish message发布消息
// https://github.com/mqttjs/MQTT.js#mqttclientpublishtopic-message-options-callback
const doPublish = (b, t) => {
//btnLoadingType.value = "publish";
const { topic, qos, payload, retain } = publish.value;
//console.log(t+b,"发布内容")
let paybody = stringFormat(connection.pubPayload, [connection.mqttToken, b ?? publish.value.payload, '', connection.clientId]); //标准格式payload
client.value.publish(t ?? connection.pubTopic, paybody, { qos }, (error) => {
nextTick(() => {
// 测试延时
setTimeout(() => {
btnLoadingType.value = '';
}, 50);
});
if (error) {
appmessage(now.toLocaleString() + '|发布消息错误.' + error);
console.log('publish error:', error);
return;
}
});
};
// 消息追加消息框
const appmessage = (msg) => {
receivedMessages.value = receivedMessages.value.concat(
// 拼接字符串输出
msg + '\r\n'
);
};
// 开关
const switchLight = (cmd) => {
if (!client.value.connected) {
appmessage('尚未连接到服务!');
return;
}
let paybody = stringFormat(connection.pubPayload, [connection.mqttToken, cmd ?? publish.value.payload, '', connection.clientId]);
const { topic, qos, payload, retain } = publish.value;
//console.log(t+b,"发布内容")
client.value.publish(connection.pubTopic, paybody, { qos }, retain, (error) => {
btnLoadingType.value = '';
if (error) {
console.log('publish error:', error);
return;
}
});
};
// disconnect 端口连接
// https://github.com/mqttjs/MQTT.js#mqttclientendforce-options-callback
const destroyConnection = () => {
if (client.value.connected) {
btnLoadingType.value = 'disconnect';
try {
client.value.end(false, () => {
initData();
connSuccess.value = false;
//console.log("断开成功 disconnected successfully");
appmessage(now.toLocaleString() + '|连接已断开.');
});
} catch (error) {
btnLoadingType.value = '';
console.log('断开错误 disconnect error:', error);
}
}
};
// 端口随协议而改变
const handleProtocolChange = (value: string) => {
connection.port = value === 'wss' ? 8084 : 8083;
};
// 清空消息框
const clsmsg = () => {
receivedMessages.value = '';
};
</script>
<style lang="scss" scoped>
.mqtt-box {
max-width: 100%;
margin: 0 auto;
}
.header {
font-size: 24px;
font-weight: bold;
margin: -6px auto 0px auto;
}
h1 {
font-size: 16px;
margin-top: 10px auto 20px auto;
padding: 6px 0px 6px 0;
}
.el-col {
padding: 4px;
}
.el-input {
font-size: 13px;
}
.el-card {
margin-bottom: 6px;
}
.el-card__body {
padding: 24px;
}
.el-select {
width: 100%;
}
.text-right {
text-align: right;
}
.sub-btn {
margin-top: 20px;
width: 160px;
}
.hidden {
display: none;
}
.w80 {
width: 80px;
}
.w100 {
width: 100px;
}
.log {
font-size: 14px;
color: #fff;
background-color: black;
}
.center {
text-align: center;
}
#ch1,
#ch2,
#ch3,
#ch4,
#ch5 {
width: 120px;
}
.el-tag {
padding: auto 4px;
margin: 5px;
min-width: 60px;
}
</style>