g0hww

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

Jun 3rd, 2012
422
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