MQTT协议发送GPS坐标到服务器
一、配置GPS
个人感觉USB的GPS好一些。感觉不好找的同学我这还有淘宝链接,卖家没给钱,只是为了方便同学们。
第一步买回来照着上图连线即可,我用了四根杜邦线:
USB的TXD连接GPS模块的RXD,USB的RXD连接GPS模块的TXD,USB的GND连接GPS模块的GND,USB的VCC连接GPS模块的VCC。连好之后GPS天线放窗外,不然没信号;USB插在树莓派上。
第二部要用树莓派读取到GPS的信号
首先查看一下这个USB,命令行输入:
ls -l /dev/tty*
安装minicom
sudo apt-get install minicom
安装好后使用minicom命令获取串口上的数据
minicom -b 9600 -o -D /dev/ttyUSB0
顺利的话会出现下图这种数据:
第三部用Python实时读取GPS数据
在终端依次输入
mkdir GPS
cd GPS
touch GPS_test.py
gedit GPS_test.py
把下面代码粘进去
import serial #导入serial模块
ser = serial.Serial("/dev/ttyUSB0",9600)#打开串口,存放到ser中,/dev/ttyUSB0是端口名,9600是波特率
while True:
line = str(str(ser.readline())[2:]) # readline()是用于读取整行
# 这里如果从头取的话,就会出现b‘,所以要从第三个字符进行读取
if line.startswith('$GPGGA'):
line = str(line).split(',') # 将line以“,”为分隔符
Longitude = float(line[4][:3]) + float(line[4][3:])/60
# 读取第5个字符串信息,从0-2为经度,再加上后面的一串除60将分转化为度
Latitude = float(line[2][:2]) + float(line[2][2:])/60
# 纬度同理
print("经度:",Longitude)
print("维度:",Latitude)
输出结果:
二、配置MQTT
接下来配置MQTT,MQTT小伙伴们可以去百度百科看一下,MQTT的话题、消息比较形象的例子是微信公众号。如果你关注了央视新闻,那么央视新闻发的消息都会给你推送;如果央视新闻也关注了你,那么你们就是互相关注,你发的消息也会给央视新闻推送。
下面来看一下如何用python实现使用MQTT协议收发消息:
需要用到的包为paho-mqtt
在树莓派终端输入
pip install paho-mqtt
来安装paho-mqtt
在终端输入
mkdir MQTT
cd MQTT
touch subscriber.py
gedit subscriber.py
把下面的代码粘进去
# subscriber.py
import paho.mqtt.client as mqtt
def on_connect(client, userdata, flags, rc):
print(f"Connected with result code {rc}")
# 订阅,需要放在 on_connect 里
# 如果与 broker 失去连接后重连,仍然会继续订阅 raspberry/topic 主题
client.subscribe("raspberry/topic")
# 回调函数,当收到消息时,触发该函数
def on_message(client, userdata, msg):
print(f"{msg.topic} {msg.payload}")
client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
# 设置遗嘱消息,当树莓派断电,或者网络出现异常中断时,发送遗嘱消息给其他客户端
client.will_set('raspberry/status', "OFF")
# 创建连接,三个参数分别为 broker 地址,broker 端口号,保活时间
client.connect("broker.emqx.io", 1883, 60)
# 设置网络循环堵塞,在调用 disconnect() 或程序崩溃前,不会主动结束程序
client.loop_forever()
运行结果:
code 0表示连接成功,其他数字不对。
到MQTTX官网下载MQTTX客户端给话题raspberry/topic
发消息,测试能不能收到。
下载安装好之后按照下图输入:
Client ID是随机的。
然后点击右上角Connect:
这时,回到树莓派终端运行
python3 subscriber.py
然后用客户端发送消息,观察终端是否显示刚刚发布的消息。成功的话应该是这样的:
下面来试试用树莓派发送消息:
在终端输入
cd MQTT
touch publisher.py
gedit publisher.py
把下面的代码粘进去
import paho.mqtt.client as mqtt
import time
def on_connect(client, userdata, flags, rc):
print(f"Connected with result code {rc}")
client = mqtt.Client()
client.on_connect = on_connect
client.connect("broker.emqx.io", 1883, 60)
# 每间隔 2 秒钟向 raspberry/topic 发送一个消息,连续发送 10 次
for i in range(10):
# 四个参数分别为:主题,发送内容,QoS, 是否保留消息
client.publish('raspberry/topic', payload=i, qos=0, retain=False)
print(f"send {i} to raspberry/topic")
time.sleep(2)
client.loop_forever()
运行
python3 publisher.py
再打开一个终端进入MQTT文件夹
python3 publisher.py
结果:
想用客户端查看的话
点击 Confirm之后就能看到
三、用MQTT协议发送GPS到服务器
现在一般用json格式来传送数据,下面代码就是将GPS坐标进行简单的封装之后发送到服务器。
import paho.mqtt.client as mqtt
import RPi.GPIO as GPIO
import serial # 导入serial模块
import json
import time
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
start_time = time.time()
flag = 17
#jing = 105.753739
#wei = 37.474912
GPIO.setup(flag, GPIO.IN)
# GPIO.add_event_detect(flag, GPIO.RISING)
ser = serial.Serial("/dev/ttyUSB0", 9600)
def on_connect(client, userdata, flags, rc):
print(f"Connected with result code {rc}")
# 订阅,需要放在 on_connect 里
# 如果与 broker 失去连接后重连,仍然会继续订阅 raspberry/topic 主题
client.subscribe("raspberry/topic")
def on_message(client, userdata, msg):
# print(f"{msg.topic} {msg.payload}")
print("主题:" + msg.topic + " 消息:" + str(msg.payload.decode('utf-8')))
print(f"receive message from raspberry/topic")
def on_subscribe(client, userdata, mid, granted_qos):
print("On Subscribed: qos = %d" % granted_qos)
start_time = time.time()
client = mqtt.Client()
client.on_connect = on_connect
client.connect("broker.emqx.io", 1883, 60)
#client.connect("broker.emqx.io", 1883, 60)
client.on_message = on_message
client.will_set('raspberry/status', "OFF")
while True:
client.on_message = on_message
client.loop_start()
line = str(str(ser.readline())[2:]) # readline()是用于读取整行
# print(line)
# 这里如果从头取的话,就会出现b‘,所以要从第三个字符进行读取
if line.startswith('$GPGGA'):
# 我这里用的GPGGA,有的是GNGGA
# print('接收的数据:' + str(line))
line = str(line).split(',') # 将line以“,”为分隔符
jing = float(line[4][:3]) + float(line[4][3:]) / 60
# 读取第5个字符串信息,从0-2为经度,即经度为116,再加上后面的一串除60将分转化为度
wei = float(line[2][:2]) + float(line[2][2:]) / 60
# 纬度同理
# print(jing)
data1 = {
"type": 1, # 1表示轨迹
"data": {
"latitude": (wei),
# 纬度
"longitude": (jing)
# 经度
}
}
param1 = json.dumps(data1)
client.publish("raspberry/topic", payload=param1, qos=0)
print(f"send message to raspberry/topic")
time.sleep(4)
if GPIO.input(flag) == GPIO.LOW:
data2 = {
"type": 2, # 2表示作业情况
"data": {
"worktime": ((time.time() - start_time) / 3600), # 表示作业3小时
"working_area": ((time.time() - start_time) * 1.12 * 6 * 0.0015)
# 表示作业面积亩
}
}
param2 = json.dumps(data2)
# print("主题:"+msg.topic+" 消息:"+str(msg.payload.decode('utf-8')))
print(f"data2")
client.publish("raspberry/topic", payload=param2, qos=0)
while True:
print(f"OFF")
time.sleep(10)
GPIO.cleanup()
client.loop_forever()
运行结果:
客户端接收到消息。
本次心得就分享到这,有什么不对的地方欢迎各位同学指正。