2011-12-28 21 views
1

私はArduino w/GPSチップを持って、NMEAの文字列を処理します。私はHTMLファイルを開いて、x秒ごとに自動リフレッシュを行います。マーカーは更新されますが、リフレッシュを行わずに位置情報を更新できるようにしたいと思っています。私はそれがここでデモとしてドラッグ&ドロップで行うことができることを知っています:http://gmaps-samples-v3.googlecode.com/svn/trunk/draggable-markers/draggable-markers.htmlしかし、私はそのドラッグイベントを置き換える代わりに、新しい座標を押し出してPythonを使用する方法を知る必要があります。新しい座標情報をWebページに取り込む方法が必要です。どんな助力/提案も非常に高く評価されるでしょう。この問題に実際に適用できる唯一のクラスはGoogleMapです。私は多くのウェブサイトに慣れていないので、シンプルな方が良いです。私が持っているものgpsのコードに基づいてGoogleマップの位置を更新

のpython - 新しい座標での、 map.htmlの更新を差し込むmap.htmlオーバー>令状とピックアップし、どのような

新しい位置を表示する - > のpythonを自動再/ wのWebページを開きます私がしたい:

のpython - >新しい位置{{}}新しいCOORDSにマーカーが移動し

import re 
import sys 
import copy 
import time 
import threading 
import Queue 
import serial 
import webbrowser 
import traceback 
import random 
import math 
import turtle 
from pprint   import pprint 
from collections import OrderedDict 

class MockIo(object): 

    def __init__(self): 
     pass 

    def read(self,buff): 
     lat = str(random.random())[2:6] 
     lon = str(random.random())[2:6] 
     return "$GPGGA,172307.000,3913.%s,N,07716.%s,W,2,10,0.8,199.9,M,-33.4,M,3.8,0000*46\r\n" % (lat,lon) 

    def write(self,buff): 
     pass 

class GPSTurtle(object): 

    def __init__(self, new_x = 0, new_y = 0): 
     self.t = turtle.Turtle() 
     self.x_coord = new_x 
     self.y_coord = new_y 

     self.diff_x = 0 
     self.diff_y = 0 
     self.heading = 0 
     self.origin_x = 0 
     self.origin_y = 0 

    def initialize_origin(self, new_x, new_y): 
     self.origin_x = self.origin_x - new_x 
     self.origin_y = self.origin_y - new_y 

    def __update_pos(self, new_x, new_y): 
     new_x  += self.origin_x 
     new_y  += self.origin_y 
     new_x *= 20 
     new_y *= 20 
     self.diff_x = new_x - self.x_coord 
     self.diff_y = new_y - self.y_coord 
     if 0 == self.diff_x: 
      if self.diff_y > 0: 
       self.heading = 90 
      elif self.diff_y < 0: 
       self.heading = 270 
     elif 0 == self.diff_y: 
      if self.diff_x > 0: 
       self.heading = 0 
      elif self.diff_x < 0: 
       self.heading = 180 
     else: 
      self.heading = math.degrees(math.atan(float(self.diff_y)/float(self.diff_x))) 
      if self.diff_x < 0: 
       self.heading += 180 
      elif self.diff_y < 0: 
       self.heading += 360 

     self.set_pos(new_x, new_y) 
     print self.diff_x,self.diff_y,self.heading,self.x_coord,self.y_coord 

    def set_pos(self, new_x, new_y): 
     self.x_coord = new_x 
     self.y_coord = new_y 

    def __draw(self): 
     self.t.setheading(self.heading) 
     self.t.pendown() 
     self.t.goto(self.x_coord, self.y_coord) 
     self.t.penup() 

    def ungps(self, new_x, new_y): 
     new_x = int(1000.0 * new_x) 
     new_y = int(1000.0 * new_y) 
     return (new_x, new_y) 

    def update_and_draw(self, new_x, new_y): 
     self.__update_pos(new_x, new_y) 
     self.__draw() 




