初めに
この記事はRaspberry Piから位置情報をPleasanterに送信し、Pleasnter上から位置情報を確認できるようにする方法を記しています。
なお、GPSモジュールやSIMドングルのセットアップについては触れません。
そもそもなぜGPSロガーを作ろうと思ったのか
昨今、車の盗難が増加しており、手口も巧妙化しています。
私の1993年式のスポーツカーにも何かしら対策を打てないかと考えた結果、
逆に考えるんだ、「盗まれちゃってもいいさ」と
に至り、居場所が分かるようにすることにしました。
しかし、某密林で販売されているGPSロガーは高額であったり、安価でもいつサポート終了されるかわからないアプリを利用する必要があったりとなかなか手を出せないため、自分で作ることにしました。
前提条件
- Raspberry Piに
gpsdとgpsd-clientsをインストール済で、位置情報を取得できている - Raspberry Piがインターネットに接続できる
- 任意のサーバーにPleasanterのインストールが完了している
【参考】Raspberry Piを使って位置情報を取得する
【参考】Pleasanterマニュアル
実現方法
次のコマンドで位置情報などが入ったJSON形式のデータを取得できます。
gpspipe -x 5 -w|sed -n '/TPV/{p;q}'
取得した位置情報をPleasanterに登録し、地図で確認できるようにします。
【参考】gpsd_jsonのリファレンス
手順
以下の手順で作成します。
- Pleasanterで位置情報を保存/地図表示するサイトを作成
- Pleasanterに位置情報を送信するシェルを作成
- cronでシェルを定期実行
1.Pleasanterで位置情報を保存/地図表示するサイトを作成
今回は記録テーブルを使用し、経度・緯度・速度を保存します。
1-1 保存するための項目の設定
以下のように設定します。
数値項目
| 項目 | 項目名 | 配置 | 単位 | 小数点以下桁数 | 端数処理種類 |
|---|---|---|---|---|---|
| 数値A | 緯度 | 右寄せ | ° | 4 | 四捨五入 |
| 数値B | 経度 | 右寄せ | ° | 4 | 四捨五入 |
| 数値C | 速度 | 右寄せ | km/h | 0 | 四捨五入 |
タイトル
緯度と経度をタイトルに設定する。(なんとなく)
1-2 位置情報データを項目にセットするサーバースクリプトを作成
今回取得できる位置情報はJSON形式のため、JavaScriptでJSON.parseしたほうが手っ取り早いと思ったので、登録APIのJSONに混ぜ込み、Pleasanter側で項目にセットすることにします。
Pleasanterのサーバースクリプトを新規作成し、条件は作成前のみにします。
以下のコードで位置情報の取得と項目へのセットを行います。

try {
// リクエストボディーの取得
const ApiRequestBody = JSON.parse(context.ApiRequestBody)
// リクエストボディーにgpsキーが存在するときのみレコード作成
if ('gps' in ApiRequestBody) {
const GPS_JSON = ApiRequestBody.gps
// 緯度・緯度が存在するときのみレコード作成
if ('lat' in GPS_JSON) {
model.NumA = GPS_JSON.lat
} else {
context.Error("緯度を取得できませんでした。")
}
if ('lon' in GPS_JSON) {
model.NumB = GPS_JSON.lon
} else {
context.Error("経度を取得できませんでした。")
}
// 速度は存在しなくてもレコード作成
if ('speed' in GPS_JSON) {
model.NumC = GPS_JSON.speed
} else {
model.NumC = 0
}
} else {
context.Error("位置情報を取得できませんでした。")
}
} catch (e) {
context.Error(e.message)
}
1-4 一覧画面で見やすいようにビューを設定
1-5 編集画面で地図表示する。
説明項目の中に埋め込む方法もありますが、今回は項目と地図で2分割表示させます。
次にスタイルを新規作成し、条件は編集のみにします。
見出しの幅を半分にしてfloatさせる以下のCSSを設定します。
(一応小さい画面の時は分割しないようにする)

@media screen and (min-width:1200px){
/* #SectionFields[見出しのID]Container */
#SectionFields1Container , #SectionFields2Container{
width:50%;
float:left;
}
}
あとは編集画面読み込み時に、右側の見出しの中にgooglemapのiframeを挿入すれば地図が表示されます。
スクリプトを新規作成し、条件は編集のみにして以下のコードを入れます。

$p.events.on_editor_load = function () {
let lat = $p.getControl("NumA").val()
let lon = $p.getControl("NumB").val()
let map_html = '<iframe src="https://www.google.com/maps?output=embed&q='+lat+','+lon+'&ll='+lat+','+lon+'&t=m&hl=ja&z=18" width="100%D" height="450" style="border:0;" allowfullscreen="" loading="lazy" referrerpolicy="no-referrer-when-downgrade"></iframe>'
// 右側の見出しのID
$('#SectionFields2Container').append(map_html)
}
2.Pleasanterに位置情報を送信するシェルを作成
gpspipeから取得したJSONをPleasanterの登録APIに混ぜ込んで送信します。
api_key='[pleasanterのAPIキー]'
json=$(gpspipe -x 5 -w | sed -n '/TPV/{p;q}'| sed 's/\r//g')
data='{
"ApiVersion": 1.1,
"ApiKey":"'${api_key}'",
"gps":'${json}'
}'
curl -X POST -H "Content-Type: application/json" https://[サーバーアドレス]/api/items/[作成したサイトのID]/create -d "$data" -s 1>/dev/null
3.cronでシェルを定期実行する
cronの実行間隔の最小単位が分なので1分ごとに実行するようにします。
*/1 * * * * ~/gpslogger.sh
完成!
あとがき
Qiita初記事を書きながら半日~1日程度で仕上げることができました。
緯度・経度の保存について、数値項目は小数点以下4桁までしか保存できないため、家一軒分ぐらいずれます。説明項目に保存したほうがよいかもしれません。




