一、简介

MQTT(消息队列遥测传输)是ISO 标准(ISO/IEC PRF 20922)下基于发布/订阅范式的消息协议。它工作在 TCP/IP协议族上,是为硬件性能低下的远程设备以及网络状况糟糕的情况下而设计的发布/订阅型消息协议,为此,它需要一个消息中间件 。

MQTT是一个基于客户端-服务器的消息发布/订阅传输协议。MQTT协议是轻量、简单、开放和易于实现的,这些特点使它适用范围非常广泛。在很多情况下,包括受限的环境中,如:机器与机器(M2M)通信和物联网(IoT)。其在,通过卫星链路通信传感器、偶尔拨号的医疗设备、智能家居、及一些小型化设备中已广泛使用。

MQTT协议在物联网中应用广泛,下面使用插件式集成到IoTBrowser平台,提供JS API即可发布broker和客户端实现发布、订阅等功能。

二、 开发插件

  1. 添加引用
    1. 添加MQTTNet,在NuGet搜索MQTTNet
    2. 添加Core,路径:\IoTBrowser\src\app_x64\Core.dll
    3. 添加Infrastructure,路径:\IoTBrowser\src\app_x64\Infrastructure.dll
    4. 添加Newtonsoft,路径:\IoTBrowser\src\app_x64\Newtonsoft.Json.dll
  2. 开发MqttHostCom和MqttClientCom插件
    1. MqttHostCom 服务端 broker
using DDS.IoT.Com;
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks; namespace DDS.IoT.Mqtt
{
public class MqttHostCom : ComBase
{
public override string Type => "mqttHostCom"; public override string Name => "Mqtt主机";
private MqttHostService hostService; public override bool Init(int port, int baudRate = 9600, string extendData = null)
{
this.Port = port;
hostService = new MqttHostService();
hostService.PushId = this.Id;
hostService.StartAsync(extendData, OnPushData);
Console.WriteLine("初始化MqttHostCom驱动程序成功!");
return true;
}
public override event PushData OnPushData; public override bool Open()
{
var b = false;
try
{
b = true;
IsOpen = true;
}
catch (Exception ex)
{ string msg = string.Format("MqttHostCom串口打开失败:{0} ", ex.Message);
Console.WriteLine(msg);
}
return b;
} public override bool Close()
{
hostService.Dispose();
hostService = null;
IsOpen = false;
OnPushData = null;
return true;
} public override string Command(string name, string data)
{
var outData = string.Empty; return outData;
}
}
}

    

  2.MqttClientCom 客户端

实现发布和订阅接口

using DDS.IoT.Com;
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks; namespace DDS.IoT.Mqtt
{
public class MqttClientCom : ComBase
{
public override string Type => "mqttClientCom"; public override string Name => "Mqtt客户端";
private MqttClientService mqttClientService; public override bool Init(int port, int baudRate = 9600, string extendData = null)
{
mqttClientService = new MqttClientService();
mqttClientService.PushId = this.Id;
this.Port = port;
mqttClientService.MqttClientStart(extendData,this.OnPushData);
Console.WriteLine("初始化MqttClientCom驱动程序成功!");
return true;
}
public override event PushData OnPushData; public override bool Open()
{
var b = false;
try
{
mqttClientService.Open();
b = true;
IsOpen = true;
}
catch (Exception ex)
{ string msg = string.Format("MqttClientCom串口打开失败:{0} ", ex.Message);
Console.WriteLine(msg);
}
return b;
} public override bool Close()
{
mqttClientService.Close();
mqttClientService = null;
IsOpen = false;
OnPushData = null;
return true;
} public override string Command(string name, string data)
{
var outData = string.Empty; var dataObj = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(data);
switch (name)
{
case "Publish":
string topic = dataObj.topic;
string payload = dataObj.data;
int? level = dataObj.level;
bool? retain = dataObj.retain;
if (!level.HasValue)
{
level = 1;
}
if (!retain.HasValue)
{
retain = false;
}
outData =mqttClientService.Publish(topic, payload, level.Value, retain.Value).ToString();
break;
case "Subscribe":
topic = dataObj.topic;
level = dataObj.level;
if (!level.HasValue)
{
level = 0;
}
outData = mqttClientService.Subscribe(topic, level.Value).ToString();
break;
}
return outData;
}
}
}

