anyPiの構成品である3Gpiを使ってGPSデータを入力し、この位置情報をネット上に設置したサーバにjson形式でアップロードします。「anyPiでGPSデータの取得」では、GPS service daemon「gpsd」を使用し、C言語からライブラリ「libgps 」を呼び出すプログラムを作成しましたが、今回はPython3を使用し、gpsdのクライアント「gps3」パッケージを用いてGPSデータを取得します。3Gpiを使ってGPSデータの入力を行ったハードウェアをつぎに示します。
Python3でGPSデバイスを使用するための環境構築
「/etc/default/gpsd」により、gpsdのデバイス名やgpsd実行時のオプションを確認します。
$ vi /etc/default/gpsd # Default settings for the gpsd init script and the hotplug wrapper. # Start the gpsd daemon automatically at boot time START_DAEMON="true" # Use USB hotplugging to add new USB devices automatically to the daemon USBAUTO="true" # Devices gpsd should collect to at boot time. # They need to be read/writeable, either by user gpsd or the group dialout. DEVICES="/dev/gps" # Other options you want to pass to gpsd GPSD_OPTIONS="-b"
次のコマンドで、gpsdサービスの状態を確認します。
$ sudo systemctl status gpsd.socket
砒sd.socket - GPS (Global Positioning System) Daemon Sockets
Loaded: loaded (/lib/systemd/system/gpsd.socket; enabled; vendor preset: enabled)
Active: active (running) since Tue 2018-08-07 18:16:41 JST; 27min ago
Listen: /var/run/gpsd.sock (Stream)
[::1]:2947 (Stream)
127.0.0.1:2947 (Stream)
Aug 07 18:16:41 raspberrypi systemd[1]: Listening on GPS (Global Positioning System) Daemon Sockets.
次のコマンドを実行し、GPSアンテナを有効にします。
$ sudo 3gpictl --gpson
Python3でGPSを使用するために、「Python 2.7-3.5 clients for gpsd」を次のコマンドでインストールします。
$ pip3 install gps3
<参考>
次のコマンドを使用して、GPSアンテナから入力されたGPSデータをモニタリングできます。
$ cgps -s
GPSデータをネット上にアップロードするPythonスクリプトの作成
次に示すPythonスクリプトにより、GPSのデータを取得し、そのデータを解析してJson形式にフォーマット化してネット上にアップロードします。
- GPSDSocket はGPSDソケット接続を生成して、GPS出力の要求を行います。
- DataStreamは、gpsdデータストリームをオブジェクト属性値にフォーマット化します。
- HTTPSのURLをアクセスすると、SSL認証エラー「urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:646)>」が発生します。開発環境にアクセスするだけのコードだったので、14行目に「ssl._create_default_https_context = ssl._create_unverified_context
」を記述します。
gpssample.py
from gps3 import gps3
import urllib.request, json
import ssl
if __name__ == '__main__':
gps_socket = gps3.GPSDSocket()
data_stream = gps3.DataStream()
gps_socket.connect()
gps_socket.watch()
url = "https://xxx.jp/gps/index.php"
method = "POST"
headers = {"Content-Type" : "application/json"}
ssl._create_default_https_context = ssl._create_unverified_context
for new_data in gps_socket:
if new_data:
data_stream.unpack(new_data)
print('time : ', data_stream.TPV['time'])
print('lat : ', data_stream.TPV['lat'])
print('lon : ', data_stream.TPV['lon'])
print('alt : ', data_stream.TPV['alt'])
print('speed : ', data_stream.TPV['speed'])
# PythonオブジェクトをJSONに変換する
obj = {"time" : data_stream.TPV['time'],
"lat" : data_stream.TPV['lat'],
"lon" : data_stream.TPV['lon'],
"alt" : data_stream.TPV['alt'],
"speed" : data_stream.TPV['speed']}
json_data = json.dumps(obj).encode("utf-8")
# httpリクエストを準備してPOST
request = urllib.request.Request(url, data=json_data, method=method, headers=headers)
with urllib.request.urlopen(request) as response:
response_body = response.read().decode("utf-8")
print(response_body)
GPSデータをネット上にアップロードするPythonスクリプトの実行
次に示す「index.php」は、URL「https://xxx.jp/gps/index.php」に配置され、Json形式で受け取ったデータを「var_dump」コマンドによりアップロードのレスポンスとして戻し、プログラムの確認のために使用します。
index.php
<?php
try {
$headers = getallheaders();
$post_body = file_get_contents('php://input');
$fp = fopen("samplepost.txt", "w");
foreach ($headers as $name => $value) {
fwrite($fp,"$name: $value\n");
}
fwrite($fp,"$post_body\n");
fclose($fp);
$obj = json_decode($post_body); // オブジェクト形式
if ($obj === NULL) return;
var_dump($obj);
} catch (PDOException $e){
var_dump($e->getMessage());
}
?>
作成したPythonスクリプト「gpssample.py」を次のコマンドで実行します。GPSからの位置情報が表示され、ネット上にJson形式でアップロードされて、そのデータが応答として表示されます。
$ python3 gpssample.py
time : n/a
lat : n/a
lon : n/a
alt : n/a
speed : n/a
object(stdClass)#1 (5) {
["alt"]=>
string(3) "n/a"
["time"]=>
string(3) "n/a"
["speed"]=>
string(3) "n/a"
["lon"]=>
string(3) "n/a"
["lat"]=>
string(3) "n/a"
}
time : 2018-08-16T06:20:35.700Z
lat : 35.43245065
lon : 139.64630665
alt : 48.1
speed : 0.0
object(stdClass)#1 (5) {
["alt"]=>
float(48.1)
["time"]=>
string(24) "2018-08-16T06:20:35.700Z"
["speed"]=>
float(0)
["lon"]=>
float(139.xx)
["lat"]=>
float(35.xx)
}
time : 2018-08-16T06:20:35.700Z
lat : 35.xx
lon : 139.xx
alt : 48.1
speed : 0.0
object(stdClass)#1 (5) {
["alt"]=>
float(48.1)
["time"]=>
string(24) "2018-08-16T06:20:35.700Z"
["speed"]=>
float(0)
["lon"]=>
float(139.xx)
["lat"]=>
float(35.xx)
}
