使用MQTT.JS创建一个网页版的MQTT客户端

一、MQTT.JS介绍

MQTT.js 是一个开源的 MQTT 协议的客户端库,使用 JavaScript 编写,主要用于 Node.js 和 浏览器环境中。是JavaScript 环境下的 MQTT 客户端库。可以用于微信小程序、支付宝小程序等定制浏览器环境。

我们可以直接在HTML文件中进行调用:

<script src="https://unpkg.com/mqtt/dist/mqtt.min.js"></script>

也可以下载该文件,和HTML文件放在同一目录来进行调用:

<script src=" ./mqtt.min.js"></script>

二、网页界面设计

调用库文件后,我们需要在html中生成一些文本框,来填写一些连接服务器所需要的信息,如服务器地址,服务器端口,服务器路径,clientID,用户名,用户密码,这里在文本框中加入了默认的一些信息,如果自已有更方便测试的服务器,可以自行修改:

      服务器地址:<input type="text" id="host" value="ws://broker.emqx.io">服务器端口:<input type="text" id="port" value="8083">服务器路径:<input type="text" id="path" value="/mqtt">客  户  端  ID:<input type="text" id="clientID" value="">用   户   名:<input type="text" id="user" value="test">密        码:<input type="text" id="password" value="123">

接下来我们需要要两个按钮,用来实现连接和断开服务器功能,当按下按钮时,分别调用connectMQTT()函数和connectEND()函数:

    <button id="connectBtn" onclick="connectMQTT()">连接</button><button id="disconnectBtn" disabled="disabled" onclick="connectEND()">已断开</button>

接下来,我们需要一个文本框来填写订阅的主题名称,以及一个按钮来确定订阅内容:

  <body><h2>MQTT订阅</h2>主题:<input type="text" id="subtopic" value="test"><button onclick="subscribe_topic()">订阅</button></body>

我们还需要两个文本框来填写发送的主题名称和发送的消息内容,以及一个按钮来确定发送消息:

  <body><h2>MQTT消息发送</h2>主题:<input type="text" id="topic" value="test">消息:<input type="text" id="message" value="test"><button onclick="sendMessage()">发送</button></body>

最后,我们需要一个文本框来显示各种信息,该文本框使用<textarea>元素,该元素为一个多行的文本输入控件,在文本输入域中可以输入任意长度的文本:

  <body><h1>消息框</h1><textarea id="messageTextArea" style="resize:none;" cols="80" rows="20"></textarea><br/></body>

以上,界面的设计已经完成。下面我们介绍一下需要用到的MQTT.JS的API

三、MQTT.JS常用API

mqtt.connect([url], options)
连接url和选项所指定的代理,并返回客户端对象。URL 可以是以下协议:"mqtt"、"mqtts"、"tcp"、"tls"、"ws"、"wss"、"wxs"、"alis"。URL 也可以是 URL.parse() 返回的对象,在这种情况下,两个对象会合并,也就是说,可以传递一个同时包含URL和连接选项的对象。也可以指定一个服务器选项,内容为[{ host: 'localhost', port: 1883 }, ... ],在这种情况下,每次连接都会遍历该数组。
client.on('connect',function)
为指定事件注册一个监听器,接受一个字符串 event 和一个回调函数。
参数1:connect    -成功连接或重连后触发reconnect    -开始一个重新连接时触发close    -断开连接时触发disconnect    -从服务器接收到断开命令的数据包时触发offline    -客户端离线时触发error    -当客户端无法连接或出现解析错误时触发end    -调用Client.end()时触发。如果向Client.end() 传递了回调,则回调返回后会触发该事件message    -客户端收到发布数据包时触发packetsend    -客户端发送任何数据包时触发。包括published()数据包以及MQTT用于管理订阅和连接的数据包packetreceive    -客户端收到任何数据包时触发。包括来自订阅主题的数据包,以及MQTT用于管理订阅和连接的数据包参数2:回调函数
Client.publish(topic, message, [options], [callback])
发布消息
参数:topic        -主题message      -消息内容[options]    -发布选项[callback]   -回调函数
Client.subscribe(topic/topic array/topic object, [options], [callback])
参数:topic/topic array/topic object    -要订阅的字符串主题或主题数组。也可以是一个对象,对象键是主题名称,值是 QoS,如 {'test1': {qos: 0}, 'test2': {qos: 1}}. 支持MQTT主题通配符("+"表示单层级,"#"表示多层级)[options]                         -是订阅的选项[callback]                        -回调函数
Client.end([force], [options], [callback])
参数:[force]        -将其设为true将立即关闭客户端,而无需等待接收到飞行中的消息。该参数为可选参数。[options]      -断开连接选项[callback]     -回调函数

