ひとりぶろぐ

価値ある情報をユーザー視点で発信するブログ

iOS用Yahoo!地図上の地点情報をfenix2J等のGarmin製GPSにウェイポイントとして渡す

   

iPhoneからGarmin製GPSにウェイポイントを渡したい

Garmin製GPSの使いこなしにおいて、地点情報、つまりウェイポイントの登録は結構重要。

でも、地図がインストールできるタイプのGPSでないと、GPS上では地点検索ができなかったり、できても細かい施設や店舗までフォローできていなかったりで、iPhone上で動作する地図アプリ上で地点情報を検索するのと比較すると、困難が大きいのです。

従って、以下で紹介しているような方法で、自宅のパソコンを使ってウェイポイントを仕込んでから外出するのがセオリーです。

Garmin ForetrexにGoogle Mapsのマイマップから地点情報(ウェイポイント)を転送する

自宅での仕込みはそれでいいとして、外出中に思った位置へのウェイポイント登録ができれば、もっとGPSを活用できるのに。上掲のような手法を使ってウェイポイントの登録をしてなお、iPhone上で検索した地点情報を、どうにかしてGPSにウェイポイントとして登録したいと思うものです。

BaseCamp MobileApp
カテゴリ: Navigation
販売元: Garmin International(サイズ: 14.8 MB)
全てのバージョンの評価: (0 件の評価)

Garmin fenixシリーズは、Bluetoothで接続したiPhone上で動作するアプリBasecamp Mobileからウェイポイントを登録できます。

GARMIN(ガーミン) fenix2J 日本版【日本正規品】 104063
GARMIN(ガーミン) (2014-11-07)
売り上げランキング: 57,516

「iPhoneとGPSの両方を持ってさえいれば、どこにいてもウェイポイントが登録できる」がまがりなりにも実現できはするのですが、ウェイポイントの位置指定の場面において地点検索ができず、現在地表示しかできないため、手動で登録したい場所までスクロールし、マーカーを落とすしかなく、あまつさえApple標準マップなのでどうにも使いづらい。

IMG 2278

Garmin製品のソフトウェアは、こういう間の抜けたところがたくさんあるのですが、スマートフォンとの連携が可能なのはGarmin製品しかないし、これで最高峰なので受け入れるしかありません。(続きは[Read More]から)

地点検索を経てのウェイポイント登録方法を考える

Basecamp Mobileは、幸いにしてGPXファイルをOpen In…から受け取ることができます。

IMG 2280

試したところでは、ウェイポイント「wpt」を含むGPXファイルを受け取ると、それをウェイポイントとして登録できるようになっています。

<?xml version="1.0"?>
<gpx xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.topografix.com/GPX/1/1" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd">
<wpt lat="35.98996315" lon="139.08347451">
<time>2015-02-01T11:37:14Z</time>
<name>西武秩父駅</name>
<sym>Waypoint</sym>
<type>user</type>
</wpt>
</gpx>

上記のようなwpt入りGPXファイルを受け取ると、ウェイポイント登録画面となります。

IMG 2281

そこで、地点検索をしつつ、検索を経て得た地点情報を含む、wpt入りGPXファイルをiPhone上で生成する方法を考案してみました。


Yahoo!地図アプリからwpt入りGPXを生成する

Yahoo!地図アプリは、キーワード検索を経由して、地図上にマーカーを落とせます。

IMG 2283

Yahoo!地図 – 無料でナビや乗換案内が使える多機能な地図アプリApp
カテゴリ: Navigation
販売元: Yahoo Japan Corporation(サイズ: 13.0 MB)
全てのバージョンの評価: (12,329 件の評価)

マーカーに紐づいた画面下の情報表示領域をタップして下から引き出すとある「共有」アイコンをタップ。

IMG 2284

共有メニューの中にあるコピーをタップすると、場所名、住所、URLがクリップボードにコピーされます。

IMG 2285

クリップボードにコピーされる情報は以下のようなもの。

西武秩父駅 - 埼玉県秩父市野坂町1丁目16
http://yahoo.jp/7sOpBl

短縮URLは以下のようなURLへ301でリダイレクトされます。ここに緯度、経度が含まれるので、これを使いwpt入りのGPXファイルが構築できます。

http://map.yahoo.co.jp/maps?lat=35.98996315&lon=139.08347451&z=18&ei=UTF-8&rdpromo=no&uid=a03cb92eae58eca63cdbd552d19d958a932f6c9a&fa=ids

なぜGoogle MapsではなくYahoo!地図なのかと思う人がほとんどだと思いますが、Google Mapsは、地点情報から緯度経度が取れないことが多いのです。

クリップボードへのアクセス、転送先の取得、GPXファイルの構築、そしてOpen In…の実行をするスクリプトをPythonistaで作りました。

