MQTT協定傳送GPS座標到伺服器

2020-09-21 13:00:26

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()

執行結果:
在這裡插入圖片描述

在這裡插入圖片描述
使用者端接收到訊息。
本次心得就分享到這,有什麼不對的地方歡迎各位同學指正。