rf框架引用python文件 python rfcomm_树莓派怎么退出python


作为一个技术宅,不在业余时间折腾折腾,总觉得浑身不得劲,能够利用自己的知识,使自己的生活更加舒适便捷,这也会带来极大的满足感,智能家居项目就是这样一种项目,通过自己的奇思妙想,搭建符合自己和家人生活习惯的贴近生活的小设备是非常有意思的一件事情。
而在搭建这样系统的过程中,我们也可以从中学到更多的技术知识,增加自己的技术储备。在这篇文章中,我们将以树莓派为载体,使用Python搭建一个最基础的智能家居设备(温湿度传感器 + 电脑远程唤醒),目的是通过手机APP能够观察到室内温度湿度,并且可以通过APP远程唤醒自己的NAS服务器。
本项目将分上下两部分来讲解,通过阅读你将了解到MQTT的基础知识,以及如果在树莓派上使用Python将其运用起来。

1. 项目背景

因为家里的电脑和手机等终端设备越来越多,在不同的终端之间拷贝数据变得非常繁琐,所以,早在几年前,就搭建了中央存储,姑且称为NAS把,不过并没有选择成品NAS,而是选择了一台小型的塔式服务器,采用Linux系统,并搭建了Nextcloud,Plex,Git,Jenkins等系统。随着时间的推移,NAS上边的资料越来越多,硬盘内存也陆续有升级,开始意识到监控服务器的状态变得重要起来,刚好手上有一个吃灰的树莓派Zero (Raspberry Pi Zero),想来可以旧物利用,搭建一个监控系统。

你可能会想到,为什么不直接在服务器上边搭建监控呢,那是因为考虑到功耗和节省能源,服务器被设定为定时睡眠,只有需要访问的时候才启动,而监控系统最好是24×7在运转,而树莓派的功耗非常低,非常适合24×7的场景。因此,我在树莓派上搭建了基于Nagios的监控系统,用于监控服务器和路由器的状态。树莓派的基础知识,和Nagios的搭建不是这篇文章的重点,如果没有听说过树莓派的童鞋可以去搜索一下,教程有很多,基本上它就是一个体积非常小的Linux设备,另外还提供了GPIO,UART,SPI等等IO和通讯接口,支持控制外部设备。

当树莓派监控系统运行起来以后,本着技术宅抠门的优良传统,总希望物尽其用,不能白白浪费电吧,于是乎想在智能家居上边做做文章,但是智能家居范围很广,有很多功能是需要比较大的改造的,因此我们从最简单的功能开始:

  1. 服务器远程控制功能 – 支持远程唤醒服务器
  2. 温湿度器 – 通过传感器读取室内温湿度,并可以在手机上展示出来

下边这左图为硬件,右图为手机App显示效果,由于使用了MQTT这个物联网的常用协议,因此可以在公网上获取到家里的温湿度信息,并控制服务器。


rf框架引用python文件 python rfcomm_树莓派 python_02


rf框架引用python文件 python rfcomm_rf框架引用python文件_03


2. 什么是MQTT

MQTT是一种基于发布/订阅(publish/subscribe)模式的”轻量级”通讯协议,该协议构建于TCP/IP协议上,由IBM在1999年发布。MQTT最大优点在于,可以以极少的代码和有限的带宽,为连接远程设备提供实时可靠的消息服务。作为一种低开销、低带宽占用的即时通讯协议,使其在物联网、小型设备、移动应用等方面有较广泛的应用。

MQTT的构架如下图所示,在MQTT的通信中,有两个角色:

  • Broker – 负责分发消息
  • Client – 客户端,连接到Broker上边,通过Broker可以实现客户端之间的消息传递

而MQTT的消息的承载方式是Topic(话题),然后客户端通过发布一个话题来将特定话题的消息内容发送给Broker,其他的客户端可以预先订阅该话题,只有订阅了该话题的客户端会收到别的客户端发布出来的话题内容。

因此可以看出所有的客户端都是相同的,没有主没有从,任何客户端都可以发送消息,也可以订阅任意的话题,应用程序的目的就是通过合理的设计话题和内容,从而实现我们的需求。


rf框架引用python文件 python rfcomm_rf框架引用python文件_04


在上图上,最左边的温度传感器向Broker用temperature话题发送了温度值24度,另外两个客户端(手机App,和Web后端)因为订阅了这个话题,所以可以接收到温度值24度。

从上边我们看出,一个使用MQTT的系统需要有Broker和Client两部分组成,Client就是我们的应用程序,而Broker一般有成熟的产品,MQTT的官网是:https://mqtt.org/ ,在官网上我们可以找到Broker软件,Mosquito,另外官网也提供了Client上可以使用的不同语言的API库,而本文中使用的 paho.mqtt.python 也可以在里边找到。

在这篇文章中,我们将着眼于自己编码实现客户端的功能,而不涉及Broker服务器的部署,不过我们还是需要一个Broker服务器才能够让整个系统运作起来,有两种办法:

  • 自己购买云主机,并在上边部署Mosquito服务
  • 使用一些共用的MQTT测试Broker,比如由hivemq提供的共用Broker,可以在这个链接中找到 https://www.hivemq.com/public-mqtt-broker/

