Never too late to learn.

0%

在ESP8266(Arduino IDE),CentOS(mosquitto)上部署和使用MQTT

介绍 Introduction

MQTT is a machine-to-machine (M2M)/“Internet of Things” connectivity protocol. It was designed as an extremely lightweight publish/subscribe messaging transport. It is useful for connections with remote locations where a small code footprint is required and/or network bandwidth is at a premium. —from “mqtt.org”

关于mqtt的介绍,网上资料很多,可以去MQTT官网了解,同时推荐一个讲的很形象的介绍,MQTT Introduction and Tutorial Part One。总之,mqtt的诸多优势使其在物联网信息传输上占有相当重要的地位,关于它跟其它的传输协议的差别,物联网通信协议的详解及选择建议里有较为详尽的分析,供参考。本篇主要是通过实地部署来演示MQTT的一个基本工作情况,和使用方法。

环境和实现

我们知道MQTT协议是Client通过向Sever(or Broker)订阅和发布Topic(主题)来实现物联网设备的相互通讯,在本次试验中,我们有:

  • 硬件:
    乐鑫ESP8266 wifi模块;
  • 软件:
    Arduino IDE, 操作系统:Win 10 x64
    阿里云ECS主机,操作系统:CentOS 7

具体实现是ESP8266作为一个物联网设备,ECS主机同时作为Sever和另一个Client(博主资源有限,切莫吐槽:)),ESP8266作为Client1订阅Topic2主题,同时推送Topic1消息给Sever,然后在ECS上的Client2使用。。。

Broker的搭建

如果你想部署一个Broker,开源的MQTT Mosquitto是非常不错的选择,至于其他的Moquette,Apollo,RabbitMQ等单机版本,以及EMQTT分布式版本,不列入讨论内容(因为不懂,[哈哈])。下载地址:https://mosquitto.org/download/

对于Windows,有Binary Installation,但是我没装成功[囧],不过这不重要,一般windows也不在物联网方面发挥什么作用,忽略;对于Mac,看官网自行安装吧,对Mac OS不熟;对于Linux,我云主机运行的是CentOS 7.0,使用最简单的yum安装,这里详细介绍一下步骤:

1.先加入yum源:

在/etc/yum.repos.d/目录中新建一个mosquitto.repo文件,并在里面写入:

1
2
3
4
5
6
7
[home_oojah_mqtt]   
name=mqtt (CentOS_CentOS-7)
type=rpm-md
baseurl=http://download.opensuse.org/repositories/home:/oojah:/mqtt/CentOS_CentOS-7/
gpgcheck=1
gpgkey=http://download.opensuse.org/repositories/home:/oojah:/mqtt/CentOS_CentOS-7//repodata/repomd.xml.key
enabled=1

熟悉命令的可以直接下载到服务器中重命名:
http://download.opensuse.org/repositories/home:/oojah:/mqtt/CentOS_CentOS-7/home:oojah:mqtt.repo

2.安装mosquitto 和mosquitto-clients模块

先查找一下所有关于mosquitto的模块

yum search all mosquitto

这里先安装mosquitto和mosquitto-clients两个模块儿,其它模块以后需要再安装。

3.配置

安装完成之后,所有配置文件会被放置于/etc/mosquitto/目录下,其中最重要的就是Mosquitto的配置文件,即mosquitto.conf,自定义的配置文件放在/etc/mosquitto/conf.d/文件夹中,文件以.conf为扩展名。详细的配置参数参考mosquitto.conf.example文件

4.启动

两种方式:

mosquitto -c /etc/mosquitto/mosquitto.conf -d
sudo /etc/init.d/mosquitto start

而我选择:

mosquitto

简单粗暴;),可以加上-v参数打印log,mosquitto具体操作命令自行-help

5.发布消息

mosquitto_pub -t “pubTopic” -m “pubMessage”

-t 指定主题参数

-m 指定消息内容

6.订阅主题

mosquitto_sub -t “subTopic”

-t 指定主题参数

Client的搭建

Client的搭建分别使用Arduino端的PubSubClient库和python版本的Paho Python Client库。他们都是开源的,使用非常容易,可以轻松几行代码实现pub和sub操作,下面分别介绍一下。

PubSubClient for Arduino IDE

PubSubClient库提供一个简单的客户端,支持MQTT的服务器订阅和发布消息,其中有对ESP8266专门的支持。

安装

在Arduino IDE上安装库是很简单便捷的,可以手动从GitHub上下载,复制到库目录,也可以使用库管理器Library Manager搜索安装,Simple!
【配图】

Code 和部署

直接使用库里的例程进行简单的修改即可建立客户端,(关于wifi链接代码非本文重点,不再列出):

打开…/pubsubclient/examples/mqtt_esp8266/mqtt_esp8266.ino

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#include <PubSubClient.h>

const char* mqtt_server = "hostname";

WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msg[50];
int value = 0;

void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
}
Serial.println();

// Switch on the LED if an 1 was received as first character
if ((char)payload[0] == '1') {
digitalWrite(BUILTIN_LED, LOW); // Turn the LED on (Note that LOW is the voltage level
// but actually the LED is on; this is because
// it is acive low on the ESP-01)
} else {
digitalWrite(BUILTIN_LED, HIGH); // Turn the LED off by making the voltage HIGH
}

}

void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Create a random client ID
String clientId = "ESP8266Client-";
clientId += String(random(0xffff), HEX);
// Attempt to connect
if (client.connect(clientId.c_str())) {
Serial.println("connected");
// Once connected, publish an announcement...
client.publish("topic1", "hello world");
// ... and resubscribe
client.subscribe("topic2");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}

void setup() {
pinMode(BUILTIN_LED, OUTPUT); // Initialize the BUILTIN_LED pin as an output
Serial.begin(115200);
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
}

void loop() {

if (!client.connected()) {
reconnect();
}
client.loop();

long now = millis();
if (now - lastMsg > 2000) {
lastMsg = now;
++value;
snprintf (msg, 75, "hello world #%ld", value);
Serial.print("Publish message: ");
Serial.println(msg);
client.publish("topic2", msg);
}
}

代码中ESP8266每两秒发布一条”Publish message: hello world#”信息给Server的topic1,同时订阅topic2的信息,如果有推送到topic2的信息,将会自动推送到ESP8266,并将推送信息从串口打印出来。

下载固件到ESP8266中,打开串口工具监视串口数据;
[配图]

Python Client

Paho Python Client是Mosquitto官方提供的MQTT的python客户端,支持MQTT v3.1和v3.1.1 在Python 2.7 or 3.x环境下的开发,可以方便的使用Python开发mqtt服务。由于只有一台主机,所以重开一个终端,主机环境Python 2.7.5。

安装

可以使用pip工具从PyPI下载和安装Python client:

pip install paho-mqtt
也可以从仓库下载和安装:
git clone https://github.com/eclipse/paho.mqtt.python.git
cd org.eclipse.paho.mqtt.python.git
python setup.py install

配置和部署

可以根据官方给出的简单例子写一个Python文件来建立一个链接到特定服务器并发布(publish)和订阅(Subscribe)不同主题(topic)消息的客户端。

这里新建一个mqtt_client.py文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import paho.mqtt.client as mqtt

# The callback for when the client receives a CONNACK response from the server.
def on_connect(client, userdata, rc):
print("Connected with result code "+str(rc))
# Subscribing in on_connect() means that if we lose the connection and
# reconnect then subscriptions will be renewed.
client.subscribe("topic1/#")
# 订阅,参数为订阅的主题

# The callback for when a PUBLISH message is received from the server.
def on_message(client, userdata, msg):
print(msg.topic+" "+str(msg.payload))

client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message

client.connect("iot.eclipse.org", 1883, 60)
# 链接到Mosquitto所在的服务器,第一个参数为Server地址;第二个是端口号,默认mqtt是1883;第三个参数是保持连接(keepAlive)时间,单位为秒

# Blocking call that processes network traffic, dispatches callbacks and
# handles reconnecting.
# Other loop*() functions are available that give a threaded interface and a
# manual interface.
client.loop_forever()

then,执行这个文件

python mqtt_client.py

[配图]

参考官网mosquitto

Coffee? ☕