SHARE
TWEET

Modified modes_kml.py for a Xastir feed from gr-air-modes

g0hww Jun 3rd, 2012 334 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #
  2. # Copyright 2010 Nick Foster
  3. #
  4. # This file is part of gr-air-modes
  5. #
  6. # gr-air-modes is free software; you can redistribute it and/or modify
  7. # it under the terms of the GNU General Public License as published by
  8. # the Free Software Foundation; either version 3, or (at your option)
  9. # any later version.
  10. #
  11. # gr-air-modes is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. # GNU General Public License for more details.
  15. #
  16. # You should have received a copy of the GNU General Public License
  17. # along with gr-air-modes; see the file COPYING.  If not, write to
  18. # the Free Software Foundation, Inc., 51 Franklin Street,
  19. # Boston, MA 02110-1301, USA.
  20. #
  21.  
  22. import sqlite3
  23. import string, math, threading, time
  24.  
  25. import subprocess #g0hww - for xastir hack
  26.  
  27. class modes_kml(threading.Thread):
  28.     def __init__(self, dbfile, filename, localpos, timeout=5):
  29.         threading.Thread.__init__(self)
  30.         self._filename = filename
  31.         self._dbfile = dbfile
  32.         self.my_coords = localpos
  33.         self._timeout = timeout
  34.         self.done = False
  35.         self.setDaemon(1)
  36.         self.start()
  37.    
  38.     def run(self):
  39.         while self.done is False:
  40.             self.output()
  41.             time.sleep(self._timeout)
  42.                
  43.         self.done = True
  44.    
  45.     def output(self):
  46.         self._db = sqlite3.connect(self._dbfile)
  47.         kmlstr = self.genkml()
  48.         if kmlstr is not None:
  49.             f = open(self._filename, 'w')
  50.             f.write(kmlstr)
  51.             f.close()
  52.         self._db.close()
  53.    
  54.     def draw_circle(self, center, rng):
  55.         retstr = ""
  56.         steps=30
  57.         #so we're going to do this by computing a bearing angle based on the steps, and then compute the coordinate of a line extended from the center point to that range.
  58.         [center_lat, center_lon] = center
  59.         esquared = (1/298.257223563)*(2-(1/298.257223563))
  60.         earth_radius_mi = 3963.19059
  61.  
  62.         #here we figure out the circumference of the latitude ring
  63.         #which tells us how wide one line of longitude is at our latitude
  64.         lat_circ = earth_radius_mi * math.cos(center_lat)
  65.         #the circumference of the longitude ring will be equal to the circumference of the earth
  66.  
  67.         lat_rad = math.radians(center_lat)
  68.         lon_rad = math.radians(center_lon)
  69.  
  70.         tmp0 = rng / earth_radius_mi
  71.  
  72.         for i in range(0, steps+1):
  73.             bearing = i*(2*math.pi/steps) #in radians
  74.             lat_out = math.degrees(math.asin(math.sin(lat_rad)*math.cos(tmp0) + math.cos(lat_rad)*math.sin(tmp0)*math.cos(bearing)))
  75.             lon_out = center_lon + math.degrees(math.atan2(math.sin(bearing)*math.sin(tmp0)*math.cos(lat_rad), math.cos(tmp0)-math.sin(lat_rad)*math.sin(math.radians(lat_out))))
  76.             retstr += " %.8f, %.8f, 0" % (lon_out, lat_out,)
  77.  
  78.         retstr = string.lstrip(retstr)
  79.         return retstr
  80.    
  81.     def genkml(self):
  82.         '''
  83.        #first let's draw the static content
  84.        retstr="""<?xml version="1.0" encoding="UTF-8"?>\n<kml xmlns="http://www.opengis.net/kml/2.2">\n<Document>\n\t<Style id="airplane">\n\t\t<IconStyle>\n\t\t\t<Icon><href>airports.png</href></Icon>\n\t\t</IconStyle>\n\t</Style>\n\t<Style id="rangering">\n\t<LineStyle>\n\t\t<color>9f4f4faf</color>\n\t\t<width>2</width>\n\t</LineStyle>\n\t</Style>\n\t<Style id="track">\n\t<LineStyle>\n\t\t<color>5fff8f8f</color>\n\t\t<width>4</width>\n\t</LineStyle>\n\t</Style>"""
  85.        retstr += """\t<Folder>\n\t\t<name>Range rings</name>\n\t\t<open>0</open>"""
  86.        
  87.        for rng in [100, 200, 300]:    
  88.                retstr += """\n\t\t<Placemark>\n\t\t\t<name>%inm</name>\n\t\t\t<styleUrl>#rangering</styleUrl>\n\t\t\t<LinearRing>\n\t\t\t\t<coordinates>%s</coordinates>\n\t\t\t</LinearRing>\n\t\t</Placemark>""" % (rng, self.draw_circle(self.my_coords, rng),)
  89.        
  90.        retstr += """\t</Folder>\n\t<Folder>\n\t\t<name>Aircraft locations</name>\n\t\t<open>0</open>"""
  91.        '''
  92.         #read the database and add KML
  93.         q = "select distinct icao from positions where seen > datetime('now', '-10 second')" # g0hww reduced time window to 10 second
  94.         c = self._db.cursor()
  95.         # g0hhw, we get errors saying that the database is locked, so try doing something about it :)
  96.         try:
  97.             c.execute(q)
  98.         except:
  99.             print "modes_kml.genkml() - Exception caught when attempting to initially access database, will try again later"
  100.             return
  101.        
  102.         icaolist = c.fetchall()
  103.         #now we have a list icaolist of all ICAOs seen in the last 1 minutes # g0hww 1 minute
  104.  
  105.         for icao in icaolist:
  106.             #print "ICAO: %x" % icao
  107.             q = "select * from positions where icao=%i and seen > datetime('now', '-2 hour') ORDER BY seen DESC" % icao
  108.             try:
  109.                 c.execute(q)
  110.             except:
  111.                 print "modes_kml.genkml() - Exception caught when attempting to subsequently access database, will try again later"
  112.                 return                
  113.             track = c.fetchall()
  114.             #print "Track length: %i" % len(track)
  115.             if len(track) != 0:
  116.                 lat = track[0][3]
  117.                 if lat is None: lat = 0
  118.                 lon = track[0][4]
  119.                 if lon is None: lon = 0
  120.                 alt = track[0][2]
  121.                 if alt is None: alt = 0
  122.                
  123.                 metric_alt = alt * 0.3048 #google earth takes meters, the commie bastards
  124.                
  125.                 trackstr = ""
  126.                
  127.                 for pos in track:
  128.                     trackstr += " %f, %f, %f" % (pos[4], pos[3], pos[2]*0.3048)
  129.  
  130.                 trackstr = string.lstrip(trackstr)
  131.             else:
  132.                 alt = 0
  133.                 metric_alt = 0
  134.                 lat = 0
  135.                 lon = 0
  136.                 trackstr = str("")
  137.  
  138.             #now get metadata
  139.             q = "select ident from ident where icao=%i" % icao
  140.             try:
  141.                 c.execute(q)
  142.             except:
  143.                 print "modes_kml.genkml() - Exception caught when attempting to penultimately access database, will try again later"
  144.                 return
  145.             r = c.fetchall()
  146.             if len(r) != 0:
  147.                 ident = r[0][0]
  148.             else: ident=""
  149.             #if ident is None: ident = ""
  150.             #get most recent speed/heading/vertical
  151.             q = "select seen, speed, heading, vertical from vectors where icao=%i order by seen desc limit 1" % icao
  152.             try:
  153.                 c.execute(q)
  154.             except:
  155.                 print "modes_kml.genkml() - Exception caught when attempting to finally access database, will try again later"
  156.                 return
  157.             r = c.fetchall()
  158.             if len(r) != 0:
  159.                 seen = r[0][0]
  160.                 speed = r[0][1]
  161.                 heading = r[0][2]
  162.                 vertical = r[0][3]
  163.  
  164.             else:
  165.                 seen = 0
  166.                 speed = 0
  167.                 heading = 0
  168.                 vertical = 0  
  169.                
  170.             # G0HWW - hack for a xastir feed in an aprs format.  
  171.             # we're gonna use the xastir udp client so we don't need a socket,  we just need to create a string, and invoke the udp client binary.
  172.             # We want to send
  173.             # Track ID as the source callsign.  We can't use the flight ID, as we might not know it and we don't want
  174.             # The command will be something like this:
  175.             # xastir_udp_client localhost 2023 G0HWW 11141 "4ca61d>ADS-B:=5223.25N/00035.00E^001/150/A=001234ADS-B Test"
  176.             utility="/usr/local/bin/xastir_udp_client"
  177.             server="localhost"
  178.             port="2023"  
  179.             mycall = "MYCALL"
  180.             mypass="MYPASS"
  181.             net="ADS-B"        
  182.  
  183.             # set up the track info
  184.             actrack=icao[0]
  185.            
  186.             latdm  = '{0:02d}{1:05.2f}{2}'.format(abs(int(lat)), (abs(lat)-abs(int(lat))) * 60, 'S' if (lat<0) else 'N')
  187.             longdm = '{0:03d}{1:05.2f}{2}'.format(abs(int(lon)), (abs(lon)-abs(int(lon))) * 60, 'W' if (lon<0) else 'E')
  188.            
  189.             #consruct the message payload string
  190.             payload = '{0:X}>{1}:={2}/{3}^{4:03.0f}/{5:03.0f}/A={6:06.0f}{7}{8}'.format(actrack,net,latdm,longdm,heading,speed,alt,ident,'')
  191.  
  192.             cmd = '{0} {1} {2} {3} {4} "{5}"'.format(utility,server,port,mycall,mypass,payload)
  193.             print cmd
  194.             subprocess.call(cmd, shell=True)          
  195.             # end G0HWW hack for Xastir
  196.                      
  197.             #now generate some KML
  198.             #retstr+= "\n\t\t<Placemark>\n\t\t\t<name>%s</name>\n\t\t\t<styleUrl>#airplane</styleUrl>\n\t\t\t<description>\n\t\t\t\t<![CDATA[Altitude: %s<br/>Heading: %i<br/>Speed: %i<br/>Vertical speed: %i<br/>ICAO: %x<br/>Last seen: %s]]>\n\t\t\t</description>\n\t\t\t<Point>\n\t\t\t\t<altitudeMode>absolute</altitudeMode>\n\t\t\t\t<extrude>1</extrude>\n\t\t\t\t<coordinates>%s,%s,%i</coordinates>\n\t\t\t</Point>\n\t\t</Placemark>" % (ident, alt, heading, speed, vertical, icao[0], seen, lon, lat, metric_alt, )
  199.  
  200.             #retstr+= "\n\t\t<Placemark>\n\t\t\t<styleUrl>#track</styleUrl>\n\t\t\t<LineString>\n\t\t\t\t<extrude>0</extrude>\n\t\t\t\t<altitudeMode>absolute</altitudeMode>\n\t\t\t\t<coordinates>%s</coordinates>\n\t\t\t</LineString>\n\t\t</Placemark>" % (trackstr,)
  201.  
  202.             #retstr+= '\n\t</Folder>\n</Document>\n</kml>'
  203.         retstr = None      
  204.  
  205.        
  206.         return retstr
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Top