<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="20">
					<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"
							size="default"
							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" type="warning" size="default" :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="20">
					<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"
							size="default"
							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"
							size="default"
							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="30">
					<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="30">
					<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"
							size="default"
							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" size="default" :icon="Delete" title="点击清空历史记录">接收(Receive)</el-button>
				<el-tag size="default" title="接收次数">收 {{ recvnum }}</el-tag>
				<el-tag size="default" :title="dht_tm">{{ dht_wsd }}</el-tag>
				<el-tag size="default" title="设备已工作时长">{{ parseInt(runSeconds) }} 秒</el-tag>
				<el-button
					type="success"
					title="关闭一路"
					:disabled="!connection.onlineStatus | !client.connected"
					v-if="connection.ch1_Status"
					icon="ele-Check"
					size="default"
					id="ch1"
					v-preventReClick="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"
					size="default"
					id="ch1"
					v-preventReClick="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"
					size="default"
					id="ch2"
					v-preventReClick="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"
					size="default"
					id="ch2"
					v-preventReClick="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"
					size="default"
					id="ch3"
					v-preventReClick="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"
					size="default"
					id="ch3"
					v-preventReClick="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"
					size="default"
					id="ch4"
					v-preventReClick="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"
					size="default"
					id="ch4"
					v-preventReClick="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"
					size="default"
					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"
					size="default"
					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" />
			</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%;
	padding: 4px;
	margin: 10px auto 0 auto;
}

.header {
	font-size: 24px;
	font-weight: bold;
	margin: -12px auto 8px auto;
}

h1 {
	font-size: 16px;
	margin-top: 10px auto 20px auto;
	padding: 5px 0px 5px 0;
}

.el-col {
	padding: 4px;
}

.el-input {
	font-size: 13px;
}
.el-card {
	margin-bottom: 12px;
}
.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>
