开始使用MQTT(译)
原文标题:getting started mqtt
作者:Arvind Ravulavaru
翻译:治电小白菜
原文地址:http://thejackalofjavascript.com/getting-started-mqtt/
注意:发现文章中用的mqtt
模块版本过低,导致有些语法失效了,比如,创建客户端的函数createClient
在最新版的mqtt
已经失效.改用为mqtt.connect
。这些我已经在代码中做了更改,并且已经运行成功。
在这篇文章中,我们将瞧一瞧一个通信协议,名字叫做Message Queue Telemetry Transport (MQTT).MQTT是一个轻量的,安全的,省电的以及一个机器对机器(M2M)/“物联网”(Internet of Things)的连接协议。
来自Cirrus Link Solutions的Andy Stanford-Clark 和 Arlen Nipper 在 1999 年编写了这个协议的第一个版本。
什么是MQTT
MQTT(全称Message Queue Telemetry Transport)是一个基于顶层TCP/IP协议的有发布/订阅功能的轻量通信协议。它被设计来连接需要“小型代码封装”(“small code footprint”)或者网络带宽被限制的远程区域。发布/订阅信息模式要求一个信息代理。信息代理负责分发信息给订阅了一个信息话题的客户端。
<br >
说明文档没有明确“小型代码封装”(“small code footprint”)和“限制网络带宽”的含义。因此,协议的可用性取决于上下文的使用。在2013年,IBM将MQTT V3.1提交给 OASIS规范,确定只对规范进行可接受的小幅动的改动。MQTT-SN是一个主协议的变种,针对在non-TCP/IP网络下的嵌入式设备,比如ZigBee。
历史上,‘MQTT’的‘MQ’来自于IBM的MQ消息队列产品线。然而,队列本身不需要在所有情况下支持作为标准特性。
现实世界的应用
Facebook Messenger:Facebook已经在Facebook Messenger很多方面中使用了MQTT。然而还不确定使用了多少MQTT以及在哪个方面使用了MQTT;另外,要注意这是一个手机应用,不是一个传感器应用。
理解OSI模型
为了更加理解MQTT的使用范围,你需要对OSI模型有一定的理解。如果你已经知道了这个,你可以跳过下面的视频。
翻墙观看:https://www.youtube.com/embed/sVDwG2RdJho?rel=0
MQTT和HTTP处于同一层,是第7层。
为什么选择MQTT?
- 它是一个订阅/发布协议
- 它有不同质量的服务等级(QOS)
- 它有消息至少处理一次(at-least-once)和只执行一次(exactly-once)语义
- 它有一个很低的日常开支(最少2bytes)
- 它支持离线信息
- 它像一个键/值存储一样来保留信息
Matteo Collina,Mosca
的作者,给了一个很棒的演说,来演讲什么是MQTT以及它如何通过Nodejs工作。
翻墙观看:https://www.youtube.com/embed/WE7GVIFRV7Q?rel=0
你可以在这个网址查看他关于MQTT和Node.js演讲的演示。http://mcollina.github.io/mqtt_and_nodejs/
MQTT将会被应用到哪里?
想象下面的环境
mqtt_arch.png在单个机器/设备的状态/传感器数据需要传递给其他机器/设备,以及一个实时仪表、一个平板或者一个可穿戴设备。连接和维持数据传输,很多设备或许是棘手的。这种情况下可以使用MQTT。
亲自动手
现在我们已经对于MQTT有了一定的理解,我们将尝试一个简单的例子。我们将实现一个服务/代理 通过Mosca来接收数据并发放到所有他的客户端。然后我们将使用MQTT.js实现一个MQTT客户端从代理处发布和订阅一个话题。
创建一个名为mqttApp
的文件夹,我们将在它里面创建两个文件夹,分别叫server
,client
.
在server
文件夹内打开命令行,创建一个新的Node.js项目,通过运行
npm init
然后,我们将安装Mosca依赖,以及保存它到package.json中。运行
npm install mosca --save
在server
文件夹内创建名为server.js
的文件。将以下代码写入其中
var mosca = require('mosca')
var settings = {
port: 1883
};
//启动mosca
var server = new mosca.Server(settings);
server.on('ready', setup);
// 启动后发出
function setup() {
console.log('Mosca server is up and running')
}
// 客户端连接后发出
server.on('clientConnected', function(client) {
console.log('client connected', client.id);
});
//接收到信息时发出
server.on('published', function(packet, client) {
console.log('Published : ', packet.payload);
});
// 客户端订阅了一个主题时发出
server.on('subscribed', function(topic, client) {
console.log('subscribed : ', topic);
});
// 客户端取消订阅一个主题时发出
server.on('unsubscribed', function(topic, client) {
console.log('unsubscribed : ', topic);
});
// 客户端断开连接时发出
server.on('clientDisconnecting', function(client) {
console.log('clientDisconnecting : ', client.id);
});
一个简单的MQTT代理服务器。这些事情要注意
- Line1:引入 Mosca
- Line3:配置服务器
- Line8:开启服务器
- Line12:当服务器开启后回调
- Line17:clientConnected:当一个客户端连接后,客户端会被当作参数传递。
- Line22:published:当一个新消息被发布;数据包和客户端将被作为参数传递。
- Line27:subscribed:当一个客户端订阅了一个主题;主题和客户端会被当作参数传递。
- Line32:unsubscribed:当一个客户端取消订阅了一个主题;主题和客户端都会被当作参数传递。
- Line37:clientDisconnecting:当一个客户端正在断开连接;客户端会被当作参数传递。
- Line42:clientDisconnected:当一个客户端已经断开连接;客户端会被当作参数传递。
简单的 pub/sub API
如果你想启用离线模式,我们需要存储数据到一个键值对的数据库。开箱即用的Mosca支持大多数著名的键值对数据库。下面是一个快速的例子,教你如何使用它,使用MongoDB。
更新server.js
var mosca = require('mosca')
var pubsubsettings = {
type: 'mongo',
url: 'mongodb://localhost:27017/mqtt',
pubsubCollection: 'myCollections',
mongo: {}
};
var settings = {
port: 1883,
backend: pubsubsettings
};
//here we start mosca
var server = new mosca.Server(settings);
server.on('ready', setup);
// fired when the mqtt server is ready
function setup() {
console.log('Mosca server is up and running')
}
// fired whena client is connected
server.on('clientConnected', function(client) {
console.log('client connected', client.id);
});
// fired when a message is received
server.on('published', function(packet, client) {
console.log('Published : ', packet.payload);
});
// fired when a client subscribes to a topic
server.on('subscribed', function(topic, client) {
console.log('subscribed : ', topic);
});
// fired when a client subscribes to a topic
server.on('unsubscribed', function(topic, client) {
console.log('unsubscribed : ', topic);
});
// fired when a client is disconnecting
server.on('clientDisconnecting', function(client) {
console.log('clientDisconnecting : ', client.id);
});
只有在第3行有改变。我们在那里增加了MongoDB设置。(你可以使用一个服务像Mongo Lab,将数据存储到云里。)然后我们在第12行处引入这些设置.
在我们启动服务器之前,我们需要启动MongoDB实例。如果你是MongoDB新手,可以看看这个http://thejackalofjavascript.com/mapreduce-in-mongodb/#mongodb
一旦MongoDB启动,我们将通过下面的命令开启服务器
node server.js
如果MongoDB开启并运行了,你应该就能看到成功的信息。否则你将看到一堆错误。
这是一个简单的实现离线功能的代理服务器。在我们更进一步之前,我们将更新我们的服务器变成一个实时的代理服务器。使用下列代码更新server.js
var mosca = require('mosca')
var settings = {
port: 1883,
persistence: mosca.persistence.Memory
};
var server = new mosca.Server(settings, function() {
console.log('Mosca server is up and running')
});
server.published = function(packet, client, cb) {
if (packet.topic.indexOf('echo') === 0) {
return cb();
}
var newPacket = {
topic: 'echo/' + packet.topic,
payload: packet.payload,
retain: packet.retain,
qos: packet.qos
};
console.log('newPacket', newPacket);
server.publish(newPacket, cb);
}
这里我们钩取了一个服务器发布事件的回调,然后创建了一个新的数据包包含每个接受到的信息,然后将新的数据包发送给客户端。
现在,我们将构建一个可以发布/订阅主题的MQTT客户端。在client
文件夹内打开一个命令行。
我们的客户端将是另一个Node.js应用。在这个例子里,都是运行在同一个机器。但是在正式情况下,客户端程序将被部署到实际的设备上,比如Pi或者Arduino。以及服务器将会被部署到云中。
现在,运行
npm init
MQTT.js依赖将会被引入,运行
npm install mqtt --save
在client
文件夹内创建一个名为client1.js
的文件。我们将在本地机器中模拟两个客户端,来看事件如何运作的。在client1.js
中写入以下代码
var mqtt = require('mqtt')
// client = mqtt.createClient(1883,'localhost');
var client = mqtt.connect('mqtt://127.0.0.1:1883')
client.on('connect', function () {
client.subscribe('presence')
client.publish('presence', 'Client 1 is alive.. Test Ping! ' + Date())
console.log('Client publishing..')
client.end()
})
以下事情需要注意
- Line1:我们需要MQTT
- Line3:我们连接到服务器
- Line5:我们订阅一个名为“presence”的主题
- Line8:我们发布一个消息到“presence”
- Line10:我们关闭客户端
我们将创建另一个客户端,来监听“presence”话题的改变。在client
文件中创建一个名为client2.js
的文件。在其中写入以下的代码
var mqtt = require('mqtt')
// client = mqtt.createClient(1883,'localhost');
client = mqtt.connect('mqtt://127.0.0.1:1883')
client.subscribe('presence');
client.on('message',function(topic,message){
console.log(message.toString());
});
console.log('client started ...');
和client1.js
一样,除了这个客户端只是监听主题的改变
为了测试这个,第一步我们将开启服务器。运行
node server.js
然后你应该能够看到服务器开启日志。然后运行 client2
node client2.js
你应该能看到客户端开启日志。最后运行 client1
node client1.js
服务器命令行应该会有反映
1.png最后的数据包是我们“presence”主题。以及client2 命令行应该看到这个
2.png简单明了的基于MQTT协议的会话!
你可以在这里看到这个例子的完整代码。https://github.com/klren0312/moscaTest
可以看Matteo Collina 的视频,关于他现场编码一个机器人以及通过网页控制它 – LXJS 2014
翻墙观看:https://www.youtube.com/embed/BxJ-27Nnakc?rel=0
希望这篇文章能给你一些关于如何在Node.js中使用MQTT的思路。
@arvindr21