<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
		xmlns:xhtml="http://www.w3.org/1999/xhtml"
>

<channel>
	<title>クレコ &#187; GPS</title>
	<atom:link href="http://creco.net/tag/gps/feed/" rel="self" type="application/rss+xml" />
	<link>http://creco.net</link>
	<description>East or west, home is best.</description>
	<lastBuildDate>Fri, 27 Nov 2009 13:26:56 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://creco.net/tag/gps/feed/" />
		<item>
		<title>今ココなう！のPythonクライアント作った</title>
		<link>http://creco.net/2009/07/17/carry_out_here_now_the_client_created_python/</link>
		<comments>http://creco.net/2009/07/17/carry_out_here_now_the_client_created_python/#comments</comments>
		<pubDate>Thu, 16 Jul 2009 22:05:35 +0000</pubDate>
		<dc:creator>inagaki</dc:creator>
				<category><![CDATA[作ってみた]]></category>
		<category><![CDATA[GPS]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[今ココなう！]]></category>

		<guid isPermaLink="false">http://creco.net/2009/07/17/carry_out_here_now_the_client_created_python/</guid>
		<description><![CDATA[周りにはiPhoneのネイティブアプリ版を早く作れ！と言われてますが、時間がかかりそう（位置情報をポストするまではできたけど、ソフトとして完成させるとなるとと物足りないよねー）なので、簡単そうなPythonクライアント作 [...]]]></description>
			<content:encoded><![CDATA[<p>周りにはiPhoneのネイティブアプリ版を早く作れ！と言われてますが、時間がかかりそう（位置情報をポストするまではできたけど、ソフトとして完成させるとなるとと物足りないよねー）なので、簡単そうなPythonクライアント作ってみた。</p>
<p>簡単というのは、以前から自作のPythonクライアントを自分のライブトラッキングサーバ用に作っていたので、それを<a href="http://www.fujita-lab.com/imakoko/api.html">今ココなう！のAPI仕様</a>にあわせるだけだったり。</p>
<p>確認してないですが、Python実行環境を導入して、スクリプトを少し改造さえすればMacやLinuxなどでも使えると思うので、もしよかったら自由にお使いください。   <br />あと、自分のGPSロガーでしか確認していません、ごめんなさい。</p>
<p> <span id="more-713"></span><br />
<h3>ソース</h3>
<pre class="csharpcode">#!/usr/bin/python
# -*- coding: utf-8 -*-

# pySerial + Win32 Extensions(optional)
import sys, os, os.path, serial, urllib, urllib2, socket, thread, time, winsound

# Httpのタイムアウト値
socket.setdefaulttimeout(10)

# シリアルポートの設定
serialPort = <span class="str">'COM6'</span>

# 今ココなう！のユーザーIDとパスワード
userId = <span class="str">'USERID'</span>
userPassword = <span class="str">'USERPASSWORD'</span>

saveFlag = 1
markerType = 0

tryCount = 0
baseTime = 0

# NMEAセンテンスの読み取り
def getNmeaSentence():
    global baseTime

    <span class="kwrd">while</span> True:
        <span class="kwrd">try</span> :
            buffer = ser.read(1000)
        except :
            print <span class="str">&quot;error&quot;</span>
            <span class="kwrd">return</span> <span class="str">&quot;error&quot;</span>

        <span class="kwrd">if</span> <span class="kwrd">int</span>(time.time()) + baseTime - time.time() &gt; 0:
            time.sleep(<span class="kwrd">int</span>(time.time()) + baseTime - time.time() )

        # タイミング調整
        <span class="kwrd">if</span> buffer[0:6] != <span class="str">'$GPGGA'</span>:
            time.sleep(0.1)
            <span class="kwrd">if</span> baseTime &gt; 0.9:
                baseTime -= 0.9
            <span class="kwrd">else</span>:
                baseTime += 0.1
            print <span class="str">&quot;clock-timing adjustment...\n&quot;</span>
            <span class="kwrd">return</span>

        # GGAセンテンスの測位時刻の秒一桁が0
        <span class="kwrd">if</span> buffer[12:13] == <span class="str">'0'</span>:
            lines = buffer.split(<span class="str">&quot;\r\n&quot;</span>)

            data = [<span class="str">''</span>] * 12

            <span class="kwrd">for</span> line <span class="kwrd">in</span> lines:
                nmea = line.split(<span class="str">','</span>)

                <span class="kwrd">if</span> nmea[0] == <span class="str">'$GPGGA'</span>:
                    data[0] = nmea[1] # 測位時刻
                    data[1] = nmea[2] # 緯度
                    data[2] = nmea[3] # 北緯・南緯
                    data[3] = nmea[4] # 経度
                    data[4] = nmea[5] # 東経・西経
                    data[5] = nmea[6] # GPS測位状態
                    data[6] = nmea[7] # 受信衛星数
                    data[7] = nmea[8] # HDOP
                    data[8] = nmea[9] # 高度
                elif nmea[0] == <span class="str">'$GPRMC'</span>:
                    data[9] = nmea[7] # 対地速度
                    data[10] = nmea[8] # 進行方向
                    data[11] = nmea[9] # 測位日付

            # GPSが受信不能
            <span class="kwrd">if</span> data[5] == <span class="str">'0'</span>:
                print <span class="str">&quot;not receivable GPS data...&quot;</span>
                winsound.PlaySound(<span class="str">&quot;SystemQuestion&quot;</span>, winsound.SND_ALIAS)
                <span class="kwrd">return</span>

            args = (data,)
            thread.start_new_thread(putGpsData, args)

# Post
def putGpsData(args) :

    global tryCount

    print <span class="str">&quot;post...&quot;</span>

    gpsTime = time.strftime(<span class="str">&quot;%Y-%m-%dT%H:%M:%S&quot;</span>, time.localtime())
    gpsLatitudeD = <span class="kwrd">int</span>(<span class="kwrd">float</span>(args[1]) / 100)
    gpsLatitudeM = (<span class="kwrd">float</span>(args[1]) - gpsLatitudeD * 100)
    gpsLatitude = gpsLatitudeD + gpsLatitudeM / 60
    <span class="kwrd">if</span> args[2] == <span class="str">'S'</span>:
        gpsLatitude *= -1
    gpsLongitudeD = <span class="kwrd">int</span>(<span class="kwrd">float</span>(args[3]) / 100)
    gpsLongitudeM = (<span class="kwrd">float</span>(args[3]) - gpsLongitudeD * 100)
    gpsLongitude = gpsLongitudeD + gpsLongitudeM / 60
    <span class="kwrd">if</span> args[4] == <span class="str">'W'</span>:
        gpsLongitude *= -1
    gpsSpeed = <span class="kwrd">float</span>(args[9]) * 1.852 # knotをkm/hに変換

    <span class="kwrd">params</span> = {
        <span class="str">&quot;time&quot;</span> : gpsTime,
        <span class="str">&quot;lat&quot;</span> : gpsLatitude,
        <span class="str">&quot;lon&quot;</span> : gpsLongitude,
        <span class="str">&quot;gpsq&quot;</span> : args[5],
        <span class="str">&quot;gpsn&quot;</span> : args[6],
        <span class="str">&quot;gpsh&quot;</span> : args[8],
        <span class="str">&quot;gpsd&quot;</span> : args[10],
        <span class="str">&quot;gpsv&quot;</span> : gpsSpeed,
        <span class="str">&quot;save&quot;</span> : saveFlag,
        <span class="str">&quot;t&quot;</span> : markerType,
    }

    topLevelUrl = <span class="str">'imakoko-gps.appspot.com'</span>
    url = <span class="str">'http://imakoko-gps.appspot.com/api/post'</span>
    passMan = urllib2.HTTPPasswordMgrWithDefaultRealm()
    passMan.add_password(None, topLevelUrl, userId, userPassword)
    authHandler = urllib2.HTTPBasicAuthHandler(passMan)
    opener = urllib2.build_opener(authHandler)
    urllib2.install_opener(opener)

    <span class="kwrd">try</span>:
        urllib2.urlopen(url, urllib.urlencode(<span class="kwrd">params</span>))
    except urllib2.HTTPError, e:
        winsound.PlaySound(<span class="str">&quot;Notify&quot;</span>, winsound.SND_ALIAS)
        print e
    except urllib2.URLError, e:
        winsound.PlaySound(<span class="str">&quot;Notify&quot;</span>, winsound.SND_ALIAS)
        print e

    tryCount = tryCount + 1

    print tryCount
    print <span class="kwrd">params</span>
    print <span class="str">&quot;\n&quot;</span>

# シリアル接続
def connect() :
    global ser, baseTime

    <span class="kwrd">try</span>:
        ser = serial.Serial(serialPort, 38400, bytesize=8, parity=<span class="str">'N'</span>, stopbits=1, timeout=0.9, xonxoff=0, rtscts=0)
    except serial.SerialException, e:
        print e

    baseTime = time.time() - <span class="kwrd">int</span>(time.time());

    <span class="kwrd">while</span> True:
        <span class="kwrd">if</span> getNmeaSentence() == <span class="str">&quot;error&quot;</span>:
            ser.close()
            <span class="kwrd">return</span>

    ser.close()

# メインループ
<span class="kwrd">while</span> True:
    connect()
    time.sleep(5)
    print <span class="str">&quot;reconnect...&quot;</span></pre>
<h3>解説<br />
<style type="text/css">
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
</h3>
<h4>導入するもの</h4>
<ul>
<li>Python実行環境</li>
<li>pySerial</li>
<li>Win32 Extension（場合によっては必要ないかも）</li>
</ul>
<h4>やっていること</h4>
<ol>
<li>メインでGPS接続試行でぐるぐる</li>
<li>GPSにシリアル接続（ボーレートとかは調節してね。なんでタイムアウトが0.9なのかは謎）</li>
<li>1秒ごとにNMEAセンテンスを読み取る。読み取るタイミングを調節</li>
<li>調節がうまくいったら、10秒ごとにGGAとRMCのセンテンスを読み取る</li>
<li>BASIC認証で今ココなう！APIにPOSTする</li>
</ol>
<p>ぼくの場合、自転車での使用を想定していて、メッセージを目視することはできないので、なんらかのエラーが起きた場合に視覚以外で知る必要があります。なので、GPS情報が取得できない場合と、POSTがうまくいかなかった場合はそれぞれサウンドがなるように設定しています。</p>
<h4>以上です。</h4>
<p>Pythonがある程度わかる人前提なので、そんなに説明することないですね。逆に、なんでこんなシリアル接続パラメーターなのかとか、タイミングの取り方でもっとスマートなやり方とか、スレッド使うときにタプルで引数を渡すのはなんで？とか教えてもらいたかったり。</p>
<h6></h6>
<h5>今ココなう！実装済み環境</h5>
<ul>
<li>Android Chrome Lite + Google Gears、各種ブラウザ + Google Gearsアドオン</li>
<li>iPhone Mobile Safari (OS 3.0以上)、Firefox 3.5以上、Safari 3.0以上</li>
<li>Python <strong>New!</strong></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://creco.net/2009/07/17/carry_out_here_now_the_client_created_python/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://creco.net/2009/07/17/carry_out_here_now_the_client_created_python/" />
	</item>
		<item>
		<title>iPhone OS 3.0 のブラウザから使えるようになったGPS現在位置情報をTwitterに投稿するJavaScript</title>
		<link>http://creco.net/2009/06/17/iphone-os-3_with_w3c_geolocation_api/</link>
		<comments>http://creco.net/2009/06/17/iphone-os-3_with_w3c_geolocation_api/#comments</comments>
		<pubDate>Wed, 17 Jun 2009 13:09:47 +0000</pubDate>
		<dc:creator>inagaki</dc:creator>
				<category><![CDATA[作ってみた]]></category>
		<category><![CDATA[Geolocation]]></category>
		<category><![CDATA[GPS]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Twitter]]></category>
		<category><![CDATA[ジオポ]]></category>

		<guid isPermaLink="false">http://creco.net/2009/06/17/iphone-os-3_with_w3c_geolocation_api/</guid>
		<description><![CDATA[
Google Maps API V3 と Gears Geolocation API 使って Android のブラウザで現在位置情報を取得する &#124; クレコ では、Androidのブラウザで現在位置情報取得してTwit [...]]]></description>
			<content:encoded><![CDATA[<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="iphone" border="0" alt="iphone" src="http://creco.net/wp-content/uploads/iphone.jpg" width="192" height="365" /></p>
<p><a href="http://creco.net/2009/06/11/google_maps_api_v3_with_gears_geolocation_api/">Google Maps API V3 と Gears Geolocation API 使って Android のブラウザで現在位置情報を取得する | クレコ</a> では、Androidのブラウザで現在位置情報取得してTwitterにポストするというJavaScriptを作りました。</p>
<p>今回は、それのiPhone版です。要 iPhone OS 3.0以上なので、まだアップデートされてない方は本日のアップデートを楽しみに待ちましょう。</p>
<p> <span id="more-573"></span><br />
<h3>iPhone OS 3.0 のブラウザ Mobile Safari でGPS現在位置情報が取得できるようになった</h3>
<h4>Mobile Safari の W3C Geolocation API 対応</h4>
<p><a href="http://lab.cirius.co.jp/blog/2009/06/-iphone-safari.php">ついに iPhone Safari ブラウザから位置情報を取得できるようになります &#8211; Cirius Lab. ブログ</a> から知ったのですが、iPhone OS 3.0 に標準搭載されているブラウザ Mobile Safari が W3C の Geolocation API に対応して、ブラウザから JavaScript を用いることによって、GPSの現在位置情報を取得することが可能になりました。</p>
<p>これによって、いままでネイティブアプリでしかできなかったことが、簡単に敷居なく実装することが可能です。</p>
<h4>W3CのGeolocation API って？</h4>
<p><a href="http://www.w3.org/TR/geolocation-API/">Geolocation API Specification</a>     <br />W3Cで標準化を進めている、位置情報を取得するためのAPI使用のことです。</p>
<p>位置情報を取得するメソッドには、<strong>getCurrentPosition()</strong> と <strong>watchPosition()</strong> があり、前者は現在の位置情報を取得するメソッド、後者は連続した位置情報を取得するメソッドとなっています。</p>
<p>つまり、従来の携帯電話ではできなかった、連続した位置情報を扱うGPSトラッキングなどもJavaScriptを記述するだけで実現できるのです！</p>
<h3>実際に現在位置情報をTwitterへポストするJavaScriptを作ってみた</h3>
<h4>JavaScript ソース</h4>
<pre class="csharpcode">&lt;html&gt;
&lt;head&gt;
&lt;meta name=<span class="str">&quot;viewport&quot;</span> content=<span class="str">&quot;initial-scale=1.0, user-scalable=no&quot;</span> /&gt;
&lt;meta http-equiv=<span class="str">&quot;content-type&quot;</span> content=<span class="str">&quot;text/html; charset=UTF-8&quot;</span>/&gt;
&lt;title&gt;GeoPo : Mobile Safari&lt;/title&gt;
&lt;script type=<span class="str">&quot;text/javascript&quot;</span> src=<span class="str">&quot;http://maps.google.com/maps/api/js?sensor=true&quot;</span>&gt;&lt;/script&gt;
&lt;script type=<span class="str">&quot;text/javascript&quot;</span>&gt;

<span class="rem">/*</span>
<span class="rem"> * GeoPo Encode in JavaScript</span>
<span class="rem"> * @author : Shintaro Inagaki</span>
<span class="rem"> * @param location (Object)</span>
<span class="rem"> * @return geopo (String)</span>
<span class="rem"> */</span>
<span class="kwrd">function</span> geopoEncode(location){
    <span class="rem">// 64characters (number + big and small letter + hyphen + underscore)</span>
    <span class="kwrd">var</span> chars = <span class="str">&quot;0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_&quot;</span>;

    <span class="kwrd">var</span> geopo = <span class="kwrd">new</span> String();
    <span class="kwrd">var</span> lat = parseFloat(location.lat); <span class="rem">// Parse as float</span>
    <span class="kwrd">var</span> lng = parseFloat(location.lng); <span class="rem">// Parse as float</span>
    <span class="kwrd">var</span> scale = parseInt(location.scale); <span class="rem">// Parse as int</span>

    <span class="rem">// Change a degree measure to a decimal number</span>
    lat = (lat + 90) / 180 * Math.pow(8, 10);
    lng = (lng + 180) / 360 * Math.pow(8, 10);

    <span class="rem">// Compute a GeoPo code from head and concatenate</span>
    <span class="kwrd">for</span>(<span class="kwrd">var</span> i = 0; i &lt; scale; i++) {
        geopo = geopo + chars.substr(Math.floor(lat / Math.pow(8, 9 - i) % 8) + Math.floor(lng / Math.pow(8, 9 - i) % 8) * 8, 1);
    }
    <span class="kwrd">return</span> geopo;
}

<span class="kwrd">var</span> lat;
<span class="kwrd">var</span> lng;
<span class="kwrd">var</span> latLng;
<span class="kwrd">var</span> geocoder = <span class="kwrd">new</span> google.maps.Geocoder();
<span class="kwrd">var</span> map;
<span class="kwrd">var</span> infowindow = <span class="kwrd">new</span> google.maps.InfoWindow();
<span class="kwrd">var</span> marker;
<span class="kwrd">var</span> watchId;

<span class="kwrd">function</span> update(position) {
    lat = position.coords.latitude;
    lng = position.coords.longitude;
    latLng = <span class="kwrd">new</span> google.maps.LatLng(lat,lng);

    <span class="kwrd">if</span>(!map){
        <span class="kwrd">var</span> options = {
            zoom: 15,
            center: latLng,
            mapTypeId: google.maps.MapTypeId.ROADMAP,
            scaleControl: <span class="kwrd">true</span>,
        }
        map = <span class="kwrd">new</span> google.maps.Map(document.getElementById(<span class="str">&quot;map_canvas&quot;</span>), options);
    } <span class="kwrd">else</span>{
        map.set_center(latLng);
    }

    <span class="kwrd">if</span>(!marker){
        marker = <span class="kwrd">new</span> google.maps.Marker({
            position: latLng,
            map: map,
            title: <span class="str">&quot;現在地&quot;</span>,
        });
        google.maps.<span class="kwrd">event</span>.addListener(marker, <span class="str">'click'</span>, <span class="kwrd">function</span>() {
            stopUpdate()
            geocoding();
        });
        google.maps.<span class="kwrd">event</span>.addListener(infowindow, <span class="str">'closeclick'</span>, <span class="kwrd">function</span>() {
            startUpdate()
        });
    } <span class="kwrd">else</span>{
        marker.set_position(latLng);
    }
}

<span class="kwrd">function</span> geocoding() {
    <span class="rem">// geopo</span>
    <span class="kwrd">var</span> location = <span class="kwrd">new</span> Object();
    location.lat = lat;
    location.lng = lng;
    location.scale = 7;
    <span class="kwrd">var</span> geopo = geopoEncode(location);

    geocoder.geocode({<span class="str">'latLng'</span>: latLng}, <span class="kwrd">function</span>(results, status) {
        <span class="kwrd">if</span> (status == google.maps.GeocoderStatus.OK) {
            <span class="kwrd">var</span> geocodeAddress;
            <span class="kwrd">for</span>(i=1; i&lt;results.length; i++){
                <span class="kwrd">if</span> (results[i].types.length &gt;= 2 &amp;&amp; results[i].types[1] == <span class="str">&quot;political&quot;</span>) {
                    <span class="kwrd">if</span>(results[i].formatted_address.indexOf(<span class="str">&quot;日本&quot;</span>) != -1){
                        geocodeAddress = results[i].formatted_address.substring(2);
                    }<span class="kwrd">else</span>{
                        geocodeAddress = results[i].formatted_address;
                    }
                    <span class="kwrd">break</span>;
                }
            }
            <span class="kwrd">if</span>(geocodeAddress){
                infowindow.set_content(<span class="str">'&lt;strong&gt;現在地：&lt;/strong&gt;&lt;br /&gt;&lt;span style=&quot;font-size:80%&quot;&gt;'</span> + geocodeAddress + <span class="str">'&lt;/span&gt;&lt;hr /&gt;&lt;a href=&quot;http://twitter.com/home?status='</span> + encodeURIComponent(<span class="str">' L:'</span> + geocodeAddress + <span class="str">' http://geopo.at/'</span> + geopo) + <span class="str">'&quot; target=&quot;twitter&quot;&gt;&lt;img src=&quot;icon_twitter.gif&quot; width=&quot;14&quot; height=&quot;16&quot; border=&quot;0&quot; align=&quot;bottom&quot; hspace=&quot;5&quot; /&gt;TwitterにPOSTする&lt;/a&gt;'</span>);
                infowindow.open(map, marker);
            } <span class="kwrd">else</span> {
                alert(<span class="str">&quot;現在地が取得できませんでした＞＜&quot;</span>);
            }
        } <span class="kwrd">else</span> {
            alert(<span class="str">&quot;Geocoder failed due to: &quot;</span> + status);
        }
    });
}

<span class="kwrd">function</span> startUpdate() {
    watchId = navigator.geolocation.watchPosition(update);
}

<span class="kwrd">function</span> stopUpdate() {
    navigator.geolocation.clearWatch(watchId);
}

startUpdate();

&lt;/script&gt;
&lt;/head&gt;
&lt;body style=<span class="str">&quot;margin:0px; padding:0px;&quot;</span>&gt;
&lt;div id=<span class="str">&quot;map_canvas&quot;</span> style=<span class="str">&quot;width: 100%; height: 100%;&quot;</span>&gt;&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;</pre>
<h4>前回の数倍丁寧に解説<br />
<style type="text/css">
<p>.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
</h4>
<p>前回のAndroid版では説明が省略されすぎて、説明になってなかった反省を踏まえて丁寧に解説。</p>
<h5>HTML</h5>
<p>前回と同様、<a href="http://code.google.com/intl/ja/apis/maps/documentation/v3/">Google Maps API V3</a> を使います。</p>
<pre class="csharpcode">&lt;meta name=<span class="str">&quot;viewport&quot;</span> content=<span class="str">&quot;initial-scale=1.0, user-scalable=no&quot;</span> /&gt;</pre>
<style type="text/css">
<p>.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>これは、iPhoneのためのmeta要素です。地図上でピンチイン、ピンチアウトを使った拡大縮小できるように、<strong>user-scalable</strong>はnoにして、HTMLでの拡大縮小はできなくしてます。</p>
<pre class="csharpcode">&lt;script type=<span class="str">&quot;text/javascript&quot;</span> src=<span class="str">&quot;http://maps.google.com/maps/api/js?sensor=true&quot;</span>&gt;&lt;/script&gt;</pre>
<p>Google Maps API V3のJavaScript読み込みですが、位置情報を取得できるデバイスでは<strong>sensor</strong>パラメータをtrueにします。</p>
<pre class="csharpcode">&lt;body style=<span class="str">&quot;margin:0px; padding:0px;&quot;</span>&gt;
&lt;div id=<span class="str">&quot;map_canvas&quot;</span> style=<span class="str">&quot;width: 100%; height: 100%;&quot;</span>&gt;&lt;/div&gt;
&lt;/body&gt;</pre>
<p>divタグで地図を表示する領域を作成、めいっぱいにするため、縦横100%にし、bodyタグでは余白をなしにするCSS。</p>
<p>うん、丁寧な説明ですね。</p>
<h5>GeoPoエンコードライブラリ</h5>
<p><a href="http://geopo.at/">ジオポ &#8211; 位置情報を短縮して使いやすく</a></p>
<p><strong>GeoPo</strong>（ジオポ）というのは、私が作成したWebサービスで。</p>
<blockquote>
<p>ジオポは位置情報を表す緯度・経度を短縮したURLに変換し、受け取る側のブラウザに合わせた地図を表示するウェブサービスで、会員登録なしに誰でも無料で利用できます。</p>
</blockquote>
<p>という、Twitterに位置情報を付加したいときに使うといいよ！的なサービス。詳しくは、<a href="http://geopo.at/intl/ja/help/feature.html">ジオポの特徴</a> や <a href="http://geopo.at/intl/ja/developer/">開発者向け情報</a> を見てね。よかったら、実装してください。</p>
<p>ソース上では、</p>
<pre class="csharpcode"><span class="rem">/*</span>
<span class="rem"> * GeoPo Encode in JavaScript</span>
<span class="rem"> * @author : Shintaro Inagaki</span>
<span class="rem"> * @param location (Object)</span>
<span class="rem"> * @return geopo (String)</span>
<span class="rem"> */</span>
<span class="kwrd">function</span> geopoEncode(location){
    <span class="rem">// 64characters (number + big and small letter + hyphen + underscore)</span>
    <span class="kwrd">var</span> chars = <span class="str">&quot;0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_&quot;</span>;

    <span class="kwrd">var</span> geopo = <span class="kwrd">new</span> String();
    <span class="kwrd">var</span> lat = parseFloat(location.lat); <span class="rem">// Parse as float</span>
    <span class="kwrd">var</span> lng = parseFloat(location.lng); <span class="rem">// Parse as float</span>
    <span class="kwrd">var</span> scale = parseInt(location.scale); <span class="rem">// Parse as int</span>

    <span class="rem">// Change a degree measure to a decimal number</span>
    lat = (lat + 90) / 180 * Math.pow(8, 10);
    lng = (lng + 180) / 360 * Math.pow(8, 10);

    <span class="rem">// Compute a GeoPo code from head and concatenate</span>
    <span class="kwrd">for</span>(<span class="kwrd">var</span> i = 0; i &lt; scale; i++) {
        geopo = geopo + chars.substr(Math.floor(lat / Math.pow(8, 9 - i) % 8) + Math.floor(lng / Math.pow(8, 9 - i) % 8) * 8, 1);
    }
    <span class="kwrd">return</span> geopo;
}
<style type="text/css">.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>
</pre>
<p>という GeoPoエンコード ライブラリ部分と、</p>
<pre class="csharpcode">    <span class="rem">// geopo</span>
    <span class="kwrd">var</span> location = <span class="kwrd">new</span> Object();
    location.lat = lat;
    location.lng = lng;
    location.scale = 7;
    <span class="kwrd">var</span> geopo = geopoEncode(location);</pre>
<p>呼び出し部分。</p>
<p>lat：緯度、lng：経度、scale：縮尺を渡して、geopoというジオポコードの文字列が返ってくる。</p>
<h5>位置情報の取得制御<br />
<style type="text/css">
<p>.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
</h5>
<p>W3CのGeolocation APIを使って、現在位置情報を取得する。</p>
<pre class="csharpcode"><span class="kwrd">function</span> startUpdate() {
    watchId = navigator.geolocation.watchPosition(update);
}

<span class="kwrd">function</span> stopUpdate() {
    navigator.geolocation.clearWatch(watchId);
}

startUpdate();</pre>
<p>ここでは、watchPosition() を使う。というのも、iPhoneでは getCurrentPosition() がうまく動かなかった。また、最初の1回だけの位置情報取得では位置情報の精度がかなり荒いので、連続して取得し精度が高くなった段階で、その位置情報を採用するという形にしたかったというのもある。</p>
<p>ここで、startUpdate() と stopUpdate() とわざわざ関数にしているのは、後々に取得動作の制御したいためです。</p>
<h5>位置情報の加工と地図の表示</h5>
<p>位置情報が取得できたときに呼ばれる update() では、位置情報を加工して、地図を表示するようにします。</p>
<pre class="csharpcode"><span class="kwrd">var</span> lat;
<span class="kwrd">var</span> lng;
<span class="kwrd">var</span> latLng;
<span class="kwrd">var</span> geocoder = <span class="kwrd">new</span> google.maps.Geocoder();
<span class="kwrd">var</span> map;
<span class="kwrd">var</span> infowindow = <span class="kwrd">new</span> google.maps.InfoWindow();
<span class="kwrd">var</span> marker;
<span class="kwrd">var</span> watchId;

<span class="kwrd">function</span> update(position) {
    lat = position.coords.latitude;
    lng = position.coords.longitude;
    latLng = <span class="kwrd">new</span> google.maps.LatLng(lat,lng);

    <span class="kwrd">if</span>(!map){
        <span class="kwrd">var</span> options = {
            zoom: 15,
            center: latLng,
            mapTypeId: google.maps.MapTypeId.ROADMAP,
            scaleControl: <span class="kwrd">true</span>,
        }
        map = <span class="kwrd">new</span> google.maps.Map(document.getElementById(<span class="str">&quot;map_canvas&quot;</span>), options);
    } <span class="kwrd">else</span>{
        map.set_center(latLng);
    }

    <span class="kwrd">if</span>(!marker){
        marker = <span class="kwrd">new</span> google.maps.Marker({
            position: latLng,
            map: map,
            title: <span class="str">&quot;現在地&quot;</span>,
        });
        google.maps.<span class="kwrd">event</span>.addListener(marker, <span class="str">'click'</span>, <span class="kwrd">function</span>() {
            stopUpdate()
            geocoding();
        });
        google.maps.<span class="kwrd">event</span>.addListener(infowindow, <span class="str">'closeclick'</span>, <span class="kwrd">function</span>() {
            startUpdate()
        });
    } <span class="kwrd">else</span>{
        marker.set_position(latLng);
    }
}</pre>
<style type="text/css">
<p>.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>position.coords.latitude には緯度、 position.coords.longitude には経度</p>
<blockquote>
<pre>  interface <dfn>Coordinates</dfn> {
    readonly attribute double <a href="http://www.w3.org/TR/geolocation-API/#lat">latitude</a>;
    readonly attribute double <a href="http://www.w3.org/TR/geolocation-API/#lon">longitude</a>;
    readonly attribute double <a href="http://www.w3.org/TR/geolocation-API/#altitude">altitude</a>;
    readonly attribute double <a href="http://www.w3.org/TR/geolocation-API/#accuracy">accuracy</a>;
    readonly attribute double <a href="http://www.w3.org/TR/geolocation-API/#altitude-accuracy">altitudeAccuracy</a>;
    readonly attribute double <a href="http://www.w3.org/TR/geolocation-API/#heading">heading</a>;
    readonly attribute double <a href="http://www.w3.org/TR/geolocation-API/#speed">speed</a>;
  };</pre>
</blockquote>
<p>他にも、altitude：高度、accuracy：水平方向の精度、altitudeAccuracy：垂直方向の精度、heading：方向、speed：速度 といった属性があります。iPhone 3G S では、コンパスによって方向なども取得できるかもしれません。iPhone 3Gでは、方向には null値、速度には 0 が入るようです。</p>
<p>map や marker は、初回はインスタンスを生成し、2回目以降の呼び出しでは地図は中心地への移動、マーカーは位置情報取得値への書き換えを行います。</p>
<p>marker の初回で、イベントリスナーを作成。上のイベントは、マーカーをクリックしたら位置情報取得動作を止めて情報ウィンドウ（ geocoding() で現在位置の住所やTwitterへポストするアンカーを記載）の表示、下のイベントは、情報ウィンドウを閉じたら位置情報取得動作の再開。</p>
<p>ここで、位置情報の取得動作を操作してるのには次の理由があります。</p>
<ol>
<li>情報ウィンドウが表示されるときに、位置情報が更新されて地図表示が移動されたりすると使い勝手が悪い。 </li>
<li>位置情報の取得のたびに情報ウィンドウの中身を更新すると大変（逆ジオコーディングとか）。 </li>
</ol>
<h5>情報ウィンドウの更新（逆ジオコーディング）</h5>
<p>現在位置の住所取得（逆ジオコーディング）とジオポコードの作成、Twitterへポストするためのアンカーを情報ウィンドウの中に書き込むための処理を geocoding() でやります。</p>
<pre class="csharpcode"><span class="kwrd">function</span> geocoding() {
    <span class="rem">// geopo</span>
    <span class="kwrd">var</span> location = <span class="kwrd">new</span> Object();
    location.lat = lat;
    location.lng = lng;
    location.scale = 7;
    <span class="kwrd">var</span> geopo = geopoEncode(location);

    geocoder.geocode({<span class="str">'latLng'</span>: latLng}, <span class="kwrd">function</span>(results, status) {
        <span class="kwrd">if</span> (status == google.maps.GeocoderStatus.OK) {
            <span class="kwrd">var</span> geocodeAddress;
            <span class="kwrd">for</span>(i=1; i&lt;results.length; i++){
                <span class="kwrd">if</span> (results[i].types.length &gt;= 2 &amp;&amp; results[i].types[1] == <span class="str">&quot;political&quot;</span>) {
                    <span class="kwrd">if</span>(results[i].formatted_address.indexOf(<span class="str">&quot;日本&quot;</span>) != -1){
                        geocodeAddress = results[i].formatted_address.substring(2);
                    }<span class="kwrd">else</span>{
                        geocodeAddress = results[i].formatted_address;
                    }
                    <span class="kwrd">break</span>;
                }
            }
            <span class="kwrd">if</span>(geocodeAddress){
                infowindow.set_content(<span class="str">'&lt;strong&gt;現在地：&lt;/strong&gt;&lt;br /&gt;&lt;span style=&quot;font-size:80%&quot;&gt;'</span> + geocodeAddress + <span class="str">'&lt;/span&gt;&lt;hr /&gt;&lt;a href=&quot;http://twitter.com/home?status='</span> + encodeURIComponent(<span class="str">' L:'</span> + geocodeAddress + <span class="str">' http://geopo.at/'</span> + geopo) + <span class="str">'&quot; target=&quot;twitter&quot;&gt;&lt;img src=&quot;icon_twitter.gif&quot; width=&quot;14&quot; height=&quot;16&quot; border=&quot;0&quot; align=&quot;bottom&quot; hspace=&quot;5&quot; /&gt;TwitterにPOSTする&lt;/a&gt;'</span>);
                infowindow.open(map, marker);
            } <span class="kwrd">else</span> {
                alert(<span class="str">&quot;現在地が取得できませんでした＞＜&quot;</span>);
            }
        } <span class="kwrd">else</span> {
            alert(<span class="str">&quot;Geocoder failed due to: &quot;</span> + status);
        }
    });
}</pre>
<p>前回のAndroid版とほぼ同じです（多少変えたってこと）。</p>
<p>逆ジオコーディングした結果で、郵便番号や道路名ってのをフィルタリングし、formatted_address には「日本」という文字が入るのが気にくわないので、「日本」を取り除いてやる。という内容。</p>
<h4>実装して iPhone OS 3.0 で動作させてみる</h4>
<p>実際に動作させてみる。</p>
<p><a href="http://inagaki.co.uk/test/safari.html">GeoPo : Mobile Safari</a> ＠inagaki.co.uk に作ったものをおいたので、自由に試してみてください。ソースコードも自由に使ってください。</p>
<h5>iPhoneでの位置情報利用の確認</h5>
<p><a href="http://creco.net/wp-content/uploads/1.jpg" rel="lightbox[573]"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="1" border="0" alt="1" src="http://creco.net/wp-content/uploads/1_thumb.jpg" width="162" height="242" /></a> <a href="http://creco.net/wp-content/uploads/2.jpg" rel="lightbox[573]"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="2" border="0" alt="2" src="http://creco.net/wp-content/uploads/2_thumb.jpg" width="162" height="242" /></a> </p>
<p>初回のみSafariでの位置情報利用と、ドメイン単位での位置情報利用の確認があります。<br />
  <br />#これ、ドメイン単位の位置情報利用確認ってリセットする方法あるんですかね？</p>
<h5>地図と情報ウィンドウの表示</h5>
<p><a href="http://creco.net/wp-content/uploads/3.jpg" rel="lightbox[573]"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="3" border="0" alt="3" src="http://creco.net/wp-content/uploads/3_thumb.jpg" width="162" height="242" /></a> <a href="http://creco.net/wp-content/uploads/4.jpg" rel="lightbox[573]"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="4" border="0" alt="4" src="http://creco.net/wp-content/uploads/4_thumb.jpg" width="162" height="242" /></a> </p>
<p>ブックマークなどからURLを読み出せば、そのまま現在位置を取得して地図を表示するという一連の動作ができます。</p>
<p>そして、この地図はスマートフォンに最適化された Google Maps API V3 で作成していますので、まるでネイティブアプリのような感覚でシームレスなスクロールが可能。</p>
<p>マーカーをクリックすることで、情報ウィンドウを表示。このときに、位置情報取得動作をストップさせて、逆ジオコーディングを行い住所を取得。</p>
<p>住所表示の下にある、アンカーをクリックすることで別ウィンドウが立ち上がりTwitterへ現在地情報のついたポストが行えます。</p>
<p>情報ウィンドウの右上の×印をクリックすれば、情報ウィンドウは非表示になり、位置情報取得取得動作を再開させます。現在地が移動した場合はリロードしなくても、情報ウィンドウの開閉だけで位置情報取得のコントロールができます。</p>
<h5>Twitterへ現在地情報の投稿</h5>
<p><a href="http://creco.net/wp-content/uploads/5.jpg" rel="lightbox[573]"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="5" border="0" alt="5" src="http://creco.net/wp-content/uploads/5_thumb.jpg" width="162" height="242" /></a> <a href="http://creco.net/wp-content/uploads/6.jpg" rel="lightbox[573]"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="6" border="0" alt="6" src="http://creco.net/wp-content/uploads/6_thumb.jpg" width="162" height="242" /></a> </p>
<p>アンカーをクリックするとTwitterの投稿のために新しいウィンドウが立ち上がります。このときに、Twitterへログインされてない場合は、ログイン画面となるので、ログインを行ってください。</p>
<p>また、iPhoneからTwitterを使用する場合、デフォルトではモバイル版の画面表示となっています。しかし、モバイル版の画面表示ですと、アンカーをクリックした際に伝える住所やジオポURLが反映されないので、ページ下部にある「スタンダード版で見る」をクリックし、スタンダード版でTwitterを表示させてください。<br />
  <br />#これ、回避方法を知ってる方いましたら教えてください</p>
<p>スタンダード版では、いまなにしてる？のテキストエリアの中に、住所とジオポURLが反映されている状態となります。そこから、メッセージを加えたり、<a href="http://geopo.at/intl/ja/help/feature.html">ジオポURLの縮尺精度変更操作</a>を行うことができます。</p>
<h3>感想、まとまらないまとめ</h3>
<p>連続した位置情報が取得できるのは熱いですね！！でも、iPhoneも熱くなります ＞＜<br />
  <br />位置情報を連続取得させるのは非常にバッテリーを消費します、ほどほどにしましょう。</p>
<p>今までGPSロガーなどがないとGPSトラッキングできなかったのですが、それがJavaScriptだけで実現できるのは魅力的です。私もiPhone単体でできるGPSトラッキングサービスを早速作りたいと思っていますよ。</p>
<p>また、すでにあるGPSトラッキングサービスでも簡単（上のソースを数行いじるだけ）に実現できるので、<a href="http://imakoko-gps.appspot.com/">今ココなう！(β)</a> などの人気のあるサービスが対応すれば一気に対応端末が増えるようになるんじゃないでしょうか？位置情報を使うことの面白さがいろんな人に伝わってくれるとうれしいですね。</p>
]]></content:encoded>
			<wfw:commentRss>http://creco.net/2009/06/17/iphone-os-3_with_w3c_geolocation_api/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://creco.net/2009/06/17/iphone-os-3_with_w3c_geolocation_api/" />
	</item>
		<item>
		<title>Google Maps API V3 と Gears Geolocation API 使って Android のブラウザで現在位置情報を取得する</title>
		<link>http://creco.net/2009/06/11/google_maps_api_v3_with_gears_geolocation_api/</link>
		<comments>http://creco.net/2009/06/11/google_maps_api_v3_with_gears_geolocation_api/#comments</comments>
		<pubDate>Thu, 11 Jun 2009 07:49:48 +0000</pubDate>
		<dc:creator>inagaki</dc:creator>
				<category><![CDATA[作ってみた]]></category>
		<category><![CDATA[Android]]></category>
		<category><![CDATA[Geolocation]]></category>
		<category><![CDATA[Google Maps]]></category>
		<category><![CDATA[GPS]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[ジオポ]]></category>

		<guid isPermaLink="false">http://creco.net/2009/06/11/google_maps_api_v3_with_gears_geolocation_api/</guid>
		<description><![CDATA[先日のGoogle Developer Day 2009 にて、GoogleさんからAndroid携帯である GDD Phone をいただいたので、早速Androidライフを楽しんでる毎日です。素敵なオモチャをありがとう [...]]]></description>
			<content:encoded><![CDATA[<p>先日の<a href="http://code.google.com/intl/ja/events/developerday/2009/home.html">Google Developer Day 2009</a> にて、GoogleさんからAndroid携帯である GDD Phone をいただいたので、早速Androidライフを楽しんでる毎日です。素敵なオモチャをありがとうございます！</p>
<p>ネイティブアプリの地図でGoogle Latitudeをいぢりたおしたりしてるんですが、地図大好きっ子としては自分で位置情報を活用したいところ。</p>
<p>そんな折、ジークルーの佐々木さんから</p>
<blockquote><p>@<a href="http://twitter.com/shinagaki">shinagaki</a> 自分が今日どこを歩いたかが履歴でMapに表示されるAndroidアプリって知らない？</p>
</blockquote>
<p>って遠まわしに作れって言われた気がしたので、Android界隈の位置情報について調べてみる。</p>
<p> <span id="more-535"></span>
</p>
<h3>Androidで位置情報を取得するにはどうすんの？</h3>
<p>調べてみたけど、ネイティブアプリでの情報しかなくて、実装が楽にできそうなブラウザでのAPI動作状況についてのサンプル例がなかった。</p>
<p>ネイティブアプリでは、<a href="http://code.google.com/intl/ja/android/add-ons/google-apis/maps-overview.html">Maps External Library &#8211; Google Projects for Android</a> に情報あるから、ネイティブアプリ作る人は見るといいよ。僕も、あとで見る。</p>
<p>Androidの搭載しているブラウザに、iPhone OS 3.0 のSafariブラウザみたくW3CのGeolocation APIをサポートして、ブラウザからGPS位置情報を取得できることを期待してたんですが、結果から言うとダメ。</p>
<p>ですが！Androidのブラウザ「Chrome Lite」はGoogle Gearsを搭載しているため、ひょっとしたらGearsのGeolocation API使えるかも！？ と思って実験。</p>
<h4>Google Gears での位置情報取得</h4>
<p><a href="http://code.google.com/intl/ja/apis/gears/api_geolocation.html">Geolocation API &#8211; Gears API &#8211; Google Code</a></p>
<p>サンプルのとおりに、 <strong>gears_init.js</strong> をおいて、</p>
<pre class="csharpcode">&lt;script type=<span class="str">&quot;text/javascript&quot;</span> src=<span class="str">&quot;gears_init.js&quot;</span>&gt;&lt;/script&gt;
&lt;script type=<span class="str">&quot;text/javascript&quot;</span>&gt;
<span class="kwrd">var</span> geo = google.gears.factory.create(<span class="str">'beta.geolocation'</span>);

<span class="kwrd">function</span> updatePosition(position) {
  alert(<span class="str">'Current lat/lon is: '</span> + position.latitude + <span class="str">','</span> + position.longitude);
}

<span class="kwrd">function</span> handleError(positionError) {
  alert(<span class="str">'Attempt to get location failed: '</span> + positionError.message);
}

geo.getCurrentPosition(updatePosition, handleError);
&lt;/script&gt;</pre>
<p>と書くだけで、位置情報取得できた！簡単。</p>
<h4>Google Maps API V3 を使って地図表示</h4>
<p>それに、Google Maps API V3 を組み合わせる。<br />
<style type="text/css">
<p>.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
</p>
<p><a href="http://code.google.com/intl/ja/apis/maps/documentation/v3/">The Google Maps API V3 &#8211; Google Maps JavaScript API V3 &#8211; Google Code</a></p>
<p>Google Maps API V3 ってのは、今までのMaps APIで効率が悪かったり、スマートフォンに最適化されてなかった部分を改善するため、一から書き直したAPIで、今までのMaps APIと書き方が異なる。</p>
<p>んでも、やってることは同じだし、まだ V3のほうができることが少ないので理解は早いと思います。</p>
<p>サンプルとしては、</p>
<pre class="csharpcode">&lt;script type=<span class="str">&quot;text/javascript&quot;</span> src=<span class="str">&quot;http://maps.google.com/maps/api/js?sensor=false&quot;</span>&gt;&lt;/script&gt;
&lt;script type=<span class="str">&quot;text/javascript&quot;</span>&gt;
  <span class="kwrd">function</span> initialize() {
    <span class="kwrd">var</span> myLatlng = <span class="kwrd">new</span> google.maps.LatLng(-34.397, 150.644);
    <span class="kwrd">var</span> myOptions = {
      zoom: 8,
      center: myLatlng,
      mapTypeId: google.maps.MapTypeId.ROADMAP
    }
    <span class="kwrd">var</span> map = <span class="kwrd">new</span> google.maps.Map(document.getElementById(<span class="str">&quot;map_canvas&quot;</span>), myOptions);
  }
&lt;/script&gt;
&lt;/head&gt;
&lt;body style=<span class="str">&quot;margin:0px; padding:0px;&quot;</span> onload=<span class="str">&quot;initialize()&quot;</span>&gt;
  &lt;div id=<span class="str">&quot;map_canvas&quot;</span> style=<span class="str">&quot;width:100%; height:100%&quot;</span>&gt;&lt;/div&gt;
&lt;/body&gt;</pre>
<p>これで、全画面の地図表示。</p>
<ul>
<li>APIキーがいらない → Open Socialなアプリ作る場合に問題だった、ドメインごとにAPIキー発行する手間がなくなる。 </li>
<li>スマートフォンに対応 → iPhoneとAndroidのUIにあわせてコントローラーを配置してくれるし、地図の描画までが早い！ </li>
</ul>
<p>だから、iPhoneのネイティブアプリ作ってて地図周りだけ、UIWebView使ってるっていう人も恩恵あるんじゃないかな？</p>
<h3>実際に現在位置をTwitterにPOSTするJavaScriptを作ってみた<br />
<style type="text/css">
<p>.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
</h3>
<p><a href="http://inagaki.co.uk/test/gears.html">Google Maps API V3 with Gears Geolocation API</a> ＠inagaki.co.uk</p>
<p>実際にAndroidで試してみてください。</p>
<p>中身はコチラ。</p>
<pre class="csharpcode">&lt;html&gt;
&lt;head&gt;
&lt;meta name=<span class="str">&quot;viewport&quot;</span> content=<span class="str">&quot;initial-scale=1.0, user-scalable=no&quot;</span> /&gt;
&lt;meta http-equiv=<span class="str">&quot;content-type&quot;</span> content=<span class="str">&quot;text/html; charset=UTF-8&quot;</span>/&gt;
&lt;title&gt;Google Maps API V3 with Gears Geolocation API&lt;/title&gt;
&lt;script type=<span class="str">&quot;text/javascript&quot;</span> src=<span class="str">&quot;http://maps.google.com/maps/api/js?sensor=false&quot;</span>&gt;&lt;/script&gt;
&lt;script type=<span class="str">&quot;text/javascript&quot;</span> src=<span class="str">&quot;gears_init.js&quot;</span>&gt;&lt;/script&gt;
&lt;script type=<span class="str">&quot;text/javascript&quot;</span>&gt;

<span class="rem">/*</span>
<span class="rem"> * GeoPo Encode in JavaScript</span>
<span class="rem"> * @author : Shintaro Inagaki</span>
<span class="rem"> * @param location (Object)</span>
<span class="rem"> * @return geopo (String)</span>
<span class="rem"> */</span>
<span class="kwrd">function</span> geopoEncode(location){
    <span class="rem">// 64characters (number + big and small letter + hyphen + underscore)</span>
    <span class="kwrd">var</span> chars = <span class="str">&quot;0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_&quot;</span>;

    <span class="kwrd">var</span> geopo = <span class="kwrd">new</span> String();
    <span class="kwrd">var</span> lat = parseFloat(location.lat); <span class="rem">// Parse as float</span>
    <span class="kwrd">var</span> lng = parseFloat(location.lng); <span class="rem">// Parse as float</span>
    <span class="kwrd">var</span> scale = parseInt(location.scale); <span class="rem">// Parse as int</span>

    <span class="rem">// Change a degree measure to a decimal number</span>
    lat = (lat + 90) / 180 * Math.pow(8, 10);
    lng = (lng + 180) / 360 * Math.pow(8, 10);

    <span class="rem">// Compute a GeoPo code from head and concatenate</span>
    <span class="kwrd">for</span>(<span class="kwrd">var</span> i = 0; i &lt; scale; i++) {
        geopo = geopo + chars.substr(Math.floor(lat / Math.pow(8, 9 - i) % 8) + Math.floor(lng / Math.pow(8, 9 - i) % 8) * 8, 1);
    }
    <span class="kwrd">return</span> geopo;
}

<span class="kwrd">var</span> geo = google.gears.factory.create(<span class="str">'beta.geolocation'</span>);

<span class="kwrd">function</span> displayMap(position) {
    <span class="kwrd">var</span> geocoder = <span class="kwrd">new</span> google.maps.Geocoder();
    <span class="kwrd">var</span> latLng = <span class="kwrd">new</span> google.maps.LatLng(position.latitude,position.longitude);
    <span class="kwrd">var</span> options = {
        zoom: 15,
        center: latLng,
        mapTypeId: google.maps.MapTypeId.ROADMAP
    }
    <span class="kwrd">var</span> map = <span class="kwrd">new</span> google.maps.Map(document.getElementById(<span class="str">&quot;map_canvas&quot;</span>), options);

    <span class="kwrd">var</span> geocodeAddress;

    <span class="kwrd">var</span> infowindow = <span class="kwrd">new</span> google.maps.InfoWindow();

    <span class="kwrd">var</span> marker = <span class="kwrd">new</span> google.maps.Marker({
        position: latLng,
        map: map,
        title:<span class="str">&quot;You are here.&quot;</span>
    });

    <span class="rem">// geopo</span>
    <span class="kwrd">var</span> location = <span class="kwrd">new</span> Object();
    location.lat = position.latitude;
    location.lng = position.longitude;
    location.scale = 7;

    <span class="kwrd">var</span> geopo = geopoEncode(location);

    <span class="kwrd">if</span> (geocoder) {
        geocoder.geocode({<span class="str">'latLng'</span>: latLng}, <span class="kwrd">function</span>(results, status) {
            <span class="kwrd">if</span> (status == google.maps.GeocoderStatus.OK) {
                <span class="kwrd">for</span>(i=1;i&lt;results.length;i++){
                    <span class="kwrd">if</span> (results[i].types.length &gt;= 2 &amp;&amp; results[i].types[1] == <span class="str">&quot;political&quot;</span>) {
                        <span class="kwrd">if</span>(results[i].formatted_address.indexOf(<span class="str">&quot;日本&quot;</span>) != -1){
                            geocodeAddress = results[i].formatted_address.substring(2);
                        }<span class="kwrd">else</span>{
                            geocodeAddress = results[i].formatted_address;
                        }
                        <span class="kwrd">break</span>;
                    }
                }
                <span class="kwrd">if</span>(geocodeAddress){
                    infowindow.set_content(<span class="str">'&lt;strong&gt;現在地：&lt;/strong&gt;&lt;br /&gt;&lt;span style=&quot;font-size:80%&quot;&gt;'</span>+geocodeAddress+<span class="str">'&lt;/span&gt;&lt;br /&gt;&lt;strong&gt;GeoPo：&lt;/strong&gt;&lt;br /&gt;&lt;span style=&quot;font-size:80%&quot;&gt;http://geopo.at/'</span>+geopo+<span class="str">'&lt;/span&gt;&lt;hr /&gt;&lt;a href=&quot;http://twitter.com/home?status='</span>+encodeURIComponent(<span class="str">' L:'</span>+geocodeAddress+<span class="str">' http://geopo.at/'</span>+geopo)+<span class="str">'&quot; target=&quot;twitter&quot;&gt;TwitterにPOSTする&lt;/a&gt;'</span>);
                    infowindow.open(map, marker);
                } <span class="kwrd">else</span>{
                    alert(<span class="str">&quot;現在地が取得できませんでした＞＜&quot;</span>);
                }
            } <span class="kwrd">else</span> {
                alert(<span class="str">&quot;Geocoder failed due to: &quot;</span> + status);
            }
        });
    }

    google.maps.<span class="kwrd">event</span>.addListener(marker, <span class="str">'click'</span>, <span class="kwrd">function</span>() {
        infowindow.open(map,marker);
    });
}

<span class="kwrd">function</span> handleError(positionError) {
    alert(<span class="str">'Attempt to get location failed: '</span> + positionError.message);
}

geo.getCurrentPosition(displayMap, handleError);

&lt;/script&gt;
&lt;/head&gt;
&lt;body style=<span class="str">&quot;margin:0px; padding:0px;&quot;</span>&gt;
  &lt;div id=<span class="str">&quot;map_canvas&quot;</span> style=<span class="str">&quot;width: 100%; height: 100%;&quot;</span>&gt;&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;</pre>
<p>&#160;</p>
<h3>こんな風に現在位置が取れるよ<br />
<style type="text/css">
<p>.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
</h3>
<h4>１．さきほどのURLにアクセスする</h4>
<p><a href="http://creco.net/wp-content/uploads/device01.png" rel="lightbox[535]"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="device01" border="0" alt="device01" src="http://creco.net/wp-content/uploads/device01-thumb.png" width="162" height="242" /></a></p>
<p>すると、Gearsで「現在地情報にアクセス」しますかというメッセージがでるので、OKを押してください。ドメインごとの許可ですかね？</p>
<h4>２． 現在地の地図を表示</h4>
<p><a href="http://creco.net/wp-content/uploads/device02.png" rel="lightbox[535]"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="device02" border="0" alt="device02" src="http://creco.net/wp-content/uploads/device02-thumb.png" width="162" height="242" /></a> </p>
<p>Gearsからの位置情報をMaps API V3で地図表示。ちゃんと、拡大縮小コントローラーもAndroidなUIになってる。</p>
<p>そして、Maps API V3の逆ジオコーディングを使って、現在住所を取ってくる。</p>
<p>ついでに、GeoPoのエンコードもしてるよ！</p>
<p>一番下のリンクがTwitterにポストするためのリンク。</p>
<h4>３．TwitterにPOST内容を渡す</h4>
<p><a href="http://creco.net/wp-content/uploads/device03.png" rel="lightbox[535]"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="device03" border="0" alt="device03" src="http://creco.net/wp-content/uploads/device03-thumb.png" width="162" height="242" /></a> </p>
<p>http://twitter.com/home/?status=[ポスト内容] で渡すことができるから、単純に URLエンコードしたものを渡してるだけ。</p>
<p>ただ、このようなTwitterのパラメータ渡しは、Twitterの表示モードがモバイルになってると無効になるみたいなので、あらかじめスタンダードに変更しておいてください。</p>
<h3>ブラウザでのGeolocation APIについて</h3>
<p>実は、Google Gearsに対応していれば、ChromeとかFirefox（要アドオン）でも上記のURLで現在地の位置情報が取得できる。</p>
<p>正確にいうと、IPから推測した位置情報なので正しくはないかもしれないけど、JavaScriptだけの実装で簡易的に位置情報が取れるのは素敵ですね。</p>
<p>将来的には、W3CのGeolocation APIが載って、開発者側はハードウェア、ソフトウェアの差異を何も考えなくて位置情報を使ったコンテンツに注力できるっていう世界になってくれると幸せです。</p>
<p>Windows 7 では、OSレベルにGeolocation APIがあるそうなので、そちらも楽しみ… その前にIEをなんとかしてｋ（ｒｙ</p>
]]></content:encoded>
			<wfw:commentRss>http://creco.net/2009/06/11/google_maps_api_v3_with_gears_geolocation_api/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://creco.net/2009/06/11/google_maps_api_v3_with_gears_geolocation_api/" />
	</item>
		<item>
		<title>初めてのジオキャッシングをやってみたよ</title>
		<link>http://creco.net/2008/08/09/my_first_geocaching/</link>
		<comments>http://creco.net/2008/08/09/my_first_geocaching/#comments</comments>
		<pubDate>Sat, 09 Aug 2008 13:06:51 +0000</pubDate>
		<dc:creator>inagaki</dc:creator>
				<category><![CDATA[野外活動]]></category>
		<category><![CDATA[Geocaching]]></category>
		<category><![CDATA[GPS]]></category>
		<category><![CDATA[PeerCast]]></category>
		<category><![CDATA[自転車]]></category>

		<guid isPermaLink="false">http://inagaki.co.uk/archives/133</guid>
		<description><![CDATA[ 
緯度経度で場所を指定され、その場所に行けばお宝がGETできるというゲーム、ジオキャッシングに挑戦してみた（＋PeerCastで生中継）。
Yatsuomote mountain
西尾市の北東に位置する八ツ面山の山頂付 [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://creco.net/wp-content/uploads/20080809.jpg" rel="lightbox[437]"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="20080809" border="0" alt="20080809" src="http://creco.net/wp-content/uploads/20080809_thumb.jpg" width="424" height="274" /></a> </p>
<p>緯度経度で場所を指定され、その場所に行けばお宝がGETできるというゲーム、ジオキャッシングに挑戦してみた（＋PeerCastで生中継）。</p>
<h3><a href="http://www.geocaching.com/seek/cache_details.aspx?wp=GCNRFX">Yatsuomote mountain</a></h3>
<p>西尾市の北東に位置する八ツ面山の山頂付近にあるキャッシュ。</p>
<p> <object width="400" height="300" data="http://www.vimeo.com/moogaloop.swf?clip_id=1496339&amp;server=www.vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=&amp;fullscreen=1" type="application/x-shockwave-flash"><param name="src" value="http://www.vimeo.com/moogaloop.swf?clip_id=1496339&amp;server=www.vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=&amp;fullscreen=1" /><param name="allowfullscreen" value="true" /></object>
<p><a href="http://www.vimeo.com/1496339?pg=embed&amp;sec=1496339">20080809 西尾ジオキャッシング1</a> from <a href="http://www.vimeo.com/user647178?pg=embed&amp;sec=1496339">Inagaki</a> on <a href="http://vimeo.com?pg=embed&amp;sec=1496339">Vimeo</a>.    <br />自転車で現場へ向かうまで</p>
<p> <object width="400" height="300" data="http://www.vimeo.com/moogaloop.swf?clip_id=1496421&amp;server=www.vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=&amp;fullscreen=1" type="application/x-shockwave-flash"><param name="src" value="http://www.vimeo.com/moogaloop.swf?clip_id=1496421&amp;server=www.vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=&amp;fullscreen=1" /><param name="allowfullscreen" value="true" /></object>
<p><a href="http://www.vimeo.com/1496421?pg=embed&amp;sec=1496421">20080809 西尾ジオキャッシング2</a> from <a href="http://www.vimeo.com/user647178?pg=embed&amp;sec=1496421">Inagaki</a> on <a href="http://vimeo.com?pg=embed&amp;sec=1496421">Vimeo</a>.    <br />八ツ面山でジオキャッシングをする！</p>
<h3><a href="http://www.geocaching.com/seek/cache_details.aspx?wp=GC16NA5">The secret base of children</a></h3>
<p>西尾市の市街にある西尾市歴史公園内のキャッシュ。</p>
<p> <object width="400" height="300" data="http://www.vimeo.com/moogaloop.swf?clip_id=1496468&amp;server=www.vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=&amp;fullscreen=1" type="application/x-shockwave-flash"><param name="src" value="http://www.vimeo.com/moogaloop.swf?clip_id=1496468&amp;server=www.vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=&amp;fullscreen=1" /><param name="allowfullscreen" value="true" /></object>
<p><a href="http://www.vimeo.com/1496468?pg=embed&amp;sec=1496468">20080809 西尾ジオキャッシング3</a> from <a href="http://www.vimeo.com/user647178?pg=embed&amp;sec=1496468">Inagaki</a> on <a href="http://vimeo.com?pg=embed&amp;sec=1496468">Vimeo</a>.    <br />八ツ面山のジオキャッシングの続きと歴史公園への移動（途中に寄ったコンビニでは編集をいれてます）</p>
<p> <object width="400" height="300" data="http://www.vimeo.com/moogaloop.swf?clip_id=1496498&amp;server=www.vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=&amp;fullscreen=1" type="application/x-shockwave-flash"><param name="src" value="http://www.vimeo.com/moogaloop.swf?clip_id=1496498&amp;server=www.vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=&amp;fullscreen=1" /><param name="allowfullscreen" value="true" /></object>
<p><a href="http://www.vimeo.com/1496498?pg=embed&amp;sec=1496498">20080809 西尾ジオキャッシング4</a> from <a href="http://www.vimeo.com/user647178?pg=embed&amp;sec=1496498">Inagaki</a> on <a href="http://vimeo.com?pg=embed&amp;sec=1496498">Vimeo</a>.    <br />歴史公園でジオキャッシング！</p>
<p>で。</p>
<p>残念ながら両方ともキャッシュの獲得ならず。本当に悔しい。</p>
<p>でも、経験したことのない・することのない機会を作ってくれるジオキャッシングというゲームは面白いね。西尾にこんなところがあったのかという発見だけでも、十分すぎるほどの収穫です。</p>
<p>次回やる場合は、スコップなどの掘る物・軍手・虫除けは必須。</p>
<p>さて、どこに行こうかな。</p>
]]></content:encoded>
			<wfw:commentRss>http://creco.net/2008/08/09/my_first_geocaching/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://creco.net/2008/08/09/my_first_geocaching/" />
	</item>
		<item>
		<title>Pythonおもしろくなってきたかも</title>
		<link>http://creco.net/2008/07/30/interested_in_python/</link>
		<comments>http://creco.net/2008/07/30/interested_in_python/#comments</comments>
		<pubDate>Tue, 29 Jul 2008 18:16:32 +0000</pubDate>
		<dc:creator>inagaki</dc:creator>
				<category><![CDATA[作ってみた]]></category>
		<category><![CDATA[GPS]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://inagaki.co.uk/archives/122</guid>
		<description><![CDATA[ 
ぶっちゃけていうと、素のままではできることが少なく、最初からいろんな関数があたえられてるPHPと比べると大変なんだけど、シンプルさとソースの見やすさから好きになりそうな言語。わかりやすいし。
それで、GPSとのシリア [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://creco.net/wp-content/uploads/20080730.jpg" rel="lightbox[429]"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="20080730" border="0" alt="20080730" src="http://creco.net/wp-content/uploads/20080730_thumb.jpg" width="324" height="244" /></a> </p>
<p>ぶっちゃけていうと、素のままではできることが少なく、最初からいろんな関数があたえられてるPHPと比べると大変なんだけど、シンプルさとソースの見やすさから好きになりそうな言語。わかりやすいし。</p>
<p>それで、GPSとのシリアル通信のプログラムなんだけど、   <br />今まで readline() で読んでたところを、timeout値を1秒近辺（後述）にし read() で取ってやるとつまりもなく、非常にスムース</p>
<p>GPSからの出力データは1秒おきにどばっとくる。そこで、timeout値は0.9秒にしてやって、データがシンクロできるようにとPythonの計算時間を考慮して、一定のコンマ秒で read() する時間を逐次調節するように</p>
<p>ソースは以下の通り</p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:63a42e4b-559e-4b0a-aaac-32c07989f89a" class="wlWriterSmartContent">
<pre class="py:collapse">#!/usr/bin/python

import sys, os, os.path, serial, urllib, urllib2, socket, thread, time

socket.setdefaulttimeout(10)

serialPort = 'COM6' #EeePC usb
#serialPort = 'COM3' #EeePC bluetooth
url = 'hogehoge'

tryCount = 0
baseTime = 0

def getGprmcSentence():
	global baseTime

	while True:
		try :
			buffer = ser.read(1000)
		except :
			print &quot;error&quot;
			return &quot;error&quot;

		if int(time.time()) + baseTime - time.time() &gt; 0:
			time.sleep(int(time.time()) + baseTime - time.time() )

		if buffer[0:6] != '$GPGGA':
			print 'sync...'+&quot;\n&quot;
			time.sleep(0.1)
			if baseTime &gt; 0.9:
				baseTime -= 0.9
			else:
				baseTime += 0.1

		if buffer[12:13] == '0':
			lines = buffer.split(&quot;\r\n&quot;)
			data = []

			for line in lines:
				nmea = line.split(',')

				if nmea[0] == '$GPGGA':
					if len(nmea) == 15 and nmea[14][0:1] == '*':
						data.append(nmea[9])
				elif nmea[0] == '$GPRMC':
					if len(nmea) == 13 and nmea[12][1:2] == '*':
						data.append(nmea[3])
						data.append(nmea[5])
						data.append(nmea[7])
						data.append(nmea[8])
						data.append(nmea[9])
						data.append(nmea[1])

			args = (data,)
			print &quot;thread start...&quot;
			thread.start_new_thread(putGpsData, args)

def putGpsData(args) :

	global tryCount

	params = {
	    &quot;date&quot; : args[5],
	    &quot;time&quot; : args[6],
	    &quot;latitude&quot; : args[1],
	    &quot;longitude&quot; : args[2],
	    &quot;altitude&quot; : args[0],
	    &quot;speed&quot; : args[3],
	    &quot;heading&quot; : args[4],
	}

	try:
		urllib2.urlopen(url, urllib.urlencode(params))
	except urllib2.HTTPError, e:
		print e

	tryCount = tryCount+1

	print tryCount
	print args
	print &quot;\n&quot;

def connect() :
	global ser, baseTime

	try:
		ser = serial.Serial(serialPort, 38400, bytesize=8, parity='N', stopbits=1, timeout=0.9, xonxoff=0, rtscts=0)
	except serial.SerialException, e:
		print e

	baseTime = time.time() - int(time.time());

	while True:
		temp = getGprmcSentence()
		if temp == &quot;error&quot;:
			ser.close()
			return

	ser.close()

while True:
	connect()
	time.sleep(5)
	print &quot;reconnect...&quot;</pre>
</div>
<p>んで、あとはGPSのデータから読み取ったデータにおいて10秒おきにスレッドでPUTしてやる。</p>
<p>そのPUTもhttpのタイムアウト値が10秒以上超してしまうと、整合性があわなくなるので、httpのタイムアウト値も10秒に設定</p>
<p>以前は、NMEAフォーマットのRMCセンテンスだけしかとってなかったので高度が取得できなかったけど、GGAセンテンスも読み取って高度をゲットや！</p>
<p>最後に、USBやBluetoothが途中に抜かれたり、通信エラーしても復帰できるように例外処理からsleep()かけて5秒後に復帰処理するように</p>
<p>PHPのほうは、Ajaxによる更新時間とGPSデータの更新時間が近すぎるとタイミングによってデータの2重取得や取得逃しが発生するので、GPSデータの更新時間から5秒後に更新する（実際にはサーバ時間で秒数の一桁が5秒のとき・・・サーバ時間が正しいことが前提だけどね）ように初回Ajax更新時間を調節</p>
<p>いろんなところにいって早く試したいなｗ</p>
]]></content:encoded>
			<wfw:commentRss>http://creco.net/2008/07/30/interested_in_python/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://creco.net/2008/07/30/interested_in_python/" />
	</item>
		<item>
		<title>GPSロガーとのシリアル通信</title>
		<link>http://creco.net/2008/07/27/serial_gps-logger/</link>
		<comments>http://creco.net/2008/07/27/serial_gps-logger/#comments</comments>
		<pubDate>Sat, 26 Jul 2008 18:33:34 +0000</pubDate>
		<dc:creator>inagaki</dc:creator>
				<category><![CDATA[作ってみた]]></category>
		<category><![CDATA[GPS]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://inagaki.co.uk/archives/119</guid>
		<description><![CDATA[pythonのシリアルモジュール使ってるんだけど、シリアルの入力をreadline()で取ってくると、1秒おきに10行程度の測位データを送ってくるのに間に合わずにバッファに溜まってしまうという現象が起きた。
面倒なんで、 [...]]]></description>
			<content:encoded><![CDATA[<p>pythonのシリアルモジュール使ってるんだけど、シリアルの入力をreadline()で取ってくると、1秒おきに10行程度の測位データを送ってくるのに間に合わずにバッファに溜まってしまうという現象が起きた。</p>
<p>面倒なんで、5秒おきにシリアルを受信しにいって、データが取れたら切断するというふうに改良したんだけど、今度はBluetoothでの通信やりとりがせいいっぱいみたいで、GPSロガー本体もオンオフ繰り返して、とっても苦しそう。</p>
<p>次に、POSTする処理をスレッドにすることでシリアル入力を楽にさせよう大作戦を行ったのだが、まったく無意味。</p>
<p><a title="http://ymasuda.jp/python/pyserial/pyserial.html" href="http://ymasuda.jp/python/pyserial/pyserial.html">http://ymasuda.jp/python/pyserial/pyserial.html</a></p>
<p>ヒントを探すためにpySerialのREADMEを見ると、</p>
<blockquote><p>flushInput() # 入力バッファをフラッシュ</p></blockquote>
<p>おお、これだ！</p>
<p>今度はいい感じで5秒おきを守ってリアルタイムに動いてくれてる。</p>
<p>まず、最初にドキュメント見るってことを肝に銘じます。</p>
]]></content:encoded>
			<wfw:commentRss>http://creco.net/2008/07/27/serial_gps-logger/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://creco.net/2008/07/27/serial_gps-logger/" />
	</item>
		<item>
		<title>Webカメラの「Qcam Pro for Notebooks」が届いたヨ</title>
		<link>http://creco.net/2008/07/25/get_webcamera_qcam-pro-for-notebooks/</link>
		<comments>http://creco.net/2008/07/25/get_webcamera_qcam-pro-for-notebooks/#comments</comments>
		<pubDate>Fri, 25 Jul 2008 12:48:40 +0000</pubDate>
		<dc:creator>inagaki</dc:creator>
				<category><![CDATA[レビュー]]></category>
		<category><![CDATA[EeePC]]></category>
		<category><![CDATA[GPS]]></category>

		<guid isPermaLink="false">http://inagaki.co.uk/archives/118</guid>
		<description><![CDATA[20080725 GPS＋車載テスト走行
もう、Webカメラってもんじゃないんですね。そのままデジカメ・ビデオカムの代わりとして使ってもいい画質の精細さと、オートフォーカス・光量などの自動調節が素晴らしい。普通、暗いとこ [...]]]></description>
			<content:encoded><![CDATA[<p><object classid='clsid:d27cdb6e-ae6d-11cf-96b8-444553540000' codebase='http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=8,0,0,0' align='middle' width='400' height='330'><param name="allowScriptAccess" value="always" /><param name="movie" value="http://eyevio.jp/fla/emp_embed_solo.swf" /><param name="quality" value="high" /><param name="devicefont" value="true" /><param name="flashvars" value="plain=true&amp;movieId=143856&amp;width=400&amp;height=330&amp;thumUrl=http://eyevio.jp/_images/G/G6/G6ed3cbf4e376f79142ea648c75e345a/143856/efayeqsfuklwnqzyqmsx_ta.jpg&amp;movie=143856&amp;hostName=http://eyevio.jp&amp;onCompleteDisplayPath=http://eyevio.jp/fla/OnCompleteDisplay.swf?hdlink=http://eyevio.jp/ent/HD" /><param name="wmode" value="transparent" /><embed src="http://eyevio.jp/fla/emp_embed_solo.swf" wmode="transparent" quality="high" devicefont="true" width="400" height="330" name="flvplayer" align="middle" allowScriptAccess="always" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="plain=true&amp;movieId=143856&amp;width=400&amp;height=330&amp;thumUrl=http://eyevio.jp/_images/G/G6/G6ed3cbf4e376f79142ea648c75e345a/143856/efayeqsfuklwnqzyqmsx_ta.jpg&amp;movie=143856&amp;hostName=http://eyevio.jp&amp;onCompleteDisplayPath=http://eyevio.jp/fla/OnCompleteDisplay.swf?hdlink=http://eyevio.jp/ent/HD" /><noembed><a href="http://eyevio.jp/movie/143856"><img src="http://eyevio.jp/_images/G/G6/G6ed3cbf4e376f79142ea648c75e345a/143856/leegbsjcqwedzyjjikdd_w1.jpg" />20080725 GPS＋車載テスト走行</a></noembed></object>
<p>もう、Webカメラってもんじゃないんですね。そのままデジカメ・ビデオカムの代わりとして使ってもいい画質の精細さと、オートフォーカス・光量などの自動調節が素晴らしい。普通、暗いところでカメラ映そうとしても、映らないかISO感度が上がってノイズの乗ったひどい画質になるんだけど、このカメラは余裕で人間の目を同じように捉えてくれる。</p>
<p>こいつをQVGAで200kbpsという申し訳ないエンコードで使ってもったいないように感じるんだけど、動画の動きが激しくないときにコイツの本領が発揮されてるんで、よかったら動画でご確認ください。</p>
<p>今日は暑かったのでエアコン効いてる車で車載動画っていうのをテストとして撮ってみた。バックミラーにWebカメラのクリップを挟むだけで固定できちゃって楽チンすぎる。</p>
<p>一方でGPSのテスト。昨日の夜に作った、</p>
<ul>
<li>GPSロガーからの情報をシリアル経由（Bluetoothをシリアルでエミュレート）でPythonでこしらえた実質5行くらいのプログラムでサーバにPOSTしてやり </li>
<li>サーバ側ではPOSTされたデータを単純に追加書き込みするPHPプログラム（どうせならPythonで作れよｗ） </li>
<li>蓄積されたデータをGoogleMapsのPolyLineとMarkerに変換して表示するPHPプログラム（どうせなｒ） </li>
</ul>
<p>を実際に動いて試す。</p>
<p><a href="http://creco.net/wp-content/uploads/20080725.jpg" rel="lightbox[425]"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="20080725" border="0" alt="20080725" src="http://creco.net/wp-content/uploads/20080725_thumb.jpg" width="324" height="244" /></a> </p>
<p>んで、思い通りのものが、簡単にできたのでオワリ。</p>
<p>1秒おきのデータはポイント数が大きくなりすぎるとか、自動で更新されないのがダサイとか、アイコンは自転車のアイコンにして進行方向に向いた形にしたい（API見たけど、回転のパラメータないから方向別に用意せなあかん）よねとか あるので、ちょっとずつ面白いものにしていきたいな。</p>
]]></content:encoded>
			<wfw:commentRss>http://creco.net/2008/07/25/get_webcamera_qcam-pro-for-notebooks/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://creco.net/2008/07/25/get_webcamera_qcam-pro-for-notebooks/" />
	</item>
		<item>
		<title>GPSロガーの「Holux M-241」が届いたヨ</title>
		<link>http://creco.net/2008/07/24/get_gps_logger_holux-m-241/</link>
		<comments>http://creco.net/2008/07/24/get_gps_logger_holux-m-241/#comments</comments>
		<pubDate>Thu, 24 Jul 2008 12:56:03 +0000</pubDate>
		<dc:creator>inagaki</dc:creator>
				<category><![CDATA[レビュー]]></category>
		<category><![CDATA[GPS]]></category>

		<guid isPermaLink="false">http://inagaki.co.uk/archives/116</guid>
		<description><![CDATA[ 
今日はいっぱい通販で買った物が届く日でした、合計4つ。まずはGPSロガーから。
GPSっていうとGARMINとか有名だけど、GPSロガーというガジェットが存在するなんて先日まで知らなかったの。少年時代からGARMIN [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://creco.net/wp-content/uploads/20080724.jpg" rel="lightbox[424]"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="20080724" border="0" alt="20080724" src="http://creco.net/wp-content/uploads/20080724_thumb.jpg" width="324" height="244" /></a> </p>
<p>今日はいっぱい通販で買った物が届く日でした、合計4つ。まずはGPSロガーから。</p>
<p>GPSっていうとGARMINとか有名だけど、GPSロガーというガジェットが存在するなんて先日まで知らなかったの。少年時代からGARMINが欲しくて憧れて、代わりにauのGPS携帯をGETして、gpsOneコマンドを解析したりして満足しちゃって、あれだけ欲しかったGARMINは1回も買ってない。</p>
<p>位置情報にはまってたとき、auのGPS携帯のJavaアプリを作って、サーバと連動したリアルタイム位置表示システムを作ったりしたけど、結局電池消費がすごくてどうしようもなかった記憶。それと同じような、GPSログを刻々と記録し続けるのが、このGPSロガー。本体に10万以上のポイントを記録できて単三電池で12時間も動くすごいやつ。</p>
<p>早速つかってみた。 ・・家の中でつかっても面白くもなんともない。</p>
<p>PCとの接続はUSBかBluetoothで疑似シリアルポートとして繋ぐ。ログの転送や変換とか一通り使い勝手を試す。まぁ、これが普通の使い方。やりたかったのは次。</p>
<p>シリアルポート経由でリアルタイムの位置情報が取れる。それによって、カシミールとかでリアルタイムナビができるわけ。この位置情報をネットにアップすれば、以前やってたauのシステムがGPSロガーでもできるだろう。</p>
<p>既に、先人の方がやってて、その方法を試してみた。   <br /><a href="http://goopstechnologies.com/">GooPs</a>というGPSデータをGoogleEarthに渡すソフトがあるんだけど、そのオプションで<a href="http://gpsgate.com/">GpsGate.com</a>（位置情報を公開するWebサービス）にデータを送る設定があって、それをポチッとすれば簡単に自分の現在位置情報が全世界で見られるようになる。オッケー完璧！</p>
<p>だけど、なんかものたんない。</p>
<p>どうせだから、位置情報をサーバ側で保存したいし、将来的にストリームサーバで動画に位置情報レイヤーを合成するとかもやってみたい。それには、独自でシリアル叩いて、その位置情報を自分のサーバにアップするプログラムが必要なの。</p>
<p>処理的にはたいしたことやらないから、LightWeightなのでサクッと作れて、シリアルのモジュールがあるものってところで検討したところ、</p>
<h5>GPSリアルタイムトラッキングしてみた   <br /><a title="http://d.hatena.ne.jp/hidep22/20080503/1209815231" href="http://d.hatena.ne.jp/hidep22/20080503/1209815231">http://d.hatena.ne.jp/hidep22/20080503/1209815231</a></h5>
<p>おっ、なんかよさそう。Pythonってのがそそる。前に横浜でのGoogleカンファレンスで話をきいたGoogle Map for APIも使えるかも！！</p>
<p>そんなこんなで、現在Pythonの勉強がてら、プログラム作成中。ひさびさにやる気モード。</p>
]]></content:encoded>
			<wfw:commentRss>http://creco.net/2008/07/24/get_gps_logger_holux-m-241/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://creco.net/2008/07/24/get_gps_logger_holux-m-241/" />
	</item>
	</channel>
</rss>