我们将使用第二种方式,在上边链接可以找到Broker的信息:

  • Broker: broker.hivemq.com
  • TCP Port: 1883
  • Websocket Port: 8000

3. 系统框架

MQTT是整个项目的核心,了解了MQTT的基本原理以后,我们就可以把这个简单的系统框架画出来了。

手机和树莓派将作为MQTT的Client连接到MQTT的Broker上边,这样就实现了从公网读取和控制局域网内设备。

而服务器和树莓派属于同一个局域网,因此树莓派可以通过局域网对服务器进行监控和控制。

在树莓派上我们连接了温湿度传感器用于读取室内温湿度,我们选择的传感器型号为DHT11。


rf框架引用python文件 python rfcomm_树莓派怎么退出python_05


3. MQTT话题设计

我们前边讲了,MQTT是这个项目的核心,系统中的所有的参与放都将由MQTT根据Broker转发过来的信息执行相应的动作,因此我们要在实际编码前设计好MQTT通讯协议,这里主要就是话题(Topic)和话题里边的消息内容的格式。

通讯模式

首先,我们希望通过手机发送命令能够控制某个客户端的行为,更直观的讲就是,我们希望客户端在收到一个消息以后,可以根据消息的内容执行一段函数。另外执行的结果,我们希望执行该动作或函数的客户端能够返回给请求方(也就是手机)。比如说,我们想通过手机发送的命令来唤醒服务器。

另外,我们还希望某些客户端可以周期性主动的发送一些状态出来。比如说,我们想在手机中周期性的获得当前的室温。

针对这两种情况,我们设计两种通讯模式:

  • 主从模式(问答模式),即请求方发送命令给接收方,接收方根据命令调用函数执行动作,并把结果返回请求方
  • 广播模式,即一个客户端定期的广播一些消息出来,感兴趣的客户端可以订阅这些广播消息,并作出相应的处理(显示或者调用函数执行动作)

话题

针对设计好的这两种通讯模式,我们来设计信息的载体,也就是话题(Topic),MQTT的所有的消息都是通过话题来区分的,话题可以被认为是消息的分类,或者通道,只有客户端订阅了某个话题以后,它才能收到别的客户端发到这个话题上的消息。

MQTT的话题通过 / 分隔的字符串来表示,比如说 home/garden/fountain 这就是一个话题。MQTT设计了两个通配符+号和#号, +号代表任意单词,#代表任意级的单词。比如home/+/fountain可以匹配到home/garden/fountain这个话题,同样home/#也可以匹配到home/garden/fountain这个话题。

通常我们要设计使用跟应用场景相关的单词,并在层级递进,比如前边这个例子 home的范围最大,garden次之,fountain最小最精确的范围,解释为家里的花园里边的花坛。我们的话题也遵循类似的设计。

  • 命令话题(主从模式):home/+/command,代表我们要向家里边的某一个客户端(+可以匹配不同的客户端名称)发送命令,比如我们要向家里的nextcloud服务器发送命令可以使用 home/nextcloud-server/command 话题
  • 响应话题(主从模式):home/+/response,代表某一个客户端针对之前收到的命令发送其处理结果,如果nextcloud在处理完命令后,可以使用 home/nextcloud-server/response 来将它的处理结果发送出来
  • 广播模式:home/+/status/#,代表我们家里的某一个客户端将它的某一个状态发送出来,比如 我们的树莓派可以使用 home/pi-zero-dht11/status/temperature话题来将它测得的温度发送出来,感兴趣的客户端都可以订阅这个话题

消息格式

众所周知Python可以很方便的处理JSON格式,因此我们的话题消息内容将采用JSON格式,接下来我们要定义JSON的格式。同样我们还是按照之前定义好的通讯模式来讨论。

  • 命令话题消息(主从模式):在命令消息中,我们主要希望能够携带需要客户端执行的命令,也就是函数名,另外就是函数使用到的参数,因此我们可以采取下边示例所示的格式

"parameter": ["true", "false"]

JSON中的name表示我们希望订阅该话题的客户端调用的函数,parameter里边包含该函数的参数。

  • 响应话题消息(主从模式):在响应消息中,我们主要希望携带命令处理结果,一般就是成功与否,或者一些文字信息,因此我们可以简单的使用value字段就行,如下:
  • 广播消息(广播模式):在广播消息中,一般要携带该条消息中需要体现的客户端状态信息,根据不同的场景需要特别设计,就本文讨论的温湿度信息而言,我们只需要使用一个value字段携带当前的温度值或湿度值就可以了。

4. 总结

我们在本文中讲解了为什么要这个项目,以及这个项目需要的必要的知识点,最后基于这些知识点,我们设计了系统的框架,和通讯模式,我们会在下篇文章中带领大家一起编码,并讲解编码过程中的要点,跟大家一起完成这个项目。