<?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; Python</title>
	<atom:link href="http://creco.net/tag/python/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/python/feed/" />
		<item>
		<title>TwitterをSoftalkのゆっくりボイスでしゃべらせる 2</title>
		<link>http://creco.net/2009/07/17/softalk_twitter_to_bring_out_slowly_in_a_voice_of/</link>
		<comments>http://creco.net/2009/07/17/softalk_twitter_to_bring_out_slowly_in_a_voice_of/#comments</comments>
		<pubDate>Thu, 16 Jul 2009 22:39:31 +0000</pubDate>
		<dc:creator>inagaki</dc:creator>
				<category><![CDATA[作ってみた]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Softalk]]></category>
		<category><![CDATA[Twitter]]></category>

		<guid isPermaLink="false">http://creco.net/2009/07/17/softalk_twitter_to_bring_out_slowly_in_a_voice_of/</guid>
		<description><![CDATA[TwitterをSoftalkのゆっくりボイスでしゃべらせる &#124; クレコ
では、python-twitterというライブラリを使っていたわけですが、そもそもタイムライン、メンションを読むだけなら、そこまで高機能なのはいら [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://creco.net/2009/04/13/softalk_tweet_timeline_of_twitter/">TwitterをSoftalkのゆっくりボイスでしゃべらせる | クレコ</a></p>
<p>では、python-twitterというライブラリを使っていたわけですが、そもそもタイムライン、メンションを読むだけなら、そこまで高機能なのはいらない！それに、導入するのが面倒！ってわけで、簡単お気軽に導入できるようにしてみた。</p>
<p> <span id="more-714"></span><br />
<h3>ソース</h3>
<pre class="csharpcode"># -*- coding: utf-8 -*-

import feedparser, os, nkf, re, time

# config
userName = <span class="str">&quot;USERNAME&quot;</span>
passWord = <span class="str">&quot;PASSWORD&quot;</span>
softalkPath = <span class="str">&quot;C:\softalk\softalk.exe&quot;</span>
softalkSpeed = <span class="str">&quot;120&quot;</span>
lastSinceId = 1
lastGetTime = 0

# convert <span class="kwrd">string</span>
def convertString(<span class="kwrd">string</span>):
    # remove HTML entity
    <span class="kwrd">string</span> = re.sub(<span class="str">'&amp;.+;'</span>, <span class="str">' '</span>, <span class="kwrd">string</span>)
    # remove URL
    <span class="kwrd">string</span> = re.sub(<span class="str">'(https?|ftp)(:\/\/[-_.!~*\'()a-zA-Z0-9;\/?:\@&amp;=+\$,%#]+)'</span>, u<span class="str">'ウェブ'</span>, <span class="kwrd">string</span>)

    # remove quote
    <span class="kwrd">string</span> = re.sub(<span class="str">'&quot;'</span>, <span class="str">' '</span>, <span class="kwrd">string</span>)
    <span class="kwrd">string</span> = re.sub(<span class="str">&quot;'&quot;</span>, <span class="str">' '</span>, <span class="kwrd">string</span>)
    <span class="kwrd">string</span> = re.sub(<span class="str">'\/'</span>, <span class="str">' '</span>, <span class="kwrd">string</span>)

    # remove my username
    <span class="kwrd">string</span> = re.sub(<span class="str">'@'</span> + userName , u<span class="str">'あなた'</span>, <span class="kwrd">string</span>)

    # convert unicode to sjis <span class="kwrd">using</span> nkf module
    <span class="kwrd">string</span> = nkf.nkf(<span class="str">&quot;-sX&quot;</span>, <span class="kwrd">string</span>.encode(<span class="str">&quot;utf8&quot;</span>))

    <span class="kwrd">return</span> <span class="kwrd">string</span>

# get twitter timeline
def getTimeline():
    global lastSinceId

    rss = feedparser.parse(<span class="str">'https://'</span> + userName + <span class="str">':'</span> + passWord + <span class="str">'@twitter.com/statuses/mentions.rss?since_id='</span> + str(lastSinceId) )
#    rss = feedparser.parse(<span class="str">'https://'</span> + userName + <span class="str">':'</span> + passWord + <span class="str">'@twitter.com/statuses/friends_timeline.rss?since_id='</span> + str(lastSinceId) )

    <span class="kwrd">if</span> len(rss.entries) &gt; 0:
        lastSinceId = re.search(<span class="str">'\d+$'</span>, rss.entries[0].guid).group()

    reversed(rss.entries)

    <span class="kwrd">for</span> i <span class="kwrd">in</span> rss.entries[::-1]:
        print <span class="str">&quot;%s&quot;</span> % (convertString(i.title))
        os.system(<span class="str">'&quot;'</span> + softalkPath + <span class="str">'&quot; /V:60 /S:'</span>+softalkSpeed+<span class="str">' /T:3 /W:'</span> + convertString(i.title))

<span class="kwrd">while</span> True:
    # time span of get timeline
    <span class="kwrd">if</span> time.time() &gt; lastGetTime + 60:
        lastGetTime = time.time()
        getTimeline()
    <span class="kwrd">else</span>:
        time.sleep(5)</pre>
<h3>解説</h3>
<h4>導入するもの<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>
</h4>
<ul>
<li>Python実行環境</li>
<li><a href="http://www.feedparser.org/">feedparser</a></li>
<li>nkf</li>
<li>SofTalk ver0151（複数起動ができるバージョン）</li>
</ul>
<h4>やっていること</h4>
<p>今回は、feedparser使ってRSSで取得をしています。since_idで最新のものだけを取得しますが、20件以上あった場合のページ処理はしていませんので注意！20件以上あると読み上げが追いつかなくなりそうですけど。</p>
<p>あとは取得した本文をフィルタかけて読み上げるだけ。前はURLとかも全部読ませていたけど、URLなんて読み上げられたところでどうしようもないので、省略して「ウェブ」とだけ読み上げるようにしました。</p>
<p>これも、適当にカスタマイズして使ってもらえればうれしいです。ではでは！</p>
]]></content:encoded>
			<wfw:commentRss>http://creco.net/2009/07/17/softalk_twitter_to_bring_out_slowly_in_a_voice_of/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://creco.net/2009/07/17/softalk_twitter_to_bring_out_slowly_in_a_voice_of/" />
	</item>
		<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>TwitterをSoftalkのゆっくりボイスでしゃべらせる</title>
		<link>http://creco.net/2009/04/13/softalk_tweet_timeline_of_twitter/</link>
		<comments>http://creco.net/2009/04/13/softalk_tweet_timeline_of_twitter/#comments</comments>
		<pubDate>Sun, 12 Apr 2009 23:09:02 +0000</pubDate>
		<dc:creator>inagaki</dc:creator>
				<category><![CDATA[作ってみた]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Softalk]]></category>
		<category><![CDATA[Twitter]]></category>

		<guid isPermaLink="false">http://creco.net/2009/04/13/softalk_tweet_timeline_of_twitter/</guid>
		<description><![CDATA[




（完成動画。時々でてる音は録画用に使ったMacの音です、紛らわしくてごめん。）
2chのスレやしたらば、カキコなどの掲示板をSoftalkで読ませるフロントエンドはあるんだけど、Twitterのタイムラインを読 [...]]]></description>
			<content:encoded><![CDATA[<div id="scid:5737277B-5D6D-4f48-ABFC-DD9C333F4C5D:4dbd3db4-dda8-47ba-af4a-e900c0262666" class="wlWriterEditableSmartContent" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">
<div id="8ef7f156-15c7-477a-bdeb-090127dbb58f" style="margin: 0px; padding: 0px; display: inline;">
<div><a href="http://www.youtube.com/watch?v=XA-KpNdgjCY&amp;hl=ja&amp;fs=1&amp;rel=0" target="_new"><img style="border-style: none" src="http://creco.net/wp-content/uploads/video814103ce00161.jpg" alt="" /></a></div>
</div>
</div>
<p>（完成動画。時々でてる音は録画用に使ったMacの音です、紛らわしくてごめん。）</p>
<p>2chのスレやしたらば、カキコなどの掲示板を<a href="http://cncc.hp.infoseek.co.jp/">Softalk</a>で読ませるフロントエンドはあるんだけど、Twitterのタイムラインを読ませるっていうのは見つからなかったので作ってみた。</p>
<p>TwitterのAPIを読むだけなので、スクラッチで書いてもそんなに難しいものではないんだけど、勉強がてらPythonのpython-twitterというライブラリを使ってみる。</p>
<h5>追記：新しくエントリーを書きました</h5>
<p><a href="../2009/07/17/softalk_twitter_to_bring_out_slowly_in_a_voice_of/">TwitterをSoftalkのゆっくりボイスでしゃべらせる  2 | クレコ</a></p>
<p><span id="more-350"></span></p>
<h4>python-twitterの導入</h4>
<p>実はこれがくそめんどいｗ</p>
<p><a href="http://d.hatena.ne.jp/ama-ch/20080514/1210757894">python-twitterまとめ ～導入まで &#8211; テックノート＠ama-ch</a><br />
を参考にして導入する。</p>
<p>simplejsonは、WindowsでCのコンパイラ環境が必要になったりする。詳しくないので、書いてある通りに実行していった。</p>
<h5>Python 2.6ではhashlibなんちゃらの警告がでます</h5>
<p>別にそのままつかっても問題ないけど毎回警告がでるので直し方。</p>
<p>@aoshimanさんに教えていただいた解決法、<br />
<a href="http://d.hatena.ne.jp/nakku/20090218#1234963425">2009-02-18 &#8211; nakkuの日記</a> [python]python2.6にtwitterのモジュールを入れる<br />
にpatchがあるので、twitter.pyを書き換えればいい。</p>
<p>具体的には、simplejsonモジュールを使っているところをjsonモジュール、md5モジュールを使っているところをhashlibモジュールを使うようにそれぞれ書き換える。</p>
<h4>TwitterのTLをSoftalkでしゃべらせるPythonスクリプト</h4>
<pre class="csharpcode">import twitter, os, nkf, re, time

# config
userName = <span class="str">"username"</span>
passWord = <span class="str">"password"</span>
softalkPath = <span class="str">"C:\hogehoge\softalk.exe"</span>
softalkSpeed = <span class="str">"120"</span>
lastSinceTime = 0
lastGetTime = 0

# convert <span class="kwrd">string</span>
def convertString(<span class="kwrd">string</span>):
    # remove HTML entity
    <span class="kwrd">string</span> = re.sub(<span class="str">'&amp;.+;'</span>, <span class="str">' '</span>, <span class="kwrd">string</span>)
    # remove quote
    <span class="kwrd">string</span> = re.sub(<span class="str">'"'</span>, <span class="str">' '</span>, <span class="kwrd">string</span>)
    <span class="kwrd">string</span> = re.sub(<span class="str">"'"</span>, <span class="str">' '</span>, <span class="kwrd">string</span>)

    # remove my username
    <span class="kwrd">string</span> = re.sub(<span class="str">'^@'</span> + userName + <span class="str">' '</span>, <span class="str">''</span>, <span class="kwrd">string</span>)

    # convert unicode to sjis <span class="kwrd">using</span> nkf module
    <span class="kwrd">string</span> = nkf.nkf(<span class="str">"-sX"</span>, <span class="kwrd">string</span>.encode(<span class="str">"utf8"</span>))

    <span class="kwrd">return</span> <span class="kwrd">string</span>

# get twitter timeline
def getTimeline():
    global lastSinceTime

    api = twitter.Api(userName, passWord)
    statuses = api.GetFriendsTimeline(userName)
    #statuses = api.GetUserTimeline(userName)
    #statuses = api.GetReplies()

    <span class="kwrd">for</span> i <span class="kwrd">in</span> statuses[::-1]:
        <span class="kwrd">if</span> i.created_at_in_seconds &gt; lastSinceTime:
            print <span class="str">"%s : %s"</span> % (convertString(i.user.name), convertString(i.text))
            os.system(<span class="str">'"'</span> + softalkPath + <span class="str">'" /V:60 /S:'</span>+softalkSpeed+<span class="str">' /T:1 /W:'</span> + convertString(i.user.name))

            # when find my name and change voice
            <span class="kwrd">if</span> re.search(userName, i.text):
                os.system(<span class="str">'"'</span> + softalkPath + <span class="str">'" /V:60 /S:'</span>+softalkSpeed+<span class="str">' /T:0 /W:'</span> + convertString(i.text))
            <span class="kwrd">else</span>:
                os.system(<span class="str">'"'</span> + softalkPath + <span class="str">'" /V:60 /S:'</span>+softalkSpeed+<span class="str">' /T:3 /W:'</span> + convertString(i.text))
            lastSinceTime = i.created_at_in_seconds

<span class="kwrd">while</span> True:
    # time span of get timeline
    <span class="kwrd">if</span> time.time() &gt; lastGetTime + 60:
        lastGetTime = time.time()
        getTimeline()
    <span class="kwrd">else</span>:
        time.sleep(5)</pre>
<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; } --></p>
<h5>twitterモジュール</h5>
<blockquote><p>api = twitter.Api(userName, passWord)</p>
<p>statuses = api.GetFriendsTimeline(userName)</p></blockquote>
<p>で、認証してタイムライン（ここではFriendTimeline）を取ってくる。</p>
<p>んで、そのリストは時系列昇順にしゃべらせるために、スライスを使って逆順にし、forで回してやる。</p>
<h5>osモジュール</h5>
<blockquote><p>os.system(<span class="str">&#8216;&#8221;&#8216;</span> + softalkPath + <span class="str">&#8216;&#8221; /V:60 /S:&#8217;</span>+softalkSpeed+<span class="str">&#8216; /T:1 /W:&#8217;</span> + convertString(i.user.name))</p></blockquote>
<p>外部コマンドでSoftalkを実行する。softalkPathにsoftalk.exeの位置を設定して、あとはパラメータ。つぶやきの中に自分のユーザー名があったら音声を変えたり。</p>
<p>/V:ボリューム、/S:スピード、/T:音声パターン、/W:しゃべらせたいテキスト</p>
<p>Softalkのソフトについては後述。</p>
<h5>nkfモジュール</h5>
<p><a href="http://city.plala.jp/moin/NkfPython">NkfPython – Ma2</a></p>
<p>Softalkにコマンド引数として値を渡すときに、UnicodeからS-JISへ変換してやる必要があるんだけど、この変換でencode()を使うとウムラウトとかが原因でエラー。</p>
<p>nkfを使えばいいらしいので、nkf使って変換。</p>
<blockquote><p><span class="kwrd">string</span> = nkf.nkf(<span class="str">&#8220;-sX&#8221;</span>, <span class="kwrd">string</span>.encode(<span class="str">&#8220;utf8&#8243;</span>))</p></blockquote>
<h5>reモジュール</h5>
<blockquote><p>string = re.sub(&#8216;&amp;.+;&#8217;, &#8216; &#8216;, string)</p></blockquote>
<p>HTMLエンティティをそのまま渡すと、コマンド引数が途切れたりしたので、HTMLエンティティはばっさり消しちゃうことにした。re.sub()は正規表現で置き換え。</p>
<p>同様に、先頭に自分のユーザー名が来てるようなreplyメッセージでのユーザー名とか、クォート符号も消す。</p>
<p>他にも何かエラー引き起こす文字があったら、深く考えないで消す。とても適当でごめんなさい。</p>
<h5>timeモジュール</h5>
<p>実行したら無限ループに入れてやり、前回の取得時間より1分以上経っていたら取得しに行く、それ以外なら5秒スリープしてループの先頭に戻る。</p>
<h4>利用するSoftalkのバージョン</h4>
<p>実行してみると、Softalkが実行するときにいちいちWindowがピョコンとでてきて、終了をしてあげないと次のつぶやきをしゃべってくれない。</p>
<p>なんか以前と違うなぁって不思議に思っていたんだけど、</p>
<p>ニコニコ動画のニコ生（生で配信）用のツール</p>
<p><a href="http://d.hatena.ne.jp/ExceptionError/20090318/1237359366">NicoRequest Ver.2.3.2 – ExceptionErrorMessage</a></p>
<p>NicoRequestのドキュメントを読んでみると、どうやらSoftalkの最新バージョンで挙動が変わったらしい。</p>
<p>ver0151に置き換えて実行してみたところ、ちゃんとうまくいって、一番はじめの動画のようにゆっくりボイスでしゃべってくれた。</p>
<h4>感想</h4>
<ul>
<li>声でタイムラインを読んでくれるっていうのは新鮮でおもしろいよ</li>
<li>Softalkは英語が不得意なので、無理にローマ字読みして何いってるかわからないことしばしば</li>
<li>移動体ライブ配信の読み上げに使おうとおもったけど、よく考えると60秒更新スパンくらいが負荷で限界なので、ものすっごくタイムラグ発生するかもね</li>
<li>PythonよりもNicoRequestみたいにJavaScriptで実現したほうがいいかも</li>
<li>SoftalkとそのライブラリAques TalkはWindows版でしか無償でつかえないので、環境を選ぶ</li>
</ul>
<p>つぶやきを送ると、ゆっくりボイスで変換してくれるBOTとか作ったら面白そう。</p>
]]></content:encoded>
			<wfw:commentRss>http://creco.net/2009/04/13/softalk_tweet_timeline_of_twitter/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://creco.net/2009/04/13/softalk_tweet_timeline_of_twitter/" />
	</item>
		<item>
		<title>ジオポの符号化、復号化をいろんな言語で書いてみる Part.2</title>
		<link>http://creco.net/2009/03/10/write_codes_in_variaous_languages_2/</link>
		<comments>http://creco.net/2009/03/10/write_codes_in_variaous_languages_2/#comments</comments>
		<pubDate>Tue, 10 Mar 2009 10:52:19 +0000</pubDate>
		<dc:creator>inagaki</dc:creator>
				<category><![CDATA[日記]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Perl]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[ジオポ]]></category>

		<guid isPermaLink="false">http://creco.net/2009/03/10/write_codes_in_variaous_languages_2/</guid>
		<description><![CDATA[いろんな言語で書いてみると楽しい。他の人の役に立つサンプルコードというよりも、自分のために書いてるところが大きいです。
そんなわけで、今回はC++、Perl、RubyとPythonで書いてみた。
 
サンプルコード
C+ [...]]]></description>
			<content:encoded><![CDATA[<p>いろんな言語で書いてみると楽しい。他の人の役に立つサンプルコードというよりも、自分のために書いてるところが大きいです。</p>
<p>そんなわけで、今回はC++、Perl、RubyとPythonで書いてみた。</p>
<p> <span id="more-151"></span><br />
<h4>サンプルコード</h4>
<h5>C++</h5>
<p>
<div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:cd35fe8e-ef86-4987-a6b6-0b8bd58ba685" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">
<pre name="code" class="c">/*
 * GeoPo Encode in C++
 * @author : Shintaro Inagaki
 * @param geopo, lat lng, scale (pointer)
 */
void geopoEncode(char *geopo, double &amp;lat, double &amp;lng, int &amp;scale)
{
	// 64characters (number + big and small letter + hyphen + underscore)
	char chars[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_";
	int i;

	// Change a degree measure to a decimal number
	lat = (lat + 90) / 180 * pow(8.0, 10.0);
	lng = (lng + 180) / 360 * pow(8.0, 10.0);

	// Compute a GeoPo code from head and concatenate
	for(i = 0;i &lt; scale;i++){
		geopo[i] = chars[(int)(floor(fmod(lat / pow(8.0, 9.0 - i), 8.0)) + floor(fmod(lng / pow(8.0, 9.0 - i), 8.0)) * 8)];
	}
	geopo[i] = '\0';
}		

/*
 * GeoPo Decode in C++
 * @author : Shintaro Inagaki
 * @param geopo, lat lng, scale (pointer)
 */
void geopoDecode(char *geopo, double &amp;lat, double &amp;lng, int &amp;scale)
{
	// 64characters (number + big and small letter + hyphen + underscore)
	char chars[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_";
	int order, i;

	scale = strlen(geopo);

	for(i = 0;i &lt; scale;i++){
		// What number of character that equal to a GeoPo code (0-63)
		order = (strchr(chars, geopo[i]) - chars);
		// Lat/Lng plus geolocation value of scale
		lat = lat + fmod(order, 8.0) * pow(8.0, 9.0 - i);
		lng = lng + floor((double)order / 8.0) * pow(8.0, 9.0 - i);
	}
	// Change a decimal number to a degree measure, and plus revised value that shift center of area
	lat = lat * 180 / pow(8.0, 10.0) - 90 + 180 / pow(8.0, scale) / 2;
	lng = lng * 360 / pow(8.0, 10.0) - 180 + 360 / pow(8.0, scale) / 2;
}	</pre>
</div>
<p>専らライトウェイトなインタプリタ言語ばかりやってるので、C++とかJavaは仕事で扱ったくらいしか経験なく、コンパイル環境すら整えてないので、MicrosoftのVisual C++をダウンロードする作業から開始した。</p>
<p>標準ライブラリのstdio.h、math.hとstring.h を使ってるから、適宜importしてください。Cではコンパイルしてないけど、Cでもokなんじゃないかな？</p>
<p>関数とかは前回のObjective-Cとほとんど同じ。<strong>pow()</strong>、<strong>fmod()</strong>、<strong>floor()</strong>とか。</p>
<p>今回はcharsを配列形式のcharにしてジオポ符号を取り出す形。最後にヌル文字を加えるのをお忘れ無く。</p>
<p>復号化は、<strong>strchr()</strong>でジオポの符号を検索してその位置を返すんだけど、返す型がポインタ。だから、そのポインタの値をcharsの先頭ポインタで引いてやることによって、位置のintを取り出すようにした。</p>
<p>Visual C++って使いづらくない？慣れだと思うけど使っててアレルギーでそうだった&#8230;特にポインタミスって色んなアプリを引き連れにハングアップさせたり&#8230;（自分が悪いけど）</p>
<h5>Perl</h5>
<p><div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:2f89d35f-2a99-4b20-ae96-abaea53be71d" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">
<pre name="code" class="php">#
# GeoPo Encode in Perl
# @author : Shintaro Inagaki
# @param %location (Hash) [lat (Float), lng (Float), scale(Int)]
# @return $geopo (String)
#
sub geopoEncode(%location) {
	# 64characters (number + big and small letter + hyphen + underscore)
	$chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_";

	$geopo = "";
	$lat = $location{'lat'};
	$lng = $location{'lng'};
	$scale = $location{'scale'};

	# Change a degree measure to a decimal number
	$lat = ($lat + 90) / 180 * 8 ** 10;
	$lng = ($lng + 180) / 360 * 8 ** 10;

	# Compute a GeoPo code from head and concatenate
	for($i = 0; $i &lt; $scale; $i++) {
		$geopo .= substr($chars, int($lat / 8 ** (9 - $i) % 8) + int($lng / 8 ** (9 - $i) % 8) * 8, 1);
	}
	return $geopo;
}		

#
# GeoPo Decode in Perl
# @author : Shintaro Inagaki
# @param $geopo (String)
# @return %location (Hash) [lat (Float), lng (Float), scale(Int)]
#
sub geopoDecode($geopo) {
	# 64characters (number + big and small letter + hyphen + underscore)
	$chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_";
	# Hash for geolocation
	%location = ();

	for ($i = 0; $i &lt; length($geopo); $i++) {
		# What number of character that equal to a GeoPo code (0-63)
		$order = index($chars, substr($geopo, $i, 1));
		# Lat/Lng plus geolocation value of scale
		$location{'lat'} += $order % 8 * 8 ** (9 - $i);
		$location{'lng'} += int($order / 8) * 8 ** (9 - $i);
	}

	# Change a decimal number to a degree measure, and plus revised value that shift center of area
	$location{'lat'} = $location{'lat'} * 180 / 8 ** 10 - 90 + 180 / 8 ** length($geopo) / 2;
	$location{'lng'} = $location{'lng'} * 360 / 8 ** 10 - 180 + 360 / 8 ** length($geopo) / 2;
	$location{'scale'} = length($geopo);

	return %location;
}		</pre>
</div>
<p>今から5年くらい前はPHPじゃなくてPerlばかり使ってた。あまりたいしたコードは書いてないけど、どんなスパゲッティコードでもソースを読み取ることができる能力は自慢ｗ まぁ、僕自身がスパゲッティを生産してたわけだけど。</p>
<p>PHPとほぼ変わらない。ユーザ関数は<strong>sub</strong>でも<strong>function</strong>でも、連想配列（ハッシュ）は<strong>%hoge</strong>と<strong>$hoge{&#8216;hoge&#8217;}</strong>みたいになるので注意。ちなみに、ただの配列だと@hoge</p>
<p><strong>%</strong>で余り、<strong>**</strong>でべき乗、<strong>int()</strong>で整数化、<strong>length()</strong>で長さ、<strong>+</strong>で文字の結合、<strong>substr()</strong>で文字の切り出し、<strong>index()</strong>で文字の位置。</p>
<p>PerlもモダンPerlが話題になってるから、再勉強してみようかな。使ってた当時は豊富なライブラリ・モジュールにお世話になりっぱなしで、クラスすら作った経験ないんだよね。</p>
<h5>Ruby</h5>
<p><div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:1dc2a9c3-3934-4212-b815-653c51df37dd" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">
<pre name="code" class="ruby">#
# GeoPo Encode in Ruby
# @author : Shintaro Inagaki
# @param location (Hash) [lat (Float), lng (Float), scale(Int)]
# @return geopo (String)
#
def geopoEncode(location)
	# 64characters (number + big and small letter + hyphen + underscore)
	chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_"

	geopo = ""
	lat = location['lat']
	lng = location['lng']
	scale = location['scale']

	# Change a degree measure to a decimal number
	lat = (lat + 90.0) / 180 * 8 ** 10; # 90.0 is forced FLOAT type when lat is INT
	lng = (lng + 180.0) / 360 * 8 ** 10; # 180.0 is same

	# Compute a GeoPo code from head and concatenate
	for i in 0..scale
		geopo += chars[(lat / 8 ** (9 - i) % 8).floor + (lng / 8 ** (9 - i) % 8).floor * 8, 1];
	end
	return geopo;
end		

#
# GeoPo Decode in Ruby
# @author : Shintaro Inagaki
# @param geopo (String)
# @return location (Hash) [lat (Float), lng (Float), scale(Int)]
#
def geopoDecode(geopo)
	# 64characters (number + big and small letter + hyphen + underscore)
	chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_"
	# Hash for geolocation
	location = {}

	lat = 0.0
	lng = 0.0
	scale = geopo.size # Scale is length of GeoPo code
	order = 0

	for i in 0..(scale - 1)
		# What number of character that equal to a GeoPo code (0-63)
		order = chars.index(geopo[i])
		# Lat/Lng plus geolocation value of scale
		lat = lat + order % 8 * 8 ** (9 - i)
		lng = lng + (order / 8).floor * 8 ** (9 - i)
	end

	# Change a decimal number to a degree measure, and plus revised value that shift center of area
	location['lat'] = lat * 180 / 8 ** 10 - 90 + 180 / 8 ** scale / 2
	location['lng'] = lng * 360 / 8 ** 10 - 180 + 360 / 8 ** scale / 2
	location['scale'] = scale

	return location
end		</pre>
</div>
<p>Rubyも必要になった経験がなかったから、あまり知らない。だけど、ライトウェイトなインタプリタ言語はひとつの言語を知っていれば、サンプルコードを真似して書ける。その中でもRubyは一番とっつきやすい（PHPからPerlから乗換え）と思う。</p>
<p>ユーザ関数は<strong>def</strong>でスタート<strong>end</strong>で終わる。forループも<strong>for</strong>でスタートendで終わる。自然とインデントするので見やすい。連想配列（ハッシュ）も普通の変数と区別なし。</p>
<p><strong>%</strong>で余り、<strong>**</strong>でべき乗、<strong>floor()</strong>で切り捨て、<strong>size</strong>と<strong>length</strong>メソッドどっちでも文字の長さ、<strong>+</strong>で文字の結合、配列と同じ操作で文字列から文字を取り出せる（<strong>slice</strong>メソッド使ってもいい）、<strong>index</strong>で文字の位置</p>
<p>PHP版Ruby on RailsといわれてるCodeIgniterがわかりつつあるので、RoRに移行してもスムースにいけるかな。ただ、本当にRubyじゃないとダメっていう案件がなさすぎる。</p>
<h5>Python</h5>
<p><div class="wlWriterSmartContent" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:d39098f2-8ad1-4ca5-a59f-9243624cbab3" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">
<pre name="code" class="py">#
# GeoPo Encode in Python
# @author : Shintaro Inagaki
# @param location (Dictionary) [lat (Float), lng (Float), scale(Int)]
# @return geopo (String)
#
def geopoEncode(location) :
       # 64characters (number + big and small letter + hyphen + underscore)
       chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_"

       geopo = ""
       lat = location['lat']
       lng = location['lng']
       scale = location['scale']

       # Change a degree measure to a decimal number
       lat = (lat + 90.0) / 180 * 8 ** 10 # 90.0 is forced FLOAT type when lat is INT
       lng = (lng + 180.0) / 360 * 8 ** 10 # 180.0 is same

       # Compute a GeoPo code from head and concatenate
       for i in range(scale):
               order = int(lat / (8 ** (9 - i)) % 8) + int(lng / (8 ** (9 - i)) % 8) * 8
               geopo = geopo + chars[order]

       return geopo		

#
# GeoPo Decode in Python
# @author : Shintaro Inagaki
# @param geopo (String)
# @return location (Dictionary) [lat (Float), lng (Float), scale(Int)]
#
def geopoDecode(geopo) :
       # 64characters (number + big and small letter + hyphen + underscore)
       chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_"

       lat = 0.0
       lng = 0.0
       scale = len(geopo) # Scale is length of GeoPo code
       order = 0

       for i in range(scale):
               # What number of character that equal to a GeoPo code (0-63)
               order = chars.find(geopo[i])
               # Lat/Lng plus geolocation value of scale
               lat = lat + order % 8 * 8 ** (9 - i)
               lng = lng + int(order / 8) * 8 ** (9 - i)

       # Change a decimal number to a degree measure, and plus revised value
that shift center of area
       location['lat'] = lat * 180 / 8 ** 10 - 90 + 180 / 8 ** scale / 2
       location['lng'] = lng * 360 / 8 ** 10 - 180 + 360 / 8 ** scale / 2
       location['scale'] = scale

       return location		</pre>
</div>
<p>GoogleのクラウドでHelloWorldくらいまで勉強した気がｗ その後、GPSロガーとのシリアル通信プログラム（PySerial）書いたときに大活躍！ライトウェイトな言語なくせして、ネイティブなデバイスが簡単に扱えた衝撃はでかかった。</p>
<p>&#8230;えっと。あまりにもRubyと変わらないのであまり書くこともないという。<br />
  <br />Python最大の特徴であるインデントに注意して、あとは<strong>find()</strong>が文字の位置、<strong>range()</strong>で範囲が便利になるよってくらい。</p>
<p>そうだそうだ、RubyとPythonは符号化のローカル変数の代入時にわざとfloatの数値を足してあげて、intで引数がわたされた場合でも強制的にfloatになるようにしてあるよ。</p>
<p>Pythonの話題もよく耳にするようになってきたし、何よりソースコードが強制的にキレイになるっていうのがいいね。</p>
<h4>まとめ</h4>
<p>コンバイラ言語はめんどくさい。ライトウェイト言語ばんざーい。</p>
<p>暇があったら、Haskell（関数型言語）に挑戦したいね。</p>
]]></content:encoded>
			<wfw:commentRss>http://creco.net/2009/03/10/write_codes_in_variaous_languages_2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://creco.net/2009/03/10/write_codes_in_variaous_languages_2/" />
	</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>
	</channel>
</rss>