class GPS(threading.Thread): 

    def __init__(self, comport = 'COM15', baud = 4800): 
     super(GPS, self).__init__() 
     self.GOOD  = True 
     self.gpgga_keys = [ 
           'message_id', 
           'utc_time', 
           'lattitude', 
           'n_s_ind', 
           'longitude', 
           'e_w_ind', 
           'pos_fix_ind', 
           'satellites', 
           'hdop', 
           'msl_altitude', 
           'units_1', 
           'geoid_sep', 
           'units_2', 
           # 'age_of_diff_corr', gps does not have this field by default 
           'diff_ref_station_id', 
           'checksum', 
          ] 
     self.PSRF103 = { 
           'name':'$PSRF103', 
           'msg':{'GGA':'00','GLL':'01','GSA':'02','GSV':'03','RMC':'04','VTG':'05'}, 
           'mode':{'SetRate':'00','Query':'01'}, 
           'rate':{'off':'00','min':'01','max':'255'}, 
           'cksumEnable':{'disable':'00','enable':'01'}, 
          } 
     self.gps_msg_q = Queue.Queue() 
     self.gps_buff = "" 
     try: 
      self.gps_com = serial.Serial( 
               comport, 
               baud, 
               timeout = 1, 
               parity = serial.PARITY_NONE, 
               rtscts = 0, 
               xonxoff = 0 
              ) 
     except serial.serialutil.SerialException: 
      print "Could not open com port, assuming simulation mode and setting" 
      print "com object to MockIo" 
      self.gps_com = MockIo() 

    def enable_all(self): 
     m = self.PSRF103 
     for msg in m['msg'].values(): 
      st = ','.join([m['name'],msg,m['mode']['Query'],m['rate']['on'],m['cksumEnable']['enable']]) 
      st = self.append_crc(st) 
      self.send_msg(st) 
     self.gps_com.read(4028) 

    def disable_all(self): 
     m = self.PSRF103 
     for msg in m['msg'].values(): 
      st = ','.join([m['name'],msg,m['mode']['Query'],m['rate']['off'],m['cksumEnable']['enable']]) 
      st = self.append_crc(st) 
      self.send_msg(st) 
     self.gps_com.read(4028) 

    def append_crc(self,st): 
     match  = re.compile("\$(.*)") 
     crc  = 0 

     if match.search(st): 
      st = match.search(st).group(1) 

     for letter in st: 
      crc = crc^ord(letter) 
     return "$%s*%0.2x\r\n" % (st,crc) 

    def run(self): 
     self.disable_all() 
     while self.GOOD: 
      self.send_GPGGA_req() 
      time.sleep(2) 

    def send_GPGGA_req(self): 
     m = self.PSRF103 
     st = ','.join([m['name'],m['msg']['GGA'],m['mode']['Query'],m['rate']['off'],m['cksumEnable']['enable']]) 
     st = self.append_crc(st) 
     self.send_msg(st) 

    def parse_msg(self,st): 
     ''' 
      SAMPLE GPGGA MSG 
      "$GPGGA,172307.000,3913.7428,N,07716.7474,W,2,10,0.8,199.9,M,-33.4,M,3.8,0000*46\r\n" 
     ''' 
     retVal = (False,None) 
     st  = st.rstrip('\r\n') 
     parse = st.split(',') 
     if st.startswith('$GPGGA') and len(self.gpgga_keys) == len(parse): 
      retVal = (True, OrderedDict(zip(self.gpgga_keys,parse))) 
     else: 
      pass 

     return retVal 

    def send_msg(self, st): 
     self.gps_com.write(st) 
     self.gps_buff = ''.join([self.gps_buff,self.gps_com.read(1024)]) 
     buffsplit  = re.compile(r'.*?\r\n|.+') 
     splt   = buffsplit.findall(self.gps_buff) 
     if 0 < len(splt): 
      if splt[-1].endswith('\r\n'): 
       self.add_list_to_q(splt) 
       self.gps_buff = "" 
      else: 
       self.add_list_to_q(splt[:-1]) 
       self.gps_buff = splt[-1] 

    def add_list_to_q(self,list_): 
     for item in list_: 
      self.gps_msg_q.put(item,False) 

    def get_item_from_q(self, block = True, timeout = 10): 
     return self.gps_msg_q.get(block, timeout) 

    def convert_lat_lon(self, lat, lon,ns,ew): 
     lat = "%f" % (float(lat[:-7]) + (float(lat[-7:])/60.0)) 
     lon = "%f" % (float(lon[:-7]) + (float(lon[-7:])/60.0)) 
     if 'S' == ns: 
      lat = str(float(lat) * -1.0) 
     if 'W' == ew: 
      lon = str(float(lon) * -1.0) 
     return (lat,lon) 




class GoogleMap(object): 

    def __init__(self, path = 'map.html'): 
     self.path = path 
     self.map_html = ''' 
          <!DOCTYPE html> 
          <html> 
          <head> 
          <meta http-equiv="refresh" content="5" /> 
          <meta name="viewport" content="initial-scale=1.0, user-scalable=no" /> 
          <style type="text/css"> 
           html { height: 100% } body { height: 100%; margin: 0px; padding: 0px } #map_canvas { height: 100% } </style> 
          <script type="text/javascript" 
            src="http://maps.google.com/maps/api/js?sensor=true"> 
          </script> 
          <script type="text/javascript"> 
           function initialize() { 
            var lat = %s 
            var lng = %s 
            var latlng = new google.maps.LatLng(lat,lng); 
            var myOptions = { 
             zoom: 13, 
             center: latlng, 
             mapTypeId: google.maps.MapTypeId.ROADMAP 
            }; 
            var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions); 
            var marker = new google.maps.Marker({position: latlng, map: map, title: %s }); 
           } 
          </script> 
          </head> 
          <body onload="initialize()"> 
           <div id="map_canvas" style="width:100%; height:100%"></div> 
          </body> 
          </html> 
         ''' 

    def write_map(self,lat = '39.229013',long = '-77.445735',marker = '""'): 
     new_map_html = self.map_html % (str(lat), str(long), str(marker).replace('"','')) 
     with open(self.path, 'w') as f: 
      f.write(new_map_html) 

    def launch_browser(self): 
     webbrowser.open_new_tab(self.path) 



