Notifications
Clear all

10/18/2023 Map Stopped Working?
Visit this post for the fix

I am working on an 1850 pixel map, need some help with the code.

8 Posts
2 Users
0 Reactions
568 Views
(@marty)
Member
Joined: 4 years ago
Posts: 0
Topic starter  

Hello,

I am working on an 1850 pixel map. But the API request for all of those is too big and the aviationweather.gov server returns an error. 

So I modified the code so it will only send a certain amount (300 at the time). It looks like it works but some airports are shown as Undefinded.

Maybe someone can help with this?

Here is the code I changed in the webapp.py 

I added this lib at #60

from itertools import islice

This var at #139

max_api_airports = 300          # The max amount of airports from api with one request

I also changed this value LED_COUNT = 2000 

And these are my edits from #1533 to #1702

# routine to capture airport information and pass along to web pages.
def get_led_map_info():
    logger.debug('In get_led_map_info Routine')

    global led_map_url
    global led_map_dict
    global lat_list
    global lon_list
    global max_lat
    global min_lat
    global max_lon
    global min_lon

    airports_count = len(airports)
    lmu_tmp = led_map_url
    
    print ("Number of airports in the list: ", airports_count)
    
    tmp_ap = airports_count
    tmp_start = 0
    tmp_end = max_api_airports

    while (tmp_ap >= 0):
    
        print ("tmp_start: ", tmp_start)
        print ("tmp_ap: ", tmp_ap)
        print ("tmp_end: ", tmp_end)
        
        for airportcode in islice(airports, tmp_start, tmp_end):
            lmu_tmp = lmu_tmp + airportcode + ","
        #led_map_url = led_map_url[:-1]
        logger.debug(lmu_tmp) # debug url if neccessary

        while True:  # check internet availability and retry if necessary. If house power outage, map may boot quicker than router.
            try:
                content = urllib.request.urlopen(lmu_tmp).read()
                logger.info('Internet Available')
                logger.info(lmu_tmp)
                break
            except:
                logger.warning('FAA Data Not Available')
                logger.warning(lmu_tmp)
                time.sleep(delay_time)
                content = ''
                pass

        if content  == '':  # if FAA data not available bypass getting apinfo
            return

        root = ET.fromstring(content)  # Process XML data returned from FAA

        for led_map_info in root.iter('METAR'):
            stationId = led_map_info.find('station_id').text

            try:
                lat = led_map_info.find('latitude').text
                lon = led_map_info.find('longitude').text
            except:
                lat = '0'
                lon = '0'

            lat_list.append(lat)
            lon_list.append(lon)

            if led_map_info.find('flight_category') is None:
                fl_cat = 'Not Reported'
            else:
                fl_cat = led_map_info.find('flight_category').text
            led_map_dict[stationId] = [lat,lon,fl_cat]
        
        tmp_ap = tmp_ap - max_api_airports
        tmp_start = tmp_start + max_api_airports
        tmp_end = tmp_end + max_api_airports
        lmu_tmp = led_map_url

    max_lat = max(lat_list)
    min_lat = min(lat_list)
    max_lon = max(lon_list)
    min_lon = min(lon_list)


# routine to capture airport information and pass along to web pages.
def get_apinfo():
    logger.debug('In Get_Apinfo Routine')

    global orig_apurl
    global apinfo_dict
    
    #print (max_api_airports)
    airports_count = len(airports)
    
    print ("Number of airports in the list: ", airports_count)
    apurl = orig_apurl  # Assign base FAA url to temp variable
    tmp_ap = airports_count
    tmp_start = 0
    tmp_end = max_api_airports
    
    while (tmp_ap >= 0):
        print ("tmp_start: ", tmp_start)
        print ("tmp_ap: ", tmp_ap)
        print ("tmp_end: ", tmp_end)
        
        for airportcode in islice(airports, tmp_start, tmp_end):
            apurl = apurl + airportcode + ","
    
        #apurl = apurl[:-1]
        print ("URL string: ", apurl)
        while True:  # check internet availability and retry if necessary. If house power outage, map may boot quicker than router.
            try:
#                s.connect(("8.8.8.8", 80))
                content = urllib.request.urlopen(apurl).read()
                logger.info('Internet Available')
                logger.info(apurl)
                break
            except:
                logger.warning('FAA Data Not Available')
                logger.warning(apurl)
                time.sleep(delay_time)
                content = ''
                pass

        if content == '':  # if FAA data not available bypass getting apinfo
            return
            
        root = ET.fromstring(content)  # Process XML data returned from FAA

        for apinfo in root.iter('Station'):
            stationId = apinfo.find('station_id').text

            if stationId[0] != 'K':
                site = apinfo.find('site').text
                country = apinfo.find('country').text
                apinfo_dict[stationId] = [site,country]

            else:
                site = apinfo.find('site').text
                state = apinfo.find('state').text
                apinfo_dict[stationId] = [site,state]
    
        
                        
        tmp_ap = tmp_ap - max_api_airports
        tmp_start = tmp_start + max_api_airports
        tmp_end = tmp_end + max_api_airports
        apurl = orig_apurl
        
        
    #print (content)
    #content2 = content.decode()
    #file = open("temp123.xml", "w")
    #file.write(content2)
    #file.close()
    
    """
    root = ET.fromstring(content)  # Process XML data returned from FAA

    for apinfo in root.iter('Station'):
        stationId = apinfo.find('station_id').text

        if stationId[0] != 'K':
            site = apinfo.find('site').text
            country = apinfo.find('country').text
            apinfo_dict[stationId] = [site,country]

        else:
            site = apinfo.find('site').text
            state = apinfo.find('state').text
            apinfo_dict[stationId] = [site,state]
    """

 

 


   
