GPS/北斗串口数据实时定位百度地图

一个小项目,做点总结。
俱乐部2.gif

项目需求

本项目为从串口读取GPS/北斗设备接收数据,进行处理后使用百度地图api实时显示定位。

解决办法

这里有几个关键的信息,需要一步一步进行实现。

串口

串口通信这里就不做介绍。本意是使用百度地图的api,但是这是一个静态的网页。如果要动态显示,且由前端直接读取PC端的串口数据其实不好实现,在网上查了很多资料,最通常的做法是在前端使用一个active控件读取串口的数据。这样有缺点,一是技术过于老套,只兼容IE,其他浏览器就不行;二是怎么做到动态实时定位呢?这个没有想明白。放弃了从前端直接读取PC串口的想法。还是需要去用后台采集数据,搭建后台和前端进行通信。

串口模拟

路是一步一步走的,胖子也是一口一口吃的,直接去读取GPSS/北斗设备的数据是不可行的。
先采用电脑端的串口助手进行数据的发送和接收。

  1. 首先采用VSPD(很著名)在PC端模拟出一怼串口,再使用某个串口助手实现数据的发送和接收显示。串口助手很多,随便选择一种即可。
  2. 这样就可以保证有可靠的数据发送和接收的通信是没有问题的。保证发送端数据的一直发送,接着用程序去读取串口的数据。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    #语言版本: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的程序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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的源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
<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
1
2
3
4
5
6
7
8
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的人开启服务

1
2
3
@echo on
python3 .\manage.py runserver
cmd /k
使用

俱乐部2.gif

微信截图_20181115165343.png

谢谢你请我吃糖果!