3.前端测试

<!DOCTYPE HTML PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.0//EN" "http://www.wapforum.org/DTD/xhtml-mobile10.dtd">
<html>
<head lang="en">
<title>Mqtt</title>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0">
<meta name="format-detection" content="telephone=no">
<!-- Set render engine for 360 browser -->
<meta name="renderer" content="webkit">
<!-- No Baidu Siteapp-->
<!--<meta http-equiv="Cache-Control" content="no-siteapp" />-->
<META HTTP-EQUIV="pragma" CONTENT="no-cache">
<META HTTP-EQUIV="Cache-Control" CONTENT="no-cache, must-revalidate">
<META HTTP-EQUIV="expires" CONTENT="0">
<link rel="alternate icon" type="image/png" href="favicon.png">
<link rel="stylesheet" href="/scripts/amazeui/amazeui.min.css" />
<link rel="stylesheet" href="../css/main.css" />
<script src="/scripts/jquery-3.3.1.min.js"></script>
<script src="/scripts/amazeui/amazeui.min.js"></script> <script src="/scripts/jquery.signalR-2.4.1.min.js"></script>
<style>
.list {
width: 1000px !important;
} .am-form {
width: 100%;
background: #fff;
} .refresh-port {
width: 80px !important;
height: 30px !important;
} #msg, #msgWrite {
clear: both;
} .am-u-sm-4 {
padding: 3px;
}
</style>
<script type="text/javascript">
var hostid;// 主机id
var clientid;// 客户端id function startHost() {
var args = $('#txtHostArgs').val();
dds.iot.com.open({
type: 'mqttHostCom',//mqtt主机
port: 1,
baudRate: 1,
extendData: args,
//extendData: JSON.stringify({ server: "*", port: 1883 }),
onReceive: function (res) {
addMsg('host:' + JSON.stringify(res.data))
console.log('host', res.data)
},
onOpen: function (ar) {
if (ar.Success) {
hostid = ar.Data;
addMsg('连接成功!')
} else {
alert(ar.Message)
}
}
})
}
function closeHost() {
dds.iot.com.close(hostid)
}
function startClient() {
var args = $('#txtClientArgs').val();
dds.iot.com.open({
type: 'mqttClientCom',//mqtt客户端
port: 1,
baudRate: 1,
extendData: args,
//extendData: JSON.stringify({ server: "localhost", port: 1883, clientid: "1", username: "", password:""}),
onReceive: function (res) {
addMsg('client:' + JSON.stringify(res.data))
console.log('client',res.data)
},
onOpen: function (ar) {
if (ar.Success) {
clientid = ar.Data;
addMsg('连接成功!')
} else {
alert(ar.Message)
}
}
})
}
function subscribe() {
var topic = $('#txtTopic').val();
dds.iot.com.exeCommand({ id: clientid, name: "Subscribe", data: { topic: topic, level: 0 } }, function (ar) {
if (ar.Success) {
addMsg('订阅成功!')
} else {
addMsg('操作失败:' + ar.Message)
}
})
}
function publish() {
var topic = $('#txtTopic').val();
var contents = $('#txtContents').val();
dds.iot.com.exeCommand({ id: clientid, name: "Publish", data: { topic: topic, data: contents } }, function (ar) {
if (ar.Success) {
addMsg('发布成功!')
} else {
addMsg('操作失败:' + ar.Message)
}
})
}
function closeClient() {
dds.iot.com.close(clientid)
}
var $msg;
function addMsg(msg) {
$msg.val($msg.val()+"\n"+msg);
}
function clearLog() {
$msg.val('');
}
// 窗口初始化事件(操作窗口大小、标题)
$(document).bind('dds.window.init', function (e, win) {
$msg = $("#msg");
})
</script> </head> <body>
<div class="fun_bd" style="padding:10px;">
<form class="am-form">
<h3>数据读取</h3>
<fieldset>
<div class="am-form-group">
<label for="doc-ipt-email-1" class="am-u-sm-4">主机参数</label>
<div class="am-u-sm-6">
<input id="txtHostArgs" type="text" value='{ server: "*", port: 1883 }' />
</div>
<button onclick="startHost()" class="am-btn-primary" type="button">启动主机</button>
<button onclick="closeHost()" class="am-btn-danger" type="button">关闭主机</button>
</div>
<div class="am-form-group">
<label for="doc-ipt-email-1" class="am-u-sm-4">客户端参数</label>
<div class="am-u-sm-6">
<input id="txtClientArgs" type="text" value='{ server: "localhost", port: 1883, clientid: "1", username: "", password:""}' />
</div>
<button onclick="startClient()" class="am-btn-primary" type="button">启动客户端</button>
<button onclick="closeClient()" class="am-btn-danger" type="button">关闭客户端</button>
</div>
<div class="am-form-group">
<label for="doc-ipt-email-1" class="am-u-sm-4">主题</label>
<div class="am-u-sm-6">
<input id="txtTopic" type="text" value="/dds/iot/mqtt/test" />
</div>
<button onclick="subscribe()" class="am-btn-primary" type="button">订阅主题</button>
</div>
<div class="am-form-group">
<label for="doc-ipt-email-1" class="am-u-sm-4">主题内容</label>
<div class="am-u-sm-6">
<input id="txtContents" type="text" value="测试测试" />
</div>
<button onclick="publish()" class="am-btn-primary" type="button">发布主题</button>
</div> <!--<div id="msg"></div>-->
<textarea id="msg" rows="18"></textarea>
<div class="am-form-group">
<button onclick="clearLog()" class="am-btn-default" type="button">清除日志</button>
</div>
</fieldset>
</form>
</div> </body> </html>

