一、如何建服务器
(说是服务器应该是Broker更合适,下面全文都使用broker来表示这里的服务器)
因为终端设备不多,不用过多考虑性能问题和算法优化,所以直接用的是本地的PC作为MQTT的。在许多主流平台如mosquitto,VerneMQ,EMQTT中,我选择了Mosquitto
1、安装下载mosquitto
- Download | Eclipse Mosquitto官网下载,选择你需要的版本,我是在windows上操作的.下载之后,安装到你要安装的路径下即可
注:这里建议将mosquitto加入到环境变量中,会更方便操作一些,在加入之后可以直接在cmd中进行命令操作。不加也没有大影响,切入到刚刚安装的mosquitto文件夹下,直接运行exe文件也可以。
2、简单的测试一下
更要的是,-h查看一下所有的选项,后面代码中会有使用
如果是向上面这样,那么就是添加环境变量或者安装成功了
⚠️:注意,修改环境变量之后,要重新打开shell或者cmd窗口才能生效
3、使用python启动该任务(线程)
从上面的第一张图(-v)中可以看到,这里已经在本地(localhost)的1883端口上开启了MQTT服务器。
所以说,这样是可行的,但是我想要将所有的功能能够一体化,而不是一边打开一个shell开启broker,一边打开一个QT作为测试。两者要想结合在一起,就要让所有的事情都在代码里完成,所以,下面来看一下怎么在python里面去运行相应的exe文件
(不过如果你只是直接在命令行启动的话,那么按照下面的操作也是一样的,只是直接在命令行窗口操作,更简单)
- 使用subprocess库。参考python subprocess-更优雅的创建子进程 - 知乎 (zhihu.com)
python代码如下(命令行操作入上两图)
import subprocess,shlex
# 定义exe文件路径和参数
exe_path = "D:\Code\mosquitto\mosquitto.exe"
conf_path = "D:\Code\mosquitto\mosquitto.conf"
com = shlex.split('{}'.format(shlex.quote(exe_path)) + ' -c ' + '{}'.format(shlex.quote(conf_path)) )
# 启动进程
process = subprocess.Popen(com, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
# 等待进程执行完成
process.communicate()
如同上面help中所说,我们需要通过-c方法将配置导入(配置.conf文件可以在你所安装mosquitto的目录下找到)
对于配置的修改有两种方式(主要区别于是否允许匿名连接),下面先看第一种:
第一种(允许匿名连接)
-
修改监听端口
其中1883为监听的端口,0.0.0.0表示任意地址的意思。组合起来,也就是说,允许任何ip地址的设备访问到该MQTTbroker。
你也可以进行修改,选择自己想要的端口和允许的ip。
-
允许匿名连接
按照上面的方法去配置完成之后,启动broker,client再去连接broker即可,这里主要演示树莓派端(因为我的broker用的是本机PC)
mqtt_client = mqtt.Client(client_name) def on_connect(client, userdata, flags, rc): if rc == 0: print("Connected to MQTT Broker!") else: print("Failed to connect, return code %d\n", rc) mqtt_client.on_connect = on_connect mqtt_client.connect('your host',port=1883) mqtt_client.loop_start()
这里是client端的连接主要代码。如上。为了检测连接是否成功,所以在on_connect函数中加入一些提示信息
如果成功的话,会输出
Connected to MQTT Broker!
否则,会提示
一些error,比如timeout,拒绝访问 或者是提示语句Failed to connect, return code --
如果出现错误,请仔细检查跑起来了broker和conf配置是否正确
第二种(不允许匿名连接)
-
修改监听端口
和第一种一样
-
不允许匿名连接
与上面不同,这里修改为false,也就是不允许匿名连接
-
注册用户
既然不允许匿名连接,那么就需要为每个连接进来的设备(client)分配一个账号和密码
先按照如下去操作
切换到mosquitto目录下,输入如下代码,之后会提示你输出和确认密码
.\mosquitto_passwd.exe -c .\piPass.txt username
- 其中.\piPass.txt位置,是用来存放账户密码的文件,可以自己命名
- username是你准备为client分配的设备名,这个也是你自己决定
请注意⚠️:-c会清除整个文件,只留下该次写入的用户,如果你想继续添加用户,请不要加-c。
.\mosquitto_passwd.exe .\piPass.txt username2
从上面也可以看到,-c会overwrite整个文件。
同样的,如果你想删除或者更新(这里是重新对密码进行hash的意思),都可以参考进行操作。不过请不要在这样添加用户之后,再-U刷新,这样会导致已经进行hash的密码再次hash计算,会使用户的密码失效。
那么为什么留下这个-U呢,接着看下面的。
-
配置conf
当有设备请求连接时,broker需要去该文件中,查找是否有该文件。所以需要为broker指明道路
在这里加入对应的路径即可。
-
client设置账号密码登录
mqtt_client = mqtt.Client(client_name) def on_connect(client, userdata, flags, rc): if rc == 0: print("Connected to MQTT Broker!") else: print("Failed to connect, return code %d\n", rc) mqtt_client.on_connect = on_connect mqtt_client.connect('your host',port=1883) mqtt_client.username_pw_set("your username","your password") mqtt_client.loop_start()
好了如此之后,你的client应该就可以连接到broker了。
再将telemetry和server分别连接到该Broker即可完成通信
OK——————————到这里,两种配置就到此结束了,broker也可以运行并被连接上了。那么下面我们来解决一下一些遗留问题
-
-U有什么用
我们说过,-U用来对密码进行hash,但是我们通过mosquitto_passwd写入的密码,会自动将其hash。所以再次-U后就会二次hash,导致密码失效。
所以只要在原密码上进行hash就可以了
在conf文件上有写这样一段话,这里(544)说到了账户密码的设置格式,所以,我们只要直接在我们要储存账号密码的文件中直接添加就行。像这样
然后,再进行-Uhash就可以不用在命令行一个个用户添加了,对于多client会更方便。
⚠️:不要有多的空行,如下是不行的(若是这样执行,会报错
Error: Corrupt password file at line 2.
,实践出真知,可以自己试一下) -
我们将mosquitto添加到环境变量中,有什么用
这一点请参考subprocess的Popen和run两个方法的使用。这在上面提到的知乎的那篇文章中,讲的很清楚。
所以,我们可以这样去写我们的代码。不过值得注意的是,这样创造出来的进程是没有communicate()方法的
process = subprocess.run(['mosquitto','-c',conf_path], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
用。这在上面提到的知乎的那篇文章中,讲的很清楚。
所以,我们可以这样去写我们的代码。不过值得注意的是,这样创造出来的进程是没有communicate()方法的
process = subprocess.run(['mosquitto','-c',conf_path], stdout=subprocess.PIPE, stderr=subprocess.PIPE)