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) }