【python】【Djang】GPS/北斗串口數據實時定位百度地圖

一個小項目,做點總結。

項目需求

本項目爲從串口讀取GPS/北斗設備接收數據,進行處理後使用百度地圖api實時顯示定位。

解決辦法

這裏有幾個關鍵的信息,需要一步一步進行實現。

串口

串口通信這裏就不做介紹。本意是使用百度地圖的api,但是這是一個靜態的網頁。如果要動態顯示,且由前端直接讀取PC端的串口數據其實不好實現,在網上查了很多資料,最通常的做法是在前端使用一個active控件讀取串口的數據。這樣有缺點,一是技術過於老套,只兼容IE,其他瀏覽器就不行;二是怎麼做到動態實時定位呢?這個沒有想明白。放棄了從前端直接讀取PC串口的想法。還是需要去用後臺採集數據,搭建後臺和前端進行通信。

串口模擬

路是一步一步走的,胖子也是一口一口吃的,直接去讀取GPSS/北斗設備的數據是不可行的。 先採用電腦端的串口助手進行數據的發送和接收。

  1. 首先採用VSPD(很著名)在PC端模擬出一懟串口,再使用某個串口助手實現數據的發送和接收顯示。串口助手很多,隨便選擇一種即可。
  2. 這樣就可以保證有可靠的數據發送和接收的通信是沒有問題的。保證發送端數據的一直髮送,接着用程序去讀取串口的數據。 #語言版本:Python3 #依賴庫:serial,pyserial #串口助手發送數據:108.111,34.111 import serial from time import sleep if __name__ == '__main__': serial = serial.Serial('COM2', 115200)#根據自己模擬的端口確定com if serial.isOpen() : print("open success") else : print("open failed") while True: n = serial.inWaiting() if n: data= str(serial.read(n))[2:-1].split(',')#對讀取的數據進行簡單的處理 j = data[0] w = data[1] print(data)

讀取串口

保證程序可以正確的讀取發送的數據後,再去處理真實的數據,開啓GPS/北斗設備,將USB插在電腦上,開始讀取原始數據。原始數據包含的信息比較多,而且發送頻率也比較高,數據眼花繚亂,這裏只匹配想要的數據進行處理。在百度地圖上定位只需要“經度”、“緯度”。(這裏牽扯到一個座標系的轉換,後面說),這是一個Ajax的程序:

def ajax_list(request):
    s = serial.Serial('COM5', 115200)
    #定義接收數據的次數
    l = 0
    data=[]
    while True:
        line = str(str(s.readline())[2:])
        # print(line)#原始數據
        if line.startswith('$GNGGA'):#只匹配以“$GNGGA”開頭的數據
            line=str(line).split(',')
            # print("接收的數據:"+ str(line))
            # print("OK:"+str(line))
            # print("指令名稱: ", line[0])
            # print("發送時間: ", line[1][:6])

            # 經緯度轉換
            #經度數據處理
            j = float(line[4][:-7])+float(line[4][-7:])/60
            #緯度數據處理
            w = float(line[2][:-7])+float(line[2][-7:])/60

            #時間
            gpstime=time.strftime('%H:%M:%S',time.localtime(time.time()))

            # id
            global l 
            l= l + 1

            # 添加數據
            data.append(j)
            data.append(w)
            data.append(l)
            data.append(gpstime)
            print(data)
            return HttpResponse(json.dumps(data), content_type='application/json')

百度地圖api

先去申請百度地圖api 的 key。然後看這裏:http://lbsyun.baidu.com/jsdemo.htm#i8_4 這裏放出百度地圖定位aip的源碼:

<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
    <style type="text/css">
        body, html{width: 100%;height: 100%;margin:0;font-family:"微軟雅黑";}
        #allmap{height:500px;width:100%;}
        #r-result{width:100%; font-size:14px;}
    </style>
    <script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=您的密鑰"></script>
    <title>城市名定位</title>
</head>
<body>
    <div id="allmap"></div>
    <div id="r-result">
        經度: <input id="longitude" type="text" style="width:100px; margin-right:10px;" />
        緯度: <input id="latitude" type="text" style="width:100px; margin-right:10px;" />
        <input type="button" value="查詢" onclick="theLocation()" />
    </div>
</body>
</html>
<script type="text/javascript">
    // 百度地圖API功能
    var map = new BMap.Map("allmap");
    map.centerAndZoom(new BMap.Point(116.331398,39.897445),11);
    map.enableScrollWheelZoom(true);
    
    // 用經緯度設置地圖中心點
    function theLocation(){
        if(document.getElementById("longitude").value != "" && document.getElementById("latitude").value != ""){
            map.clearOverlays(); 
            var new_point = new BMap.Point(document.getElementById("longitude").value,document.getElementById("latitude").value);
            var marker = new BMap.Marker(new_point);  // 創建標註
            map.addOverlay(marker);              // 將標註添加到地圖中
            map.panTo(new_point);      
        }
    }
</script>

上面的程序是靜態的,項目需求把從串口源源不斷讀取的數據在百度地圖上進行顯示。這裏想到使用了Ajax。

Ajax