代码地址:https://gitee.com/yizhuqing/IoTBrowser

基于Chromium内核使用H5快速开发工控系统界面,使用JS API前端人员既可以完成界面展示与硬件控制。系统自带串口、RFID、电子秤等硬件协议支持,并且支持二次定制开发。可以用来开发人机界面(HMI)或数据采集与监督控制系统(SCADA) 。 使用H5或Vue可以本地打包离线应用,也可以在线加载Web网页来控制设备硬件。

 
 

物联网浏览器(IoTBrowser)-MQTT协议集成和测试的更多相关文章

  1. 海鑫智圣:物联网漫谈之MQTT协议

    什么是MQTT协议 MQTT(消息队列遥测传输协议)是IBM在1999年专门针对物联网等应用场景来制订的轻量级双向消息传输协议,它主要是为了解决物联网上使用到的设备的互相通信的问题,以及这些设备与后端 ...

  2. MQTT是IBM开发的一个即时通讯协议,构建于TCP/IP协议上,是物联网IoT的订阅协议,借助消息推送功能,可以更好地实现远程控制

    最近一直做物联网方面的开发,以下内容关于使用MQTT过程中遇到问题的记录以及需要掌握的机制原理,主要讲解理论. 背景 MQTT是IBM开发的一个即时通讯协议.MQTT构建于TCP/IP协议上,面向M2 ...

  3. 【转载】MQTT学习笔记——MQTT协议体验 Mosquitto安装和使用

    http://blog.csdn.net/xukai871105/article/details/39252653 0 前言     MQTT是IBM开发的一个即时通讯协议.MQTT是面向M2M和物联 ...

  4. 深度剖析MQTT协议的整个通信流程

    http://www.elecfans.com/d/587483.html MQTT,目前物联网的最主要的协议,基本所有收费的云平台都是基于MQTT协议,比如机智云,和所有的开放云平台比如中国移动的o ...

  5. MQTT协议学习研究 & Mosquitto简要教程(安装和使用)

    若初次接触MQTT协议,可先理解以下概念: [MQTT协议特点]——相比于RESTful架构的物联网系统,MQTT协议借助消息推送功能,可以更好地实现远程控制. [MQTT协议角色]——在RESTfu ...

  6. 物联网项目开发必读 深度分析MQTT协议优缺点

    物联网并不仅仅是一种网络,而是一个新的生态环境,它描述的本质是越来越多的使用物品通过网络连接在一起并可使用单个或者多个的终端设备对它们进行各种控制和使用—当然,工业上的物联网通常连接到的石鼓传感器或者 ...

  7. 转战物联网·基础篇09-选择MQTT协议还是CoAP协议

      前面章节介绍过,MQTT协议和CoAP协议都是物联网中比较流行的协议,都对传输量做了很大的精简,传输开销小,以适应物理网的网络环境.   XMPP协议也有人说是适合物联网通信的,但它是基于XML, ...

  8. 物联网MQTT协议分析和开源Mosquitto部署验证

    在<物联网核心协议—消息推送技术演进>一文中已向读者介绍了多种消息推送技术的情况,包括HTTP单向通信.Ajax轮询.Websocket.MQTT.CoAP等,其中MQTT协议为IBM制定 ...

  9. 【物联网云端对接-3】通过MQTT协议与微软Azure IoT Hub进行云端通信

    在上一篇文章<通过MQTT协议与阿里云物联网套件进行云端通信>中,我们介绍了通过MQTT对接阿里云的物联网套件.其实同样的代码,稍加调整也可以对接到微软Azure IoT hub上,不过需 ...

  10. 物联网网关MQTT应用与配置测试介绍

    1.MQTT介绍: MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),作为除Modbus外最常用的协议之一,因其基于发布/订阅的模式,具有资源消 ...

