M5StackでownTracksの場所表示

久しぶりのブログですが、昨年の今頃国内でも売り出されてヒットしたWi-Fi/BLE搭載ESP32マイコンボードに、ちょうどいい大きさのカラーディスプレイとボタン、バッテリー、SDカードスロットなどをつけてきれいにパッケージにしたM5Stack が国内でも発売されたので、何か作ってみようということで、ownTracksで記録した位置情報を拾ってディスプレイ上に表示する、というものを作ってみました。

IMG_20180323_2201126

ownTracksは基本的にはMQTT で位置情報を送信するスマホアプリで、送信先のMQTTサーバを自由に選べますから、スマホの場所を送信/検索するようなサービスを自前で構築することができます。

M5StackにはMicroPythonが移植されており、LCD表示やMQTT、HTTP通信なども容易に取り扱うことができます。そして、Wi-Fiに常時接続している状態にするなら、M5Cloudというオンラインエディタ上でMicroPythonのコードを書いていき、クリック1回でそれをMStackの実機に同期して実行する、ということもできてしまいます。また、M5Cloudに接続した状態でも、M5Stack本体をUSB-CケーブルでPCに接続するとシリアルポートとして認識されるので、ここにMicroPythonのREPLが出ます。このシリアルポートに実行時エラーメッセージ等も表示されるので、そこそこ効率的にデバッグもすることができます。

今回は、地図表示にはOpenStreetMapを使いましたが、それなりに常用しようと思っているので、地図画像データを配信するタイルサーバもあらかじめ用意しました。タイルサーバの構築方法は今回の記事では割愛しますが、基本的にはこちらの記事 が親切に書かれており、こちらに従ってトラブルなく完了できました。

タイルサーバを作っただけでは、ownTracksが出す緯度経度から画像を得ることはまだできず、緯度経度から必要となるタイルの座標情報に変換する必要があります。この計算はサーバ側で実施することとして、staticMapLite というPHPスクリプトを使わせてもらいました。このスクリプトの中で、

   protected $tileSrcUrl = array('mapnik' => 'http://tile.openstreetmap.org/{Z}/{X}/{Y}.png',

として定義されているタイルサーバのアドレスを自分で用意したタイルサーバのものに変更して用いました。

しかしもう1つ問題がありました。M5StackのMicroPythonは、内部にファイルシステムも持っているのですが、ここにJPEGもしくはBMPでイメージファイルを用意すれば、簡単にLCDに表示することができます。しかし、PNGファイルは現時点ではサポートされていないのです。一方、OpenStreetMapのタイルサーバは、現時点でPNGでしか地図画像を出力することができません。そこで、このフォーマット変換もstaticMapLiteでカバーすることにしました。staticmaplite.phpの中で、

    return imagepng($this->image);

というようにimagepngを呼び出しているところが3か所ありますが、これをすべて imagejpeg() に置き換え、また

   header('Content-Type: image/png');

となっているところも、image/jpeg に変更します。これで、staticmapliteが、指定した緯度経度の座標の地図を指定したタイルサーバから取得し、JPEG画像として返してくれます。

M5Stack側では、MQTTのownTracksのトピックをsubscribeして、データが来たら該当する緯度経度を指定してstaticmapliteを呼び出し、戻ってきたJPEG画像データをMicroPythonの内部ストレージに格納して、LCDに表示する、というプログラムを書けばいいわけです。

できあがったソースコードはgistに置きました。

タイルサーバのHSTSの都合でSSLを有効にしなければならなかったので、M5Stackのメモリが足りるか少し心配だったんですが、SSL通信をサポートするusslモジュールを使っても大丈夫なようです。MicroPython向けに、4M-PSRAMを搭載したモデルも発売予定のようですから、いろいろできそうで楽しみですね。