现在,我们将使用Python作为主要的编程语言来生成将充当发布者和订阅者的MQTT客户端。 我们将Python MQTT客户端连接到MQTT服务器,并处理命令以使用MQTT消息控制小型车辆。 小型车辆具有现实道路车辆所具有的许多功能。
我们将使用TLS加密和TLS身份验证,因为我们不希望任何MQTT客户端能够向我们的车辆发送命令。
根据平台的不同,每辆车都将提供其他功能,因为某些板比其他板功能更强大。 但是,我们将专注于基本功能,以使我们的示例保持简单并专注于MQTT。 然后,我们将能够将该项目用作其他解决方案的基准,这些解决方案要求我们在运行Python 3.x代码的IoT板上运行代码,必须连接到MQTT服务器并处理命令。
为车辆供电的板上运行的代码必须能够处理特定主题消息中收到的命令。 我们将在有效负载中使用JSON字符串。
同样用Python编写的客户端应用程序必须能够控制一个或多个车辆。 我们还将使用Python编写客户端应用程序,它将使用JSON字符串将MQTT消息发布到每个车辆的主题。 客户端应用程序必须显示执行每个命令的结果。 每当成功执行命令时,每辆车都必须向特定主题发布消息。
定义主题和命令
我们将使用以下主题名称来发布车辆的命令:vehicles/vehiclename/commands,其中必须用分配给车辆的唯一名称替换车辆名称。 例如,如果我们为使用Raspberry Pi 3 Model B +板的车辆指定了vehiclepi01作为名称,则必须将命令发布到vehicle/vehiclepi01/commands主题。 在该板上运行的Python代码将订阅该主题,以接收带有命令的消息并对其作出反应。
我们将使用以下主题名称来使车辆发布有关成功执行的命令的详细信息:vehicles/vehiclename/executedcommands,其中必须用分配给车辆的唯一名称替换车辆名称。 例如,如果我们将vehiclebeagle03分配为由BeagleBone Black板的车辆的名称,则想要接收有关成功处理的命令的信息的客户端必须订阅vehicle/vehiclebeagle03/executedcommands主题。
命令将以带有键值对的JSON字符串发送。 密钥必须等于CMD,并且值必须指定以下任何有效命令。 当命令需要其他参数时,参数名称必须包含在下一个键中,并且此参数的值应包含在该键的值中:
- TURN_ON_ENGINE:打开车辆的引擎
- TURN_OFF_ENGINE:关闭车辆的引擎
- LOCK_DOORS:关闭并锁上车门
- UNLOCK_DOORS:解锁并打开车门
- PARK:停车
- PARK_IN_SAFE_PLACE:将车辆停放在为车辆配置的安全地方
- TURN_ON_HEADLIGHTS:打开车辆的大灯
- TURN_OFF_HEADLIGHTS:关闭车辆的大灯
- TURN_ON_PARKING_LIGHTS:打开车辆的停车灯,也称为侧灯
- TURN_OFF_PARKING_LIGHTS:关闭车辆的停车灯,也称为侧灯
- ACCELERATE:加速车辆,即踩油门踏板
- BRAKE:制动车辆,即踩下制动踏板
- ROTATE_RIGHT:使车辆向右旋转。 我们必须在DEGREES键的值中指定我们希望车辆向右旋转多少度
- ROTATE_LEFT:使车辆向左旋转。 我们必须在DEGREES键的值中指定我们希望车辆向左旋转多少度
- SET_MAX_SPEED:设置我们允许车辆的最高速度。 我们必须在MPH键的值中指定所需的最大速度(以英里/小时为单位)
- SET_MIN_SPEED:设置我们允许车辆的最低速度。 我们必须在MPH键的值中指定所需的最小速度(以英里/小时为单位)
下一行显示了用于打开车辆引擎的命令的有效负载的示例:
{'CMD': 'TURN_ON_ENGINE'}
下一行显示了该命令的有效负载示例,该命令将车辆的最大速度设置为每小时五英里:
{'CMD': 'SET_MAX_SPEED', 'MPH': 5}
我们具有所有必要的详细信息,以便开始使用Python进行编码。
安装paho-mqtt
Eclipse Paho项目提供了MQTT的开源客户端实现。 该项目包括一个Python客户端,也称为Paho Python客户端或Eclipse Paho MQTT Python客户端库。 该Python客户端来自Mosquitto项目,最初被称为Mosquitto Python客户端。
我们将使用pip installer安装paho-mqtt 1.3.1。 我们只需要在用于开发板的SSH终端或本地终端窗口中,或者在用于安装软件包的计算机上运行以下命令:
pip install paho-mqtt==1.3.1
如果在Windows的默认文件夹中安装了Python,并且您没有使用Python虚拟环境,则必须在管理员命令提示符中运行上一个命令。 如果您不在Raspbian中使用Python虚拟环境,则必须使用sudo作为前缀运行前面的命令:sudo pip install paho-mqtt。 但是,如前所述,强烈建议使用虚拟环境。
输出的最后几行将指示paho-mqtt软件包1.3.1版已成功安装。 输出将与以下各行相似,但不完全相同,因为输出会根据运行命令的平台而有所不同:
Collecting paho-mqtt==1.3.1
Downloading paho-mqtt-1.3.1.tar.gz (80kB)
100% |################################| 81kB 1.2MB/s
Installing collected packages: paho-mqtt
Running setup.py install for paho-mqtt ... done
Successfully installed paho-mqtt-1.3.1
使用paho-mqtt连接客户端和服务器
首先,我们将使用paho-mqtt创建一个连接到Mosquitto MQTT服务器的MQTT客户端。 我们将编写几行Python代码来建立安全的连接并订阅一个主题。
首先,我们需要将在Mosquitto服务器安全中创建的以下文件复制到将用于运行Python脚本的计算机或设备上的目录中。 我们将文件保存在名为mqtt_certificates的目录中。 在要用作此示例的MQTT客户端的计算机或板上,创建board_certificates目录。 将以下三个文件复制到此新目录:
- ca.crt:证书机构证书文件
- board001.crt:客户端证书文件
- board001.key:客户端密钥
现在,我们将在主虚拟环境文件夹中创建一个名为config.py的新Python文件。 以下各行显示了此文件的代码,该代码定义了许多配置值,这些配置值将用于与Mosquitto MQTT服务器建立连接。 这样,所有配置值都包含在特定的Python脚本中。 您必须用创建的board_certificates目录的路径替换certificate_path字符串中的/ Users / gaston / board_certificates值。 另外,将mqtt_server_host的值替换为您可能决定使用的Mosquitto服务器或任何其他MQTT服务器的IP地址或主机名。
</>
现在,我们将在主虚拟环境文件夹中创建一个名为subscription_with_paho.py的新Python文件。 以下各行显示了此文件的代码,该文件与我们的Mosquitto MQTT服务器建立连接,订阅了Vehicles / vehiclepi01 / tests主题过滤器,并打印了在订阅的主题过滤器中收到的所有消息。
</>
回调
先前的代码使用最近安装的paho-mqtt版本1.3.1模块与MQTT服务器建立加密连接,订阅vehicle / vehiclepi01 / tests主题过滤器,并在我们收到主题中的消息时运行代码。 我们将使用此代码来了解paho-mqtt的基础知识。 该代码是MQTT客户端的非常简单的版本,它订阅了主题过滤器,我们肯定会在下一部分中对其进行改进。
第一行导入我们在先前编码的config.py文件中声明的变量。 第二行将paho.mqtt.client导入为mqtt。 这样,无论何时使用mqtt别名,我们都将引用paho.mqtt.client。
当我们声明一个函数时,我们将该函数作为参数传递给另一个函数或方法,或者将这个函数分配给一个属性,然后某些代码在某个时候调用该函数。 这种机制称为回调。 之所以使用名称回调,是因为代码有时会回调一个函数。 paho-mqtt版本1.3.1程序包要求我们处理许多回调,因此,了解它们如何工作非常重要。
代码声明了以下三个函数,我们稍后将其指定为回调:
- on_connect:当MQTT客户端从MQTT服务器接收到CONNACK响应时,即与MQTT服务器成功建立连接时,将调用此函数。
- on_subscribe:当MQTT客户端从MQTT服务器接收到SUBACK响应时,即成功完成订阅时,将调用此函数。
- on_message:当MQTT客户端从MQTT服务器接收到PUBLISH消息时,将调用此函数。 每当MQTT服务器基于客户端的订阅发布消息时,都会调用此函数。
下表总结了将根据从MQTT服务器接收到的响应来调用的函数:
MQTT服务器响应 | 函数调用 |
CONNACK | on_connnect |
SUBACK | on_subscribe |
PUBLISH | on_message |
主块的代码创建了代表MQTT客户端的mqtt.Client类(paho.mqtt.client.Client)的实例。 我们使用该实例与我们的MQTT服务器Mosquitto通信。 如果使用默认参数创建新实例,则可以使用MQTT 3.1版。 我们想使用MQTT 3.11版,因此,我们将mqtt.MQTTv311指定为协议参数的值。
然后,代码将功能分配给属性。 下表总结了这些分配:
属性 | 分配函数 |
client.on_connect | on_connect |
client.on_message | on_message |
client.on_subscribe | on_subscribe |
调用client.tls_set方法可配置加密和身份验证选项。 在运行client.connect方法之前,调用此方法非常重要。 我们在ca_certs,certfile和keyfile参数中指定证书颁发机构证书文件,客户端证书和客户端密钥的完整字符串路径。 ca_certs参数名称有点混乱,但是我们只需要指定证书颁发机构证书文件的字符串路径,而不是多个证书即可。
最后,主块调用client.connect方法并指定主机,端口和keepalive参数的值。 这样,代码将要求MQTT客户端建立与指定MQTT服务器的连接。
connect方法以异步执行方式运行,因此,它是一个非阻塞调用。
与MQTT服务器成功建立连接后,将执行client.on_connect属性中指定的回调,即on_connect函数。 该函数在client参数中接收与mqtt服务器建立连接的mqtt.Client实例。
如果要与不使用TLS的MQTT服务器建立连接,则无需调用client.tls_set方法。 此外,您需要使用适当的端口,而不是使用TLS时指定的8883端口。 请记住,当您不使用TLS时,默认端口为1883。
订阅主题
详情参考 - 亚图跨际