if __name__ == "__main__": 
    map = GoogleMap('map.html') 
    map.write_map() 
    map.launch_browser() 

    gps = GPS('COM15',4800) 
    gps.start() 

    t = GPSTurtle() 
    first_update = True 

    try: 
     while True: 
      try: 
       st = gps.get_item_from_q(True,2) 
       success,gpgga = gps.parse_msg(st) 
       if success: 
        lat, lon = gps.convert_lat_lon(gpgga['lattitude'], 
                gpgga['longitude'], 
                gpgga['n_s_ind'], 
                gpgga['e_w_ind']) 
        la,ln = t.ungps(float(lat),float(lon)) 
        if first_update: 
         t.initialize_origin(la,ln) 
         first_update = False 
        else: 
         t.update_and_draw(la,ln) 

        map.write_map(lat,lon,'ME!') 
        time.sleep(5) 
      except Queue.Empty: 
       # pass 
       print "Q-Empty" 
    except: 
     gps.GOOD = False 
     gps.join() 
     print "\n\nEXITING PROGRAM\n\n" 
     traceback.print_exc(file=sys.stdout) 

答えて

1

Inste広告を更新すると、ajaxの短いポーリングをセットアップすることができます。基本的に、数秒ごとにマーカーの位置を返すエンドポイントでページチェックを行います。 Real-time data on webpage with jQuery

もう1つの方法は、長いポーリングを設定することです。ページが更新を待っているサーバーとオープンな接続を維持するようにしてください。大きな面は、座標が変更されるとすぐにUIが更新されるということです。大きな欠点は、サーバーにかなりの負荷がかかり、オープン接続を維持する必要があることです。長いポーリングをスケーリングするのは難しいです。

この投稿はうまく両方のオプションをまとめたものです。Short-polling vs Long-polling for real time web applications?

EDIT:

ここではかなりの粗例だが、それはあなたに継続的に緯度長いを更新するためのシンプルなフレームワークを与える必要があります。事前にお詫びしておきますが、私の経験はウェブサーバーを使用せずに制限されているので、私は考えることのできる最も単純なものを使用しました。これは、インストールと実行が簡単なdevサーバーが付属しています。ここSDKへのリンクです:http://code.google.com/appengine/downloads.html

main.py:

#!/usr/bin/env python 

import os 

from google.appengine.ext import webapp 
from google.appengine.ext.webapp import util 
from google.appengine.ext.webapp import template 

def doRender(handler, page, templatevalues=None): 
    path = os.path.join(os.path.dirname(__file__), page) 
    handler.response.out.write(template.render(path, templatevalues)) 

class MainHandler(webapp.RequestHandler): 
    def get(self): 
     doRender(self, 'template/main.html') 


class AjaxHandler(webapp.RequestHandler): 
    def get(self): 
     self.response.out.write('{ "lat": "1", "long": "1"}') 

def main(): 
    application = webapp.WSGIApplication([('/', MainHandler), 
              ('/data.js', AjaxHandler)], 
             debug=True) 
    util.run_wsgi_app(application) 


if __name__ == '__main__': 
    main() 

のapp.yaml:のルートフォルダの下に

application: ajaxtest 
version: 1 
runtime: python 
api_version: 1 

handlers: 
- url: /favicon\.ico 
    static_files: favicon.ico 
    upload: favicon\.ico 

- url: .* 
    script: main.py 

main.htmlと(フォルダにこれを入れて "テンプレート"プロジェクト):

<html> 
<head> 
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script> 

</head> 
<body> 
<button>Get JSON data</button> 
<div></div> 
<script type="text/javascript"> 
var test = 1; 

function update(){ 
    $.getJSON("/data.js",function(data){ 

    var items = []; 
     $.each(data, function(key, val){ 
     $("div").append(key + ":" + val + " "); 
     }); 
    }); 
    } 

var t=setInterval("update()",1000); 

</script> 
</body> 
</html> 

目的のために、AjaxHandlerを修正してGPS座標を再クエリします。また、$( "div")を変更します。append(key + ":" + val + "");マーカーの座標をGoogleマップに更新します。

これが役に立たない場合や、ねじれた運がない場合は教えてください。私は今日働いているので、もっと多くの時間を捧げることができるはずです。がんばろう!

+0

Webサーバーを設定しないでこれを行うことは可能ですか?Webの経験はありません。私は、ファイルシステムなどを見てそれを行う方法があると考えていました。この例でも、私が必要とする以上に多くのものがあると思われます。http://stackoverflow.com/questions/333664/simple-long-polling-example-code – pyInTheSky

+0

簡単な方法はありません、サンプル#と緯度/経度のjsonファイルを出力し、ファイルを読み込むための単純なajax/jscriptを持っていますね、ねえ、私は新しい座標系を持っています、 ? – pyInTheSky

+0

http://www.html5rocks.com/jp/tutorials/file/dndfiles/がローカルファイルシステムファイルの読み取りに使用できるように見えました。その場合、私はちょうどhtml5 'コード'とjavascriptとのインターフェース方法を知らないままです。 – pyInTheSky

関連する問題