Quote
Mark Harris
(@markyharris)
Member Admin Registered
Joined: 5 years ago
Posts: 557
 

Marty, all I can say is "Wow". This will be an awesome map. I can't wait to see a picture. 

If I understand your question properly, the undefined nature of an airport (as listed in the airport editor) does not necessarily correlate to an error, or missing metar from that airport. 

There are a number of weather data products at work on this project. The Airport editor uses an API from weather.gov while the LED's uses XML data returned from https://www.aviationweather.gov/dataserver. For some reason, there are often inconsistencies between these 2 weather products that I can't explain.

So as long as you know that each airport you are using publishes a METAR your LED's should perform properly. This URL will list all the airports and will tell you if it reports a METAR or not;

 https://www.aviationweather.gov/docs/metar/stations.txt 

Mark


   
ReplyQuote
(@marty)
Member
Joined: 4 years ago
Posts: 0
Topic starter  

Hi Mark,

thanks for your fast reply. So the API URL used in both functions is just for the LEDs.

They both start with: www.aviationweather.gov

This is how it looks like on the webapp:

image

When I look up those airports directly on the aviationweather.gov, all of those UNDF ones reporting METARs

 

Thanks,

 

Daniel 

 


   
ReplyQuote
Mark Harris
(@markyharris)
Member Admin Registered
Joined: 5 years ago
Posts: 557
 

Yes, that's what has confounded me all this time.

Try this in your browser;

 https://api.weather.gov/stations/KPZZ/observations/latest 

Then try this;

 https://api.weather.gov/stations/KGHB/observations/latest 

I have no idea why there is a discrepancy. I've often wondered if I should remove the weather report from the airports editor for this very reason. BTW: The reason for using this api, is that I can use Jquery and Ajax to update the html on the page on the fly. 

Hope this helps explain it. - Mark


   
ReplyQuote
(@marty)
Member
Joined: 4 years ago
Posts: 0
Topic starter  

@markyharris Thanks for the links. I also have an issue when I click on map layout. 

I get this error, 

builtins.KeyError
KeyError: 'KXER'

Traceback (most recent call last)
File "/usr/lib/python3/dist-packages/flask/app.py", line 2309, in __call__
return self.wsgi_app(environ, start_response)
File "/usr/lib/python3/dist-packages/flask/app.py", line 2295, in wsgi_app
response = self.handle_exception(e)
File "/usr/lib/python3/dist-packages/flask/app.py", line 1741, in handle_exception
reraise(exc_type, exc_value, tb)
File "/usr/lib/python3/dist-packages/flask/_compat.py", line 35, in reraise
raise value
File "/usr/lib/python3/dist-packages/flask/app.py", line 2292, in wsgi_app
response = self.full_dispatch_request()
File "/usr/lib/python3/dist-packages/flask/app.py", line 1815, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/usr/lib/python3/dist-packages/flask/app.py", line 1718, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/usr/lib/python3/dist-packages/flask/_compat.py", line 35, in reraise
raise value
File "/usr/lib/python3/dist-packages/flask/app.py", line 1813, in full_dispatch_request
rv = self.dispatch_request()
File "/usr/lib/python3/dist-packages/flask/app.py", line 1799, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/NeoSectional/webapp.py", line 359, in led_map
+"</a><br>Pin&nbspNumber&nbsp=&nbsp"+str(pin_num)+"<br><b><font size=+2 color="+color+">"+led_map_dict[led_ap][2]+"</font></b>"
KeyError: 'KXER'
The debugger caught an exception in your WSGI application. You can now look at the traceback which led to the error.
To switch between the interactive traceback and the plaintext one, you can click on the "Traceback" headline. From the text traceback you can also create a paste of it. For code execution mouse-over the frame you want to debug and click on the console icon on the right side.

   
ReplyQuote
Mark Harris
(@markyharris)
Member Admin Registered
Joined: 5 years ago
Posts: 557
 

KXER is not a recognized airport ID. Could it be mis-spelled?

Try this search on FAA's lookup site; 

 https://nfdc.faa.gov/nfdcApps/services/ajv5/airportDisplay.jsp?airportId=KXER 

When you put a recognizable airport id in you won't get this error. - Mark


   
ReplyQuote
(@marty)
Member
Joined: 4 years ago
Posts: 0
Topic starter  

Hi Mark,

it's an offshore something, it reports the weather to aviationweather.gov and foreflight but maybe not to weather.gov 

Thanks for all the help with this. 

 

image
image

   
ReplyQuote
Mark Harris
(@markyharris)
Member Admin Registered
Joined: 5 years ago
Posts: 557
 

You are right. Here's the URL that the LED's use to display the proper flight category;

 https://www.aviationweather.gov/adds/dataserver_current/httpparam?dataSource=metars&requestType=retrieve&format=xml&mostRecentForEachStation=constraint&hoursBeforeNow=2.5&stationString=KXER 

And it does in fact show the METAR data for KXER. It's a shame that all the weather products could not be synced up. - Mark


   
ReplyQuote
Share: