前言
前几天在mblock为光环板写了一个MQTT的扩展,可以让光环接通过mqtt协议连接到Easyiot物联网平台,可实现发布和订阅消息。当然也可以通过物联网平台,控制其他物联网设备(eg:光环板语音控制掌控板)。
最近不是树莓派日(3.14)嘛!自己也想着为社区做点贡献,就做一个树莓派连接EasyIOT的教程吧!
MQTT的工作原理
MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅(publish/subscribe)模式的"轻量级"通讯协议,该协议构建于TCP/IP协议上,由IBM在1999年发布。MQTT最大优点在于,可以以极少的代码和有限的带宽,为连接远程设备提供实时可靠的消息服务。作为一种低开销、低带宽占用的即时通讯协议,使其在物联网、小型设备、移动应用等方面有较广泛的应用。
MQTT是一个基于客户端-服务器的消息发布/订阅传输协议。MQTT协议是轻量、简单、开放和易于实现的,这些特点使它适用范围非常广泛。在很多情况下,包括受限的环境中,如:机器与机器(M2M)通信和物联网(IoT)。其在,通过卫星链路通信传感器、偶尔拨号的医疗设备、智能家居、及一些小型化设备中已广泛使用。
中介承担着转发MQTT 通信的服务器的作用。相对而言,发布者和订阅者则起着客户端的作用。发布者是负责发送消息的客户端,而订阅 者是负责接收消息的客户端。MQTT 交换的消息都附带“主题”地址,各个客户端把这个“主题”视为收信地址,对其执行传输消息的操作。 形象地比喻一下,中介就是接收邮件的邮箱。
中介在等待各个客户端对其进行连接。订阅者连接中介,把自己想订阅的主题名称告诉中介。这就叫作订阅。 然后发布者连接中介,以主题为收信地址发送消息。这就是发布。发布者一发布主题,中介就会把消息传递给订阅了该主题的订阅者。
如上图所示,如果订阅者订阅了主题A,那么只有在发布者发布了主题A 的情况下,中介才会把消息传递给订阅者。订阅者和中介总是处于 连接状态,而发布者则只需在发布时建立连接,不过要在短期内数次发布时,就需要保持连接状态了。因为中介起着转发消息的作用,所以各 个客户端彼此之间没有必要知道对方的IP 地址等网络上的收信地址。又因为多个客户端可以订阅同一个主题,所以发布者和订阅者是一 对多的关系。在设备和服务器的通信中,设备相当于发布者,服务器则相当于订阅者。
题采用的是分层结构。用“#”和“+”这样的符号能指定多个主题。如上图所示,/Sensor/temperature/# 中使用了“#”符号,这样就 能指定所有开头为/Sensor/temperature/ 的主题。此外,/Sensor/+/room1中使用了符号“+”,这样一来就能指定所有开头是/Sensor/、结尾是/room1 的主题。
MQTT原理转载至 [图解物联网 / 日本NTT DATA集团等著;丁灵译. --北京:人民邮电出版社, 2017.4]
准备阶段
我们在掌控板和光环板这些ESP32或者ESP8266类型芯片中(前提刷入MicroPython-lib),主要用到的是umqtt.simple库具体API及样例程序可以参照此链接
好了废话不多说,现在我们开始配置我们的树莓派环境吧,let's GO
更新下系统,更新前记得改国内源,不知怎么更换的看这贴:http://bbs.hassbian.com/thread-27-1-1.html
sudo apt-get update
sudo apt-get upgrade -y
在终端输入以下命令确认pip是否已经安装:
pip -V
输入以下命令安装mqtt包:
sudo pip install paho-mqtt
这样我们的paho-mqtt库就安装完成,具体Python paho-mqtt 模块使用和API分析请点击此连接里面对paho-mqtt的API讲解很清楚,我这里就不一一概述了,下文中只会针对自己的用到的函数,做简单的讲解
一般客户端使用流程
创建一个客户端实例;
1、使用connect方法连接broker;
2、调用loop方法(注:loop包含loop,loop_forever,loop_start);
3、使用subscribe方法订阅某个主题;
4、使用publish方法向某个主题发布消息到broker;
5、使用disconnect方法断开和broker的链接
6、还有一个重要的概念就是callback,程序可能在某些事件触发时需要做一些操作,这些操作就可以放入回调方法中。
发布程序测试
# encoding: utf-8
import paho.mqtt.client as mqtt
import time
server = "182.254.130.180"
port = 1883
iot_id = "填写自己的用户名"
iot_pwd = "填写自己的用户密码"
topic = "填写自己的设备名"
def test(msg):
client_id = time.strftime('%Y%m%d%H%M%S',time.localtime(time.time())) # 以当前时间作为client_id
client = mqtt.Client(client_id) # ClientId不能重复,所以使用当前时间
client.connect(server,port , 30) #设置连接的服务器、端口及keepalive
client.username_pw_set(iot_id, iot_pwd) # 设置连接用户和密码,必须设置,否则会返回Connected with result code 4
client.publish(topic,msg,1) # 向topic发送msg信息
client.loop_start()
if __name__ == '__main__':
while True:
message = input("please input your message")
test(message)
测试结果:
订阅程序测试
作为一个接收者,同一个主题没有发布(pub)信息的时候,就自己一直等候。
#coding: UTF-8
import paho.mqtt.client as mqtt
import time
server = "182.254.130.180"
port = 1883
iot_id = "填写自己的用户名"
iot_pwd = "填写自己的用户密码"
topic = "填写自己的设备名"
def on_connect(client, userdata, flags, rc):
client.subscribe(topic) # 填写订阅的主题
def on_message(client, userdata, msg):
print(msg.topic+" " + ":" + str(msg.payload)) # 打印接受的消息
def on_publish(topic, payload, qos):
client.publish(topic, payload, qos)
def main():
client_id = time.strftime('%Y%m%d%H%M%S',time.localtime(time.time())) # 以当前时间作为client_id
client = mqtt.Client(client_id) # ClientId不能重复,所以使用当前时间
client.username_pw_set(iot_id, iot_pwd) # 设置连接用户和密码,必须设置,否则会返回Connected with result code 4
client.on_connect = on_connect
client.on_message = on_message
client.connect(server, port, 30) # 1883为服务端口号,如果是安全认证,端口号需要修改为1884
client.loop_forever()
if __name__ == '__main__':
main()
测试结果:
注意事项
loop()方法在MQTT客户端中也非常重要,它主要是用来去查询消息缓存区。当有新的消息到达时,这些消息会存储在接收缓存区,等待有客户端程序去读取。loop()方法就是一个内置的读取接收和发送缓存区,并分发消息的方法。简单说就是,如果不loop,也不自己去主动读取接收缓存区,就触发不了回调函数,所以要记着写上loop。
Paho python client中提供了3个方法:
loop_forever() --会阻塞程序,其实是周期调用loop()方法,如果程序需要一直处于订阅中的话,可以用这个方法,它也会对客户端进行重连。
loop_start() --会新起一个thread,这个thread会调用loop_forever(),所以也会周期调用loop(),并且会保证客户端自动re-connect
loop() --这个方法只会loop指定的时间(默认1s),只会就结束,不会继续去读取缓存区,所以如果在程序中使用的话,需要自己写个周期调用,并且还要自己处理re-connect上面2个loop方法都可以通过loop.stop()方法来停止。
总结
通过MQTT协议,也就可以让我的树莓派万物互联啦!比如做一个人脸识别小区门禁,实时上传小区业主出入进的数据到物联网平台等等,搞定了物联网部分,其他的创意就留给你们啦!