У меня Arduino с GPS-чипом, обрабатывающим строки NMEA с Python. У меня есть файл HTML, который я открываю, и я автоматически обновляю его каждые x секунд s.t. маркер обновляется, но я бы очень хотел иметь возможность обновлять информацию о положении без обновления. Я знаю, что это можно сделать с помощью перетаскивания, как показано здесь: http://gmaps -samples-v3.googlecode.com / svn / trunk / draggable-markers / draggable-markers.html , но мне нужно знать, как заменить это событие перетаскивания и вместо этого взаимодействовать с python, выдвигая новые координаты. Мне нужен способ получения моей новой информации о координатах на веб-странице. Любая помощь / предложения будут с благодарностью. Единственный класс, действительно применимый к этой проблеме, это GoogleMap. Я не знаком с большим количеством веб-материалов, поэтому чем проще, тем лучше.
что у меня есть:
python -> открывает веб-страницу с автозагрузкой
python -> пишет поверх map.html, вставляя новые координаты
map.html обновляет, поднимает и отображает новую позицию
что я хочу:
python -> маркер новой позиции {{}} перемещается в новые координаты
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)