树莓派连接普通Mqtt服务器
本文介绍如何使用Python语言在树莓派上实现与普通MQTT服务器的连接,并进行双线程的消息发布和订阅。此教程将利用paho-mqtt库来完成MQTT协议下的通信任务,适用于物联网项目和爱好者。
正文
树莓派是一款小型但强大的单板计算机,常用于教育、编程学习和物联网项目。在物联网应用中,MQTT是一种轻量级的消息协议,非常适合于网络带宽受限的情况。本教程将指导您如何在树莓派上使用Python创建一个简单的MQTT客户端,实现消息的发布和订阅。
步骤1:安装paho-mqtt
首先,确保您的树莓派已经安装了paho-mqtt库。如果还未安装,可以使用以下命令进行安装:
pip install paho-mqtt
代码双线程发布订阅
以下是Python脚本的完整代码,该代码创建了一个MQTT客户端,可以连接到普通的MQTT服务器,并在两个线程之间实现消息的发布和订阅:
# -*- coding: utf-8 -*-
import paho.mqtt.client as mqtt
import time
import random
import json
import threading # 导入线程模块
# MQTT服务器地址和端口
HOST = "broker.emqx.io"
PORT = 1883
# 发布和订阅的主题
PUB_TOPIC = "test/topic/pub" # 修改为你的发布主题
SUB_TOPIC = "test/topic/sub" # 修改为你的订阅主题
# The callback for when the client receives a CONNACK response from the server.
def on_connect(client, userdata, flags, rc):
print("Connected with result code "+str(rc))
client.subscribe(SUB_TOPIC) # 订阅主题
# The callback for when a PUBLISH message is received from the server.
def on_message(client, userdata, msg):
print(f"Message received on topic {msg.topic}: {str(msg.payload)}")
# 定义发布消息的函数
def publish_data(client):
while True: # 创建一个循环来持续发送数据
payload_json = {
'id': int(time.time()),
'params': {
'temperature': random.randint(20, 30), # 随机温度
'humidity': random.randint(40, 50) # 随机相对湿度
}
}
print('Sending data to IoT server: ' + str(payload_json))
client.publish(PUB_TOPIC, payload=json.dumps(payload_json), qos=1)
time.sleep(5) # 每隔5秒发送一次数据
# 获取MQTT客户端实例
def getMQTTClient():
client = mqtt.Client()
return client
if __name__ == '__main__':
client = getMQTTClient()
client.on_connect = on_connect
client.on_message = on_message
# 连接 MQTT 服务器
client.connect(HOST, PORT, 300)
# 启动线程来发布消息
publish_thread = threading.Thread(target=publish_data, args=(client,))
publish_thread.start() # 启动线程
# 开始 MQTT 客户端的循环,处理接收到的消息和重新连接等
client.loop_forever()
添加连接失败重新连接以及天气时间上传代码
# -*- coding: utf-8 -*-
import paho.mqtt.client as mqtt
import time
import random
import json
import threading # 导入线程模块
import datetime#导入时间模块
import pytz#导入时区模块
import requests#导入requests模块
# MQTT服务器地址和端口
HOST = "broker.emqx.io"
PORT = 1883
# 发布和订阅的主题
PUB_TOPIC = "test/topic/pub" # 修改为你的发布主题
SUB_TOPIC = "test/topic/sub" # 修改为你的订阅主题
# The callback for when the client receives a CONNACK response from the server.
def on_connect(client, userdata, flags, rc):
print("Connected with result code "+str(rc))
client.subscribe(SUB_TOPIC) # 订阅主题
LED=0#全局LED状态
# The callback for when a PUBLISH message is received from the server.
def on_message(client, userdata, msg):
global LED#声明全局变量LED
print(f"Message received on topic {msg.topic}: {str(msg.payload)}")
if 'LED' in str(msg.payload):#如果收到的消息中包含LED
# 处理过程: 若信息中包含LED,截取{"LED":0/1},若为1,则点亮LED
# 代码如下:
if '1' in str(msg.payload):
#若LED已经为1,则打印LED has already been on,否则打印LED ON
if LED==1:
print('LED has already been on')
else:
print('LED ON')
LED=1#LED状态为1
else:
#若LED已经为1,则打印LED has already been off,否则打印LED off
if LED==0:
print('LED has already been off')
else:
print('LED OFF')#否则LED灭
LED=0#LED状态为0
#获取当前时间
def get_time():
tz = pytz.timezone('Asia/Hong_Kong')#设置时区为香港
now = datetime.datetime.now(tz)#获取当前时间
return now.strftime("%Y-%m-%d %H:%M:%S")#返回当前时间
# 获取香港室外真实天气
def get_hongkong_wheather():
try:
# 使用高德地图天气API(请替换成你的API密钥)
url = "https://restapi.amap.com/v3/weather/weatherInfo?city=香港&key=<请替换成你的API密钥>&extensions=base"#获取香港室外返回实况天气
#url = "https://restapi.amap.com/v3/weather/weatherInfo?city=香港&key=284cf14fad27d0155fc3502ecbe26064&extensions=all"#获取香港室外返回预报天气
response = requests.get(url)
weather_data = response.json()
# 高德API响应的数据结构不同,需要相应地提取温度和湿度数据
if weather_data["status"] == '1' and weather_data["info"] == 'OK' and "lives" in weather_data:#若获取成功
temperature = float(weather_data['lives'][0]['temperature'])#获取温度
humidity = float(weather_data['lives'][0]['humidity'])#获取湿度
windpower = float(weather_data['lives'][0]['windpower'])#获取风力
return temperature, humidity, windpower#返回温度,湿度,风力
else:
print("Error in weather data response")#若获取失败,则打印错误信息
return None, None, None#返回空值
except Exception as e:#若获取失败,则打印错误信息
print("Error retrieving weather data from AMap: ", e)#打印错误信息
return None, None, None#返回空值
# 定义发布消息的函数
def publish_data(client):
global LED#声明全局变量LED
count = 0 #计数器
temperature, humidity, windpower=None, None, None#初始化温度,湿度,风力
while True: # 创建一个循环来持续发送数据
#计入代码如果count为30的倍数以及temperature, humidity, windpower全部为None,则发送数据
if count % 30 == 0 or (temperature == None and humidity == None and windpower == None):
temperature, humidity, windpower = get_hongkong_wheather()#获取香港室外真实天气
count = 0#计数器清零
payload_json = {
'id': int(time.time()),
'params': {
'temperature': random.randint(20, 30), # 随机温度
'humidity': random.randint(40, 50), # 随机相对湿度
#加入LED状态
'LED': LED,
#加入香港室外真实温度
'hongkong_temperature': temperature,
#加入香港室外真实湿度
'hongkong_humidity': humidity,
#加入香港室外真实风力
'hongkong_windpower': windpower,
#加入当前时间
'time': get_time()
}
}
print('Sending data to IoT server: ' + str(payload_json))
client.publish(PUB_TOPIC, payload=json.dumps(payload_json), qos=1)
count += 1 # 更新计数器
time.sleep(2) # 每隔1秒发送一次数据
# 获取MQTT客户端实例
def getMQTTClient():
client = mqtt.Client()
return client
if __name__ == '__main__':
#循环直至连接成功
while True:
try:
client = getMQTTClient()
client.on_connect = on_connect
client.on_message = on_message
# 连接 MQTT 服务器
client.connect(HOST, PORT, 300)
break
except:
print('Connect failed, reconnecting...')
time.sleep(1)
print('Connected successfully!')
# 启动线程来发布消息
publish_thread = threading.Thread(target=publish_data, args=(client,))#创建线程,target为线程函数,args为线程函数的参数
publish_thread.start() # 启动线程
# 开始 MQTT 客户端的循环,处理接收到的消息和重新连接等
client.loop_forever()
步骤3:运行和测试
在您的树莓派上运行上述Python脚本。您将看到程序连接到MQTT服务器,并开始在指定的主题上发布随机生成的温度和湿度数据。同时,程序也订阅了另一个主题,用于接收可能来自其他客户端的消息。
结论
使用paho-mqtt库在树莓派上实现MQTT客户端非常简单。通过本文提供的示例代码,您可以建立一个基础的消息发布和订阅系统,进而可以根据您的项目需求进行扩展和定制。