PythonistaApp
カテゴリ: Productivity
販売元: Ole Zorn(サイズ: 118.9 MB)
全てのバージョンの評価: (25 件の評価)

登録するウェイポイント名を問い合わせる手順を入れたので、日本語版でないGPSの場合、ここでローマ字の名前などに付け替えることができます。

IMG 2289

yahoo2wpt.py

最初のスクリプトは、Yahoo!地図でクリップボードにコピーした地点情報からwpt入りのGPXを作り、そのままOpen In…を実行するもの。

#coding: utf-8
import sys
import datetime
import urllib2
from urlparse import urlparse
from cgi import parse_qs
import re
import clipboard
import console
 
WPT_TEMPLATE = '''<?xml version="1.0"?>
<gpx xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.topografix.com/GPX/1/1" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd">
<wpt lat="%s" lon="%s">
<time>%s</time>
<name>%s</name>
<sym>Waypoint</sym>
<type>user</type>
</wpt>
</gpx>'''

GPX_FILE_NAME = 'waypoint.gpx'

# http://azyobuzin.hatenablog.com/entry/2013/04/08/001935
class MyRedirectHandler(urllib2.HTTPRedirectHandler):
     http_error_301 = lambda self, req, fp, code, msg, headers: fp

def main():
     c = clipboard.get()
     # print c
     m = re.match("(.+) - (.+)\n(http://yahoo.jp/[a-zA-Z0-9!-\.:-@\[-`{-~]+)", c)
     if m == None:
          console.alert("ERROR: Invalid Format", c, hide_cancel_button=True)
          return

     title = console.input_alert("Input Title", "", m.group(1))
     surl = m.group(3)
     console.show_activity()
     opener = urllib2.build_opener(MyRedirectHandler)
     request = urllib2.Request(surl)
     request.get_method = lambda: "HEAD"
     response = opener.open(request)
     console.hide_activity()
     url = response.headers['location']
     qs = urlparse(url).query
     paras = parse_qs(qs)
     lat = paras['lat'][0]
     lon = paras['lon'][0]
     # ISO 8601
     time = datetime.datetime.utcnow().replace(microsecond=0).isoformat()+'Z'
     f = open(GPX_FILE_NAME, 'wb')
     f.write(WPT_TEMPLATE % (lat, lon, time, title))
     f.close()
     console.open_in(GPX_FILE_NAME)

main()

ウェイポイント一つ送ればいい場合は、こちらの方が手間がありません。

yahoo2wpt_push.py / yahoo2wpt_pop.py

こちらのスクリプトは、Yahoo!地図でクリップボードにコピーした地点情報を次々と溜め込むyahoo2wpt_push.py。

溜め込んだ(複数の)地点情報からwpt入りのGPXを作り、Open In…を実行するyahoo2wpt_pop.py。

この二つから成るものです。GPSに送りたいウェイポイントが二つ以上ならこちらの方が便利です。

  • yahoo2wpt_push.py
    • Yahoo!地図でクリップボードにコピーした地点情報を次々と溜め込みます
#coding: utf-8
import sys
import datetime
import os.path
import urllib2
from urlparse import urlparse
from cgi import parse_qs
import re
import clipboard
import console
import pickle

DUMP_FILE_NAME = 'waypoints.pickle'

# http://azyobuzin.hatenablog.com/entry/2013/04/08/001935
class MyRedirectHandler(urllib2.HTTPRedirectHandler):
     http_error_301 = lambda self, req, fp, code, msg, headers: fp

def main():
     c = clipboard.get()
     # print c
     m = re.match("(.+) - (.+)\n(http://yahoo.jp/[a-zA-Z0-9!-\.:-@\[-`{-~]+)", c)
     if m == None:
          console.alert("ERROR: Invalid format", c, "OK", hide_cancel_button=True)
          return

     title = console.input_alert("Input Title", "", m.group(1))
     surl = m.group(3)
     console.show_activity()
     opener = urllib2.build_opener(MyRedirectHandler)
     request = urllib2.Request(surl)
     request.get_method = lambda: "HEAD"
     response = opener.open(request)
     console.hide_activity()
     url = response.headers['location']
     qs = urlparse(url).query
     paras = parse_qs(qs)
     lat = paras['lat'][0]
     lon = paras['lon'][0]
     # ISO 8601
     time = datetime.datetime.utcnow().replace(microsecond=0).isoformat()+'Z'
     if os.path.exists(DUMP_FILE_NAME):
          wps = pickle.load(open(DUMP_FILE_NAME))
     else:
          wps = []
          wps.append({'title':title, 'time':time, 'lat':lat, 'lon':lon})
          pickle.dump(wps, open(DUMP_FILE_NAME, 'wb'))
          console.hud_alert("%d Waypoint(s) Pushed" % len(wps), 'success', 1.5)