随机推荐

  1. 一些 Codeforce Content 补题记录

    Codeforces Round #651 (Div. 2) 1370A. Maximum GCD 给定一个 n,求(1~n)中任意组合对的最大的公约数. 思路:如果 \(n\) 是偶数,那么最大公约 ...

  2. uni-app学习笔记

    uniapp封装请求方法(含请求期间的Loading样式) https://blog.csdn.net/weixin_43242112/article/details/108019404?utm_me ...

  3. 启动vue项目失败,报错Failed at the node-sass@4.14.1 postinstall script.

    https://www.cnblogs.com/xiaodangshan/p/13061618.html

  4. [VS工程技巧]远程调试工具及dump文件来检查程序崩溃及异常等问题

    做什么 之前有一次梦中所得,既然可以让vs附加到进程去调试活动的dll,那要是可以让我本地的电脑去调试别人客户端或者测试环境的DLL就好了,这样就可以不通过dbgview去一个个输出看,而是可以直接调 ...

  5. 《DREEAM Guiding Attention with Evidence for Improving Document-Level Relation Extraction》阅读笔记

    代码   原文地址   预备知识: 1.什么是K-L散度(Kullback-Leibler Divergence)? K-L散度,是一种量化两种概率分布P和Q之间差异的方式,又叫相对熵.在概率学和统计 ...

  6. SD-Host控制器设计架构

    SD Host功能列表 SD Host挂接在SoC中,与外部的SD card进行交互 有控制寄存器和状态寄存器,SoC往往有CPU,通过CPU进行配置寄存器,有些SoC没有CPU,需要使用I2C或者S ...

  7. [转帖]麒麟v10上部署TiDBv5.1.2生产环境的最佳实践

    https://tidb.net/book/tidb-monthly/2022/2022-07/usercase/tidb-v5-1-2 前言​ 笔者最近在一个银行项目中做 PoC 测试,由于客户选择 ...

  8. [转帖]CentOS7安装笔记:minio分布式集群搭建

    文章目录 准备机器 部署(所有机器均执行) 创建挂载磁盘路径 挂载磁盘路径到文件系统 创建minio目录 下载minio安装包 创建启动脚本 创建启动服务 启动测试(所有机器执行) 重新加载服务的配置 ...

  9. [转帖]Jmeter学习笔记(九)——响应断言

    Jmeter学习笔记(九)--响应断言 https://www.cnblogs.com/pachongshangdexuebi/p/11571348.html Jmeter中又一个元件叫断言,用于检查 ...

  10. [转帖]【Jmeter】Jmeter压力测试工具安装及使用教程(redis测试)

    摘自:https://www.cnblogs.com/monjeo/p/9330464.html 一.Jmeter下载 进入官网:http://jmeter.apache.org/ 1.第一步进入官网 ...