USBレシーバーが手元にあるのでラズパイにつけて現在地を取得してみます。
BU-353S4を使いました。
アナログな方法ですが、GPSレシーバーの抜き差し前後で下記コマンドを実行して対象のデバイスを特定します。
$ ls /dev/ttyUSB*
/dev/ttyUSB0 /dev/ttyUSB1 /dev/ttyUSB2 /dev/ttyUSB3 /dev/ttyUSB4
今回は/dev/ttyUSB4
として認識されている事を前提に進めます。
GPSの値を取得するスクリプト
# !/usr/bin/env python
# -*- coding: utf-8 -*-
import time
import serial
# デバイスの指定
DEV = '/dev/ttyUSB4'
# 緯度、経度の分数表記⇒度数表記への変換関数
def convert(x):
result = (float(x[0:-7])+(float(x[-7:])/60))
return result
# 必要な値を文字列として返す関数
def get_str(x):
result =""
if (x[2] == "A") and (x[2] != ""):
result += "state:"+"ok "
elif (x[2] == "V") and (x[2] != ""):
result += "state:"+"alert "
else:
result += "state:"+"no data "
if x[7] != "":
result += 'speed:'+ '%.1f' % (float(x[7])*1.852) + "km/h "
else:
result += "speed:"+"no data "
if (x[4] == "N") and ( x[4] != "" ):
result += "north latitude:" + '%.4f' % convert(x[3]) +' '
elif (x[4] == "S") and ( x[4] != "" ):
result += "south latitude:" + '%.4f' % convert(x[3]) +' '
else:
result += "latitude:"+"no data "
if (x[6] == "E") and ( x[6] != ""):
result += "east longitude:" + '%.4f' % convert(x[5]) +' '
elif (x[6] == "W") and ( x[6] != ""):
result += "west longitude" + '%.4f' % convert(x[5]) +' '
else:
result += "logitude:"+"no data "
return result
# チェックサムの検証
def checksum_verify(c_sum,data):
c_data = '0x00'
for i in range(1,len(data)-3):
c_data = hex(int(c_data,16) ^ int(hex(ord(data[i])),16))
if int(c_sum,16) == int(c_data,16):
return True
else:
return False
# メインループ
# GPRMCの値のみ処理、その値の要素の数が13未満でうまく取得出来ていない場合は処理しない
try:
#シリアルの取得
sr = serial.Serial(DEV, 4800)
while 1:
#改行コードは除外
tmp = sr.readline().rstrip()
#チェックサムの確認
if checksum_verify(tmp[-2:],tmp):
tmp2 = tmp.split(",")
#GPRMCのみ処理
if (tmp2[0] == '$GPRMC'):
line = get_str(tmp2)
print 'OK:'+tmp
print line
time.sleep(0.5)
else:
print 'NG:'+tmp
finally:
print 'serial_close'
sr.close()
補足説明
GPRMCの各値は下記の通りです
tmp2[1] UTC時刻 日本標準時の-9時間
tmp2[2] ステータス Aは正常 Vは警告
tmp2[3] 緯度(分数表記)
tmp2[4] (N)北緯か(S)南緯か
tmp2[5] 経度(分数表記)
tmp2[6] (E)東経か(W)西経か
tmp2[7] 移動速度 knot
tmp2[8] 真方位
tmp2[9] 協定世界時(UTC) ddmmyyの形式
tmp2[12] チェックサム
※分数表記⇒度数表記
緯度、経度 3641.6498なら 36度41.6498分となるが41.6498を60で割りと度数と足せば度数表記
※移動速度
knotは1.852倍でkm/h
※チェックサム
$
から*
の間の文字をXOR計算して同じ値か確認
$GPRMC,034357.279,V,,,,,,,020117,,,N*42
上記であれば、
GPRMC,034357.279,V,,,,,,,020117,,,N
が計算対象となる
デバイス参照時の固定方法
接続されているデバイスや環境によって/dev/ttyUSB0
だったり/dev/ttyUSB4
だったり都度変わってしまうというのは不便です。
自動起動のスクリプトで使用する事が出来ません。そういうときの対処です。
デバイスIDの使用
差し込むUSBポートが決まっていれば下記の情報を確認し、使用する
$ ls -al /dev/serial/by-path
total 0
drwxr-xr-x 2 root root 140 Jan 2 01:30 .
drwxr-xr-x 4 root root 80 Jan 1 20:03 ..
lrwxrwxrwx 1 root root 13 Jan 2 01:30 platform-3f980000.usb-usb-0:1.3:1.0-port0 -> ../../ttyUSB4
lrwxrwxrwx 1 root root 13 Jan 1 20:03 platform-3f980000.usb-usb-0:1.4:1.0-port0 -> ../../ttyUSB0
lrwxrwxrwx 1 root root 13 Jan 1 20:03 platform-3f980000.usb-usb-0:1.4:1.1-port0 -> ../../ttyUSB1
lrwxrwxrwx 1 root root 13 Jan 1 20:03 platform-3f980000.usb-usb-0:1.4:1.2-port0 -> ../../ttyUSB2
lrwxrwxrwx 1 root root 13 Jan 1 20:03 platform-3f980000.usb-usb-0:1.4:1.3-port0 -> ../../ttyUSB3
対処のデバイスが/dev/ttyUSB4
であれば、下記のように修正
# デバイスの指定
DEV = '/dev/ttyUSB4'
↓
DEV = '/dev/serial/by-path/platform-3f980000.usb-usb-0:1.3:1.0-port0'
udevルールへの記載(USBポートの変更可能)
udev
ルールについてはOracleのudevルールについてを参照。
下記コマンド実行し情報の確認(/dev/ttyUSB4
が対象デバイスの時)
udevadm info -a -p $(sudo udevadm info -q path -n /dev/ttyUSB4)
表示された中から下記を確認
looking at parent device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.3':
KERNELS=="1-1.3"
SUBSYSTEMS=="usb"
DRIVERS=="usb"
ATTRS{bDeviceSubClass}=="00"
ATTRS{bDeviceProtocol}=="00"
ATTRS{devpath}=="1.3"
ATTRS{idVendor}=="067b"
ATTRS{speed}=="12"
ATTRS{bNumInterfaces}==" 1"
ATTRS{bConfigurationValue}=="1"
ATTRS{bMaxPacketSize0}=="64"
ATTRS{busnum}=="1"
ATTRS{devnum}=="21"
ATTRS{configuration}==""
ATTRS{bMaxPower}=="100mA"
ATTRS{authorized}=="1"
ATTRS{bmAttributes}=="80"
ATTRS{bNumConfigurations}=="1"
ATTRS{maxchild}=="0"
ATTRS{bcdDevice}=="0400"
ATTRS{avoid_reset_quirk}=="0"
ATTRS{quirks}=="0x0"
ATTRS{version}==" 1.10"
ATTRS{urbnum}=="65169"
ATTRS{ltm_capable}=="no"
ATTRS{manufacturer}=="Prolific Technology Inc. "
ATTRS{removable}=="removable"
ATTRS{idProduct}=="2303"
ATTRS{bDeviceClass}=="00"
ATTRS{product}=="USB-Serial Controller D"
下記の三点を抜き出し
ATTRS{idProduct}=="2303"
ATTRS{idVendor}=="067b"
ATTRS{product}=="USB-Serial Controller D"
/etc/udev/rules.d
配下に70-bu353s4.rules
などのファイルを作成し下記の情報を記載する。
※/etc/udev/rules.d
配下に'70-'で始まるファイルがあって重複する場合は重複しない番号を指定
ATTRS{idProduct}=="2303",ATTRS{idVendor}=="067b",ATTRS{product}=="USB-Serial Controller D",SYMLINK+="bu353s4"
ファイルの作成後、GPSレシーバーの抜き差しを実施
これで/dev/bu353s4
でGPSレシーバーに接続できるようになるので下記のように修正
# デバイスの指定
DEV = '/dev/ttyUSB4'
↓
DEV = '/dev/bu353s4'