ぶっちゃけていうと、素のままではできることが少なく、最初からいろんな関数があたえられてるPHPと比べると大変なんだけど、シンプルさとソースの見やすさから好きになりそうな言語。わかりやすいし。
それで、GPSとのシリアル通信のプログラムなんだけど、
今まで readline() で読んでたところを、timeout値を1秒近辺(後述)にし read() で取ってやるとつまりもなく、非常にスムース
GPSからの出力データは1秒おきにどばっとくる。そこで、timeout値は0.9秒にしてやって、データがシンクロできるようにとPythonの計算時間を考慮して、一定のコンマ秒で read() する時間を逐次調節するように
ソースは以下の通り
#!/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 "error" return "error" if int(time.time()) + baseTime - time.time() > 0: time.sleep(int(time.time()) + baseTime - time.time() ) if buffer[0:6] != '$GPGGA': print 'sync...'+"\n" time.sleep(0.1) if baseTime > 0.9: baseTime -= 0.9 else: baseTime += 0.1 if buffer[12:13] == '0': lines = buffer.split("\r\n") 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 "thread start..." thread.start_new_thread(putGpsData, args) def putGpsData(args) : global tryCount params = { "date" : args[5], "time" : args[6], "latitude" : args[1], "longitude" : args[2], "altitude" : args[0], "speed" : args[3], "heading" : args[4], } try: urllib2.urlopen(url, urllib.urlencode(params)) except urllib2.HTTPError, e: print e tryCount = tryCount+1 print tryCount print args print "\n" 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 == "error": ser.close() return ser.close() while True: connect() time.sleep(5) print "reconnect..."
んで、あとはGPSのデータから読み取ったデータにおいて10秒おきにスレッドでPUTしてやる。
そのPUTもhttpのタイムアウト値が10秒以上超してしまうと、整合性があわなくなるので、httpのタイムアウト値も10秒に設定
以前は、NMEAフォーマットのRMCセンテンスだけしかとってなかったので高度が取得できなかったけど、GGAセンテンスも読み取って高度をゲットや!
最後に、USBやBluetoothが途中に抜かれたり、通信エラーしても復帰できるように例外処理からsleep()かけて5秒後に復帰処理するように
PHPのほうは、Ajaxによる更新時間とGPSデータの更新時間が近すぎるとタイミングによってデータの2重取得や取得逃しが発生するので、GPSデータの更新時間から5秒後に更新する(実際にはサーバ時間で秒数の一桁が5秒のとき・・・サーバ時間が正しいことが前提だけどね)ように初回Ajax更新時間を調節
いろんなところにいって早く試したいなw