一、設定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()
執行結果:
使用者端接收到訊息。
本次心得就分享到這,有什麼不對的地方歡迎各位同學指正。