Ajax 即“Asynchronous Javascript And XML”(異步 JavaScript 和 XML),是指一種創建交互式網頁應用的網頁開發技術。 Ajax = 異步 JavaScript 和 XML(標準通用標記語言的子集)。 Ajax 是一種用於創建快速動態網頁的技術。 Ajax 是一種在無需重新加載整個網頁的情況下,能夠更新部分網頁的技術。 通過在後臺與服務器進行少量數據交換,Ajax 可以使網頁實現異步更新。這意味着可以在不重新加載整個網頁的情況下,對網頁的某部分進行更新。 傳統的網頁(不使用 Ajax)如果需要更新內容,必須重載整個網頁頁面。

Django

使用的是Python語言,用Django後臺框架就很簡單,這裏推薦一個博客,學習到很多。自強學堂-Django教程 花了點時間學習了下,Django還是很容易上手的最後將接收到處理的數據存儲爲csv文件。 這裏給出本項目的Django和前端的程序。

view.py
from django.http import HttpResponse
from django.shortcuts import render
import json
import serial
import time
import csv
from time import sleep

def ajax_list(request):
    data=[]
    while True:
        line = str(str(s.readline())[2:])
        # print(line)
        if line.startswith('$GNGGA'):
            line=str(line).split(',')
            # print("接收的數據:"+ str(line))
            # print("OK:"+str(line))
            # print("指令名稱: ", line[0])
            # print("發送時間: ", line[1][:6])

            # 經緯度轉換
            j = float(line[4][:-7])+float(line[4][-7:])/60
            w = float(line[2][:-7])+float(line[2][-7:])/60

            #時間
            gpstime=time.strftime('%H:%M:%S',time.localtime(time.time()))

            # id
            global l 
            l= l + 1

            # 添加數據
            data.append(j)
            data.append(w)
            data.append(l)
            data.append(gpstime)
            print(data)
            with open('./rec_gps.csv','a',newline='') as csvFile1:
                writer = csv.writer(csvFile1)
                writer.writerow((l,gpstime,j,w))
                csvFile.close()
            return HttpResponse(json.dumps(data), content_type='application/json')
s = serial.Serial('COM5', 115200)
global l 
l = 0
csvFile = open('./rec_gps.csv', 'a',encoding = 'utf-8',newline='')
writer = csv.writer(csvFile)
writer.writerow(('id','time','longitude','latitude'))
index.html
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
    <style type="text/css">
        body, html{width: 100%;height: 100%;margin:0;font-family:"微軟雅黑";}
        /* #allmap{height:500px;width:100%;}
        #r-result{width:100%; font-size:14px;} */
        #allmap{float: right;height:100%;width:80%;}
        #r-result{float: left;height:80%;width:20%; overflow:auto;text-align: center}
        #list{position:fixed;top:-16px;}
        #title{position:fixed;top:5px;}
    </style>
    <script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=這裏寫你申請的百度地圖api的key"></script>
    <script src="http://apps.bdimg.com/libs/jquery/1.11.1/jquery.min.js"></script>
    <!-- WGS84轉BD09 start-->
    <script src="https://unpkg.com/gcoord/dist/gcoord.js"></script>
    <!-- end -->
    <title>經緯度定位</title>
</head>
<!-- 框架測試start -->

<!-- end -->
<body>
    <div id="allmap"></div>

    <div id="r-result">
         <div id="list">
             <p  style="background-color:rgb(0, 255, 221)">經緯度數據(WGS84座標)</p>
            </div> 
         <div id = "title" >
              <p style="background-color:rgb(0, 255, 221)">ID  |  Time  |  Longitude  | Latitude</p>
            </div> 
         <p>&nbsp</p>
         <div id="list_result" style="font-size: 90%"></div>
    </div>
</body>
</html>
<script type="text/javascript">
    // 百度地圖API功能
    var map = new BMap.Map("allmap");
    map.centerAndZoom(new BMap.Point(108.953445,34.265721),15);
    map.enableScrollWheelZoom(true);

    $(document).ready(function(){
      // 列表 list
      $('#list').click(function(){
          $.getJSON('/ajax_list/',function(ret){

            //
            $('#list_result').append(ret[2]+",  "+ret[3]+",  "+ret[0].toFixed(6)+",  "+ret[1].toFixed(6) +"<br />");
            // $('#list_result').append("緯度:" + ret[1]+"<br />" );


           // WGS84座標
            var result = gcoord.transform(
                [ret[0], ret[1]],    // 經緯度座標
                gcoord.WGS84,               // 當前座標系
                gcoord.BD09                 // 目標座標系
                );
            //BD09座標
            var longitude = result[0];
            var latitude  = result[1];
            var id 

            map.clearOverlays(); 
            var new_point = new BMap.Point(longitude,latitude);
            var marker = new BMap.Marker(new_point);  // 創建標註
            map.addOverlay(marker);              // 將標註添加到地圖中
            map.panTo(new_point);    
            document.getElementById("longitude").innerHTML=longitude;  
            document.getElementById("latitude").innerHTML=latitude; 

            // $('#list_result').append("經度:" + ret[0]+"<br />" );
            // $('#list_result').append("緯度:" + ret[1]+"<br />" );
          })
      })
    });
</script>
<!-- # 自動點擊按鈕js -->
<script type="text/javascript">
    function myrefresh(){ 
    document.getElementById('list').click();
    } 
    setInterval("myrefresh()","2000"); 
</script>
urls.py
from django.urls import path
from gps import views as gps_views
from django.contrib import admin

urlpatterns = [
    path('', gps_views.index),
    path('ajax_list/', gps_views.ajax_list)
]
Run_me.bat

批處理文件,方便不懂Django的人開啓服務

@echo on
python3 .\manage.py runserver
cmd /k
使用
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章