这里介绍一些常用的API,如果想了解详细的API说明,可以到官方地址:https://github.com/mqttjs/MQTT.js

四、函数设计

我们需要以下几个函数来完整地实现一个MQTT客户端功能:

1、连接服务器函数

该函数从网页的文本框中获取连接服务器所需的信息,如服务器地址,服务器端口,服务器路径,clientID,用户名,用户密码,通过以上信息用mqtt.connect()函数连接服务器,连接成功后,

触发client.on('connect',function)所指向的回调函数

/* 连接服务器 */function connectMQTT(){var host = document.getElementById("host").value;			//服务器地址var port = document.getElementById("port").value;			//服务器端口var path = document.getElementById("path").value;			//服务器路径var clientID = document.getElementById("clientID").value;	//clientIDvar user = document.getElementById("user").value;			//用户名var password = document.getElementById("password").value;	//用户密码var url = host+':'+port+path;								//URL地址console.log(url);											//后台输入URL地址var options = {												//创建一个参数对象clientID:clientID,										//clientIDusername:user,											//用户名password:password										//用户密码};client = mqtt.connect(url,options);							//连接服务器console.log(client);console.log(client.connected);client.stream.on('error', function(err) {					//连接错误时触发console.error('Connection error:'+err);console.log('连接失败');client.end();											//关闭客户端对象})client.on('connect',function(packet){													//连接服务器后触发document.getElementById("connectBtn").setAttribute("disabled","disabled");			//连接按钮不可用document.getElementById("connectBtn").innerHTML = "已连接";							//连接按钮显示为已连接document.getElementById("disconnectBtn").removeAttribute("disabled","disabled");	//断开按钮设为可用document.getElementById("disconnectBtn").innerHTML = "断开";						//断开按钮显示为断开client.on('message', message_str)													//定义接收消息后触发回调函数var messageTextArea = document.getElementById("messageTextArea");					//textarea添加文本messageTextArea.value += "已连接\n"													//textarea添加文本console.log("已连接");																//后台输出已连接})}

2、断开消息函数

该函数利用client.end()关闭client对象

/* 断开连接服务器 */function connectEND(){if(client && client.connected){client.end();console.log("已断开连接");document.getElementById("connectBtn").removeAttribute("disabled","disabled");		//连接按钮设为可用document.getElementById("connectBtn").innerHTML = "连接";							//连接按钮显示为连接document.getElementById("disconnectBtn").setAttribute("disabled","disabled");		//断开按钮设为不可用document.getElementById("disconnectBtn").innerHTML = "已断开";						//断开按钮显示已断开var messageTextArea = document.getElementById("messageTextArea");					//textarea添加文本messageTextArea.value += "已断开\n"													//textarea添加文本}else{console.log("未连接");}}

3、发布消息函数

该函数使用client.publish()发送消息。

/* 发送消息 */function sendMessage() {var topic = document.getElementById("topic").value;			//获取主题var message = document.getElementById("message").value;		//获取消息文本//console.log(topic);if(client && client.connected){client.publish(topic, message);							//发送消息console.log("已发送");}else{console.log("未连接");}}

4、订阅主题函数

该函数使用client.subscribe()来订阅一个主题。

/* 订阅主题 */function subscribe_topic(){var topic = document.getElementById("subtopic").value;				//获取主题client.subscribe(topic);											//定阅主题var messageTextArea = document.getElementById("messageTextArea");	//获取textarea元素messageTextArea.value += "已定阅"+topic+"\n";						//textarea添加文本console.log("已订阅:"+topic);}

5、接收消息函数

该函数由"连接服务器函数"中的client.on('message', message_str)事件触发,当该事件触发时,调用该函数

/* 接收消息函数 */function message_str(topic,message){													//监听消息函数console.log("收到来自主题:"+topic+"的消息:"+message.toString());var messageTextArea = document.getElementById("messageTextArea");					//获取textarea元素messageTextArea.value += "收到来自主题:"+topic+"的消息:"+message.toString()+"\n"; 	//将新的文本追加到 value}

五、完整代码

保存为index.html

<!DOCTYPE html>
<html><head><!-- 可选在线mqtt.min.js文件与本地mqtt.min.js文件 --><!-- <script src=" https://unpkg.com/mqtt@5.3.4/dist/mqtt.min.js"></script> --><script src=" ./mqtt.min.js"></script></head><body><h2>MQTT服务器设置</h2><form>服务器地址:<input type="text" id="host" value="ws://broker.emqx.io">服务器端口:<input type="text" id="port" value="8083"> </br>服务器路径:<input type="text" id="path" value="/mqtt">客  户  端  ID:<input type="text" id="clientID" value=""> </br>用   户   名:<input type="text" id="user" value="test">密        码:<input type="text" id="password" value="123"> </br></form><button id="connectBtn" onclick="connectMQTT()">连接</button><button id="disconnectBtn" disabled="disabled" onclick="connectEND()">已断开</button></body><body><h2>MQTT订阅</h2>主题:<input type="text" id="subtopic" value="test"><button onclick="subscribe_topic()">订阅</button></body><body><h2>MQTT消息发送</h2>主题:<input type="text" id="topic" value="test">消息:<input type="text" id="message" value="test"><button onclick="sendMessage()">发送</button></body><body><h1>消息框</h1><textarea id="messageTextArea" style="resize:none;" cols="80" rows="20"></textarea><br/></body><script>document.getElementById("clientID").setAttribute("value",randomID()); 	//生成随机clientIDvar client;																//创建一个客户端对象
/* 连接服务器 */function connectMQTT(){var host = document.getElementById("host").value;			//服务器地址var port = document.getElementById("port").value;			//服务器端口var path = document.getElementById("path").value;			//服务器路径var clientID = document.getElementById("clientID").value;	//clientIDvar user = document.getElementById("user").value;			//用户名var password = document.getElementById("password").value;	//用户密码var url = host+':'+port+path;								//URL地址console.log(url);											//后台输入URL地址var options = {												//创建一个参数对象clientID:clientID,										//clientIDusername:user,											//用户名password:password										//用户密码};client = mqtt.connect(url,options);							//连接服务器console.log(client);console.log(client.connected);client.stream.on('error', function(err) {					//连接错误时触发console.error('Connection error:'+err);console.log('连接失败');client.end();											//关闭客户端对象})client.on('connect',function(packet){													//连接服务器后触发document.getElementById("connectBtn").setAttribute("disabled","disabled");			//连接按钮不可用document.getElementById("connectBtn").innerHTML = "已连接";							//连接按钮显示为已连接document.getElementById("disconnectBtn").removeAttribute("disabled","disabled");	//断开按钮设为可用document.getElementById("disconnectBtn").innerHTML = "断开";						//断开按钮显示为断开client.on('message', message_str)													//定义接收消息后触发回调函数var messageTextArea = document.getElementById("messageTextArea");					//textarea添加文本messageTextArea.value += "已连接\n"													//textarea添加文本console.log("已连接");																//后台输出已连接})}/* 断开连接服务器 */function connectEND(){if(client && client.connected){client.end();console.log("已断开连接");document.getElementById("connectBtn").removeAttribute("disabled","disabled");		//连接按钮设为可用document.getElementById("connectBtn").innerHTML = "连接";							//连接按钮显示为连接document.getElementById("disconnectBtn").setAttribute("disabled","disabled");		//断开按钮设为不可用document.getElementById("disconnectBtn").innerHTML = "已断开";						//断开按钮显示已断开var messageTextArea = document.getElementById("messageTextArea");					//textarea添加文本messageTextArea.value += "已断开\n"													//textarea添加文本}else{console.log("未连接");}}/* 发送消息 */function sendMessage() {var topic = document.getElementById("topic").value;			//获取主题var message = document.getElementById("message").value;		//获取消息文本if(client && client.connected){client.publish(topic, message);							//发送消息console.log("已发送");}else{console.log("未连接");}}/* 订阅主题 */function subscribe_topic(){var topic = document.getElementById("subtopic").value;				//获取主题client.subscribe(topic);											//定阅主题var messageTextArea = document.getElementById("messageTextArea");	//获取textarea元素messageTextArea.value += "已定阅"+topic+"\n";						//textarea添加文本console.log("已订阅:"+topic);}/* 接收消息函数 */function message_str(topic,message){													//监听消息函数console.log("收到来自主题:"+topic+"的消息:"+message.toString());var messageTextArea = document.getElementById("messageTextArea");					//获取textarea元素messageTextArea.value += "收到来自主题:"+topic+"的消息:"+message.toString()+"\n"; 	//将新的文本追加到 value}/* 生成随机clientID */function randomID(){return 'clientID_' + Math.random().toString(16).substr(2, 8)}</script>
</html>

六、测试代码

我们用浏览器打开该html文件

点击连接,并订阅名为"test"的主题,同时给"test"主题发送一个文本内容为"test"的消息。

测试成功

备注:在网页中使用MQTT.JS,只支持WebSocket连接选项,就是说,在网页版的客户端中,无法连接mqtt://为前缀的地址。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/593900.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CMake是什么?为什么学习CMake

&#x1f608;「CSDN主页」&#xff1a;传送门 &#x1f608;「Bilibil首页」&#xff1a;传送门 &#x1f608;「本文的内容」&#xff1a;CMake入门教程 &#x1f608;「动动你的小手」&#xff1a;点赞&#x1f44d;收藏⭐️评论&#x1f4dd; 文章目录 1.CMake简介2.为什么…

Redis(二)

1、redis的持久化 "Redis 如何将数据写入磁盘"&#xff0c;首先要明白的时候&#xff0c;我们使用的redis的数据保存在内存上的&#xff0c;也就是说&#xff0c;只要我们的电脑关机或者重启服务器&#xff0c;那么在内存中的数据就会消失&#xff0c;所以要想持久化…

06.02 customizing plots with style sheets

使用 style 来配置 pyplot 风格 import matplotlib.pyplot as plt import numpy as np%matplotlib inlinestyle 是 pyplot 的一个子模块&#xff0c;方便进行风格转换&#xff0c; pyplot 有很多的预设风格&#xff0c;可以使用 plt.style.available 来查看&#xff1a; plt.…

爆肝整理,接口性能测试总结,一篇直接上高速...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、 性能测试术语…

uni-app 从入门到精通 3天快速掌握 文字版 学习专栏

大家好&#xff0c;我是java1234小锋老师。 近日锋哥又卷了一波课程&#xff0c;uni-app 从入门到精通 3天快速掌握教程&#xff0c;文字版视频版。三天掌握。 2023版uniapp从入门到上天视频教程(Java后端无废话版)&#xff0c;火爆更新中..._哔哩哔哩_bilibili2023版uniapp从…

亚信安慧AntDB数据库——通信运营商核心系统的全面演进

AntDB数据库源自通信运营商核心系统&#xff0c;经过15年的平稳运行和不断演进&#xff0c;成功跟随通信技术的升级步伐&#xff0c;逐步迈向5G时代&#xff0c;并且在这期间完成了8次大版本的迭代&#xff0c;为行业树立了技术领先的典范。其独特之处在于具备超融合架构&#…

如何在win7同样支持Webview2 在 WPF 中使用本地 Webview2 ,如何不依赖系统 Runtime

项目运行环境&#xff1a; .Net Framework 4.5.2 Windows 7 x64 Service Pack 1 WebView2 Microsoft.WebView2.FixedVersionRuntime.120.0.2210.91.x64 考虑到很多老项目&#xff0c;本项目使用的是.Net Framework 4.5.2&#xff0c;.Net 更高版本的其实也是可以支持的。 …

vmware安装龙蜥操作系统

vmware安装龙蜥操作系统 1、下载龙蜥操作系统 8.8 镜像文件2、安装龙蜥操作系统 8.83、配置龙蜥操作系统 8.83.1、配置静态IP地址 和 dns3.2、查看磁盘分区3.3、查看系统版本 1、下载龙蜥操作系统 8.8 镜像文件 这里选择 2023年2月发布的 8.8 版本 官方下载链接 https://mirro…

起名+算命+塔罗+星座+八字测算大全小程序源码系统 带完整的安装包以及搭建教程

随着科技的发展和人们生活水平的提高&#xff0c;越来越多的人开始关注个人命运和运势&#xff0c;希望通过各种方式了解自己的未来。在这样的背景下&#xff0c;一款集合了起名、算命塔、罗星座、八字测算等多种功能的小程序应运而生。这款小程序源码系统旨在为用户提供全方位…

mybatis-flex笔记

MyBatis-Flex 的增删改功能 - MyBatis-Flex 官方网站https://mybatis-flex.com/zh/base/add-delete-update.html 代码https://gitee.com/hntianshu/mybatis-flex-test 一 新增数据 不忽略 null 值。 就是允许有null 忽略null 就是不允许有null BaseMapper 的接口提供了 inser…

jmeter的安装与目录介绍

1、启动 apache-jmeter-5.0\bin 2、永久修改中文配置 zh-CN就行了

图像分割-漫水填充法 floodFill (C#)

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的。 本文的VB版本请访问&#xff1a;图像分割-漫水填充法 floodFill-CSDN博客 FloodFill方法是一种图像处理算法&#xff0c;它的目的是…

2023年度最热 AI 应用 TOP 50,除了 ChatGPT 还有这么多宝藏

原文章链接&#xff1a;年度最热 AI 应用 TOP 50&#xff0c;除了 ChatGPT 还有这么多宝藏 - IT之家 更多消息&#xff1a;AI人工智能行业动态&#xff0c;aigc应用领域资讯 在 AI 工具激烈竞争的一年中&#xff0c;尽管ChatGPT在访问量上遥遥领先&#xff0c;但单次使用时长未…

Java LinkedList解密

一、LinkedList最底层的原理 LinkedList其实底层是链表&#xff1a; 当初始化的时候&#xff0c;会将链表这个节点的值、prev指针和next指针初始化。 二、LinkedList初始化 无参构造并没有做什么。有参构造会先调用无参构造&#xff0c;然后调用addAll方法将链表的节点都初始化…

什么是高防 IP?哪些行业适合用高防 IP?

在数字化浪潮席卷全球的今天&#xff0c;网络安全问题日益凸显。有听说过“高防 IP”这个名词吗&#xff1f;它究竟是什么东西&#xff0c;又能在哪些领域大显身手呢&#xff1f; 一、什么是高防 IP&#xff1f; 高防 IP&#xff0c;顾名思义&#xff0c;就是具备高级防护能力…

1_并发编程_线程的基本概念和线程终止及线程问题排查

1.线程的运行状态 在Java中&#xff0c;线程的状态一共是6种状态&#xff0c;分别是 NEW&#xff1a;初始状态&#xff0c;线程被构建&#xff0c;但是还没有调用start方法 RUNNABLED&#xff1a;运行状态&#xff0c;JAVA线程把操作系统中的就绪和运行两种状态统一称为“运行…

【C程序设计】C判断

判断结构要求程序员指定一个或多个要评估或测试的条件&#xff0c;以及条件为真时要执行的语句&#xff08;必需的&#xff09;和条件为假时要执行的语句&#xff08;可选的&#xff09;。 C 语言把任何非零和非空的值假定为 true&#xff0c;把零或 null 假定为 false。 下面…

.mallox勒索病毒数据恢复|金蝶、用友、管家婆、OA、速达、ERP等软件数据库恢复

引言&#xff1a; 随着技术的不断发展&#xff0c;网络空间也不可避免地面临着各种威胁&#xff0c;其中之一就是勒索病毒&#xff0c;而.mallox是近期引起关注的一种恶意软件。本文将介绍.mallox勒索病毒&#xff0c;以及如何有效地恢复被其加密的数据文件&#xff0c;并提供…

OpenFeign相关面试题及答案(2024)

1、什么是OpenFeign&#xff0c;它如何简化远程服务调用&#xff1f; OpenFeign是一个声明式的Web服务客户端&#xff0c;它使得编写HTTP客户端变得更加容易。它属于Spring Cloud Netflix项目的一部分&#xff0c;可以与Spring Boot应用轻松集成。通过使用OpenFeign&#xff0…

Lingo 17安装包下载及安装教程

Lingo 17下载链接&#xff1a;https://docs.qq.com/doc/DUndEVXd4WVVweGFR 1.鼠标右键解压到“Lingo 17.0” 2.双击打开【Setup】文件夹 3.选中Lingo 17.0&#xff0c;鼠标右键选择“以管理员身份运行” 4.点击“Next” 5.选中I accept the terms in the license agreement&…