main()
  • yahoo2wpt_pop.py
    • 溜め込んだ(複数の)地点情報からwpt入りのGPXを作り、Open In…を実行します
#coding: utf-8
import os.path
import console
import pickle

GPX_TEMPLATE = '''<?xml version="1.0"?>
<gpx xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.topografix.com/GPX/1/1" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd">
%s
</gpx>'''

WPT_TEMPLATE = '''<wpt lat="%s" lon="%s">
<time>%s</time>
<name>%s</name>
<sym>Waypoint</sym>
<type>user</type>
</wpt>'''

DUMP_FILE_NAME = 'waypoints.pickle'
GPX_FILE_NAME = 'waypoint.gpx'

def main():
    if os.path.exists(DUMP_FILE_NAME):
        wps = pickle.load(open(DUMP_FILE_NAME))
        if len(wps) > 0:
            f = open(GPX_FILE_NAME, 'wb')
            f.write(GPX_TEMPLATE % "\n".join(map(lambda x: WPT_TEMPLATE % (x['lat'], x['lon'], x['time'], x['title']), wps)))
            f.close()
            res = console.alert("Confirm", "Are you sure to delete pushed waypoints?", "OK")
            if res == 1:
                os.remove(DUMP_FILE_NAME)
            console.open_in(GPX_FILE_NAME)
    else:
        console.alert("ERROR", "Pushed waypoints not found", "OK", hide_cancel_button=True)

main()

使い方

上のスクリプトをPythonistaに登録します。

IMG 2286

後は適宜実行するだけですが、iOSアプリMyMemoを使うと、通知センターからスクリプトを実行できるようになります。

IMG 2287

MyMemo – メモウィジェットApp
カテゴリ: Utilities
販売元: Takeyoshi Nakayama(サイズ: 433 KB)
全てのバージョンの評価: (19 件の評価)

以下のhtmlをメモに貼ります。

<style>
  .button01 {
  border: solid 1px white;
  padding: 5px;
  margin: 4px;
  -webkit-border-radius: 5px;
  text-align: center;
  font-family: "Hiragino Kaku Gothic ProN";
  font-size: 20px;
  text-decoration: none;
  color: white;
  display: block;
  background-color: transparent;
  }
  a:active {
  background-color: gray;
  opacity: 0.5;
  }
</style>

<p><a class="button01" href="pythonista://yahoo2wpt?action=run">yahoo2wpt</a></p>
<p><a class="button01" href="pythonista://yahoo2wpt_push?action=run">yahoo2wpt_push</a></p>
<p><a class="button01" href="pythonista://yahoo2wpt_pop?action=run">yahoo2wpt_pop</a></p>

この例では、通知センターウィジェットの高さ指定は190でちょうどでした。

IMG 2288

Bluetoothの付いていないGPSとの連携

Garmin fenixのようにBluetoothでiPhoneと接続し、Basecamp Mobileでウェイポイントを登録できるGPSの場合はOpen In…でwpt入りGPXファイルをBasecamp Mobileに渡せば済むのですが、Bluetoothの付いていないGPSとiPhoneとの連携は、どうすればいいのでしょうか?

以下のエントリの「スマートフォンとの直接連携」の項で紹介しているように、データのやりとりをマスストレージ経由でできる最近のGarmin製GPSの場合、RATOC Systems REX-WIFIUSB1や、プリンストン デジ蔵 ShAirDisk PTW-WMS1を使ってWi-Fi経由でGPXファイルを受け渡すことができます。

乾電池駆動の腕時計型GPS Garmin Foretrex 401をスマートフォンと組み合わせて使うとサイクリング、ハイキングに大変便利

プリンストン デジ蔵 ShAirDisk PTW-WMS1の方をおすすめします。

Garmin製GPSは、書き込み可能領域にシステムの重要なファイルが設置され、扱いを間違うとそれが消えてしまい、動作に支障を来すことがあるため、自己責任でお試しください。アンマウントの操作をせずにGPSをPTW-WMS1から外すと危険です。

また、eTrex 20以上のように、microSDを挿入するとデバイス上にボリュームが複数出来る機種の場合は、microSDを抜いてからの方がよさそうです。

PTW-WMS1経由でアクセスして、あるべきファイル、ディレクトリが見えない場合は、その場で使用を中止しましょう。

僕はOS XのディスクユーティリティでGPSのルートファイルシステムのバックアップを取ってあります。eTrex 30Jの入ったポーチを落として電源の瞬断が生じ、ローカライズに関与するファイルが消えて、日本語が表示できなくなったことがありますが、そのときは、ディスクユーティリティでバックアップから書き戻して事なきを得ました。

プリンストン デジゾウシリーズ ワイヤレスモバイルストレージ デジ蔵 ShAirDisk PTW-WMS1
プリンストンテクノロジー (2014-04-30)
売り上げランキング: 1,290

 - Garmin, GPS, iOS, iPhone