[技術] 在Ubuntu使用Holux M-1000C GPS配合Google Earth
Written on 12:10 下午 by Yu Lai
本篇介紹為了這次出差買的Holux M-1000C GPS在Ubuntu
下配合Google Earth來達到即時定位.
1. 首先當然是要先讓Ubuntu與Holux M-1000C連線
Holux M-1000C本身主要是用藍芽的方式與NB或手機連線,
它也有提供特殊的USB線可以直接轉成RS-232的方式連結,
但這條線我沒買,有機會下次再介紹這條特別的線。
在Ubuntu下用GUI的藍芽只能完成初步的連線,至於GPS常用
的SPP只能在Terminal下指令了,方式如下:
先scan藍芽,把M-1000C的MAC記下來。
# hcitool scan
Scanning ...
00:1B:C1:05:9C:64 Holux M-1000C
接著查看GPS使用的RFCOMM的channel。
# sdptool browser 00:1B:C1:05:9C:64
Browsing 00:1B:C1:05:9C:64 ...
Service Name: SPP slave
Service RecHandle: 0x10000
Service Class ID List:
"Serial Port" (0x1101)
Protocol Descriptor List:
"L2CAP" (0x0100)
"RFCOMM" (0x0003)
Channel: 1
Language Base Attr List:
code_ISO639: 0x656e
encoding: 0x6a
base_offset: 0x100
最後編輯/etc/bluetooth/rfcomm.conf建立rfcomm介面:
rfcomm0 {
bind yes;
device 00:1B:C1:05:9C:64;
channel 1;
comment “Holux M-1000C”;
}
重啟Bluetooth services
/etc/init.d/bluetooth stop
(wait a while)
/etc/init.d/bluetooth start
2. 安裝與設定Google Earth
Google Earth自行到Google網頁上抓就有了,我是抓5.1beta版本。
接下來我們要利用了Google Earth的KML以及KML可以refresh的功能,
來達到即時定位的目的。
預設Google Earth會安裝在/opt/google-earth目錄下,
在該目錄下建立一個Realtime GPS.kml,內容如下:
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://earth.google.com/kml/2.2">
<NetworkLink>
<name>Realtime GPS</name>
<open>1</open>
<Link>
<href>./realtime/Realtime GPS.kml</href>
<refreshMode>onInterval</refreshMode>
</Link>
</NetworkLink>
</kml>
接著把相關目錄realtime建立出來:
# mkdir /opt/google-earth/realtime
接著打開Google Earth,它建好的KML開啟放在Places下(檔案 -> 開啟...)。
3. 從M-1000C取出NMEA定位資料
我們剛才己經將RFCOMM介面設定好了,接著只要下
# rfcomm connect 0
syntax error line 23
Connected /dev/rfcomm0 to 00:1B:C1:05:9C:64 on channel 1
Press CTRL-C for hangup
然後另外開一個Terminal就可以從/dev/rfcomm0內取到M-1000C回報的定位資料了。
e.g.
# cat /dev/rfcomm0
$GPGGA,044423.000,0910.5038,N,09916.9805,E,1,9,0.89,8.6,M,-24.3,M,,*72
$GPRMC,044423.000,A,0910.5038,N,09916.9805,E,0.03,0.00,311009,,,A*67
$GPVTG,0.00,T,,M,0.03,N,0.06,K,A*38
$GPGGA,044424.000,0910.5038,N,09916.9805,E,1,9,0.89,8.6,M,-24.3,M,,*75
$GPRMC,044424.000,A,0910.5038,N,09916.9805,E,0.06,0.00,311009,,,A*65
$GPVTG,0.00,T,,M,0.06,N,0.10,K,A*3A
...
所以接下來就是要拆NMEA的format將它轉成剛才在Google Earth設定realtime的KML檔,
提供給Google Earth讀取並顥示即時位置了。
(PS:NMEA格式可以到GPS - NMEA sentence information參考。)
以下是我自己寫的C Code,是將NMEA中的GPRMC格式轉成KML,
當然可以依照自喜歡的格式和語言自己改寫。
/*
* filename: gps2kml.c
* author: lazyf (lazyflai (at) gmail.com)
* date: 2009/10/31
* copyright: http://creativecommons.org/licenses/by-nc-nd/2.5/tw/
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#define DEV_FILE "/dev/rfcomm0"
#define KML_FILE "/opt/google-earth/realtime/Realtime GPS.kml"
int main(int argc, char *argv[]) {
char strbuf[256];
char *strp;
FILE *fp, *fp2;
float latitude, latitude_in, latitude_degrees, latitude_minutes;
float longitude, longitude_in, longitude_degrees, longitude_minutes;
float altitude, speed;
/* Call rfcomm connect */
system("rfcomm release 0");
sleep(3);
system("rfcomm connect 0 &");
sleep(5);
/* Open device file */
if((fp = fopen(DEV_FILE, "r"))) {
/* Call Google Earth up */
system("/opt/google-earth/googleearth &");
while(1) {
/* Read text */
memset(strbuf, 0, sizeof(strbuf));
fscanf(fp, "%s\n", strbuf);
if(strlen(strbuf) < 58)
continue;
/* Parse GPRMC format */
if(memcmp(strbuf, "$GPRMC", 6)==0) {
strp = (char *)strtok(strbuf, ","); /* $GPRMC */
strp = (char *)strtok(0, ","); /* Time */
strp = (char *)strtok(0, ","); /* Avalible or Void */
strp = (char *)strtok(0, ","); /* Latitude */
latitude_in = atof(strp);
strp = (char *)strtok(0, ","); /* N or S */
if(strcmp(strp, "S") == 0)
latitude_in = -latitude_in;
latitude_degrees = (int)(latitude_in/100);
latitude_minutes = latitude_in - latitude_degrees*100;
latitude = latitude_degrees + (latitude_minutes/60);
strp = (char *)strtok(0, ","); /* Longitude */
longitude_in = atof(strp);
strp = (char *)strtok(0, ","); /* E or W */
if(strcmp(strp, "W") == 0)
longitude_in = -longitude_in;
longitude_degrees = (int)(longitude_in/100);
longitude_minutes = longitude_in - longitude_degrees*100;
longitude = longitude_degrees + (longitude_minutes/60);
strp = (char *)strtok(0, ","); /* Speed */
speed = atof(strp) * 1.852;
if(speed < 3)
speed = 0;
strp = (char *)strtok(0, ","); /* Altitude */
altitude = atof(strp);
/* Output KML file */
if((fp2 = fopen(KML_FILE, "w"))) {
fprintf(fp2,
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<kml xmlns=\"http://earth.google.com/kml/2.0\">\n"
"\t<Placemark>\n"
"\t\t<name>GPS %d.%d km/h</name>\n"
"\t\t<description></description>\n"
"\t\t<Point>\n\t\t\t<coordinates>%f,%f,%f</coordinates>\n\t\t</Point>\n"
"\t</Placemark>\n"
"</kml>\n",
(int)speed, ((int)(speed*10))%10, longitude, latitude, altitude);
fflush(fp2);
fclose(fp2);
}
}
}
fclose(fp);
}
return 0;
}
最後把它compile出來執行,就會自動建好rfcomm0和開啟Google Earth啦。