""" forecaster.py This script is designed to run at a regular interval, polling various feeds from the National Weather Service and updating Django models WeatherCondition, WeatherAlert, and WeatherForecast in the Almanac application. WeatherUnderground RSS Structure: feed entries 0 - current weather conditions summary_detail value - String of Temp, Hum, Pres, Cond, WindDir, WindSpd, CondImg """ from datetime import datetime, timedelta from dateutil.parser import * import urllib import feedparser import elementtree.ElementTree as ET import time from almanac.models import WeatherConditions, WeatherAlert, WeatherForecast from directory.models import Town ALERT_ZONES = { "Coastal_Hancock_County": "MEZ029", } LOCATIONS = { "04624": "Blue Hill", "04627": "Stonington", } weather_url = "http://rss.wunderground.com/auto/rss_full/ME/%s.xml?units=english" alerts_url = "http://www.weather.gov/alerts-beta/wwaatmget.php?x=%s" def coords_for_zipcode(zipcode, client): coords = ET.fromstring(client.service.LatLonListZipCode(zipcode)) coords = coords[0].text.split(",") return coords def update_conditions(): """ function process_conditions input: ElementTree object of weather conditions result: Look up new weather condition and save it to the db """ for location in LOCATIONS: feed = feedparser.parse(weather_url % location) args = {} args["observation_time"] = parse(feed.feed.updated, ignoretz=True) args["town"] = Town.objects.get(name=LOCATIONS.get(location)) # First, we update the current conditions, assuming we have an update try: WeatherConditions.objects.get( observation_time__exact=args["observation_time"], town__exact=args["town"], ) print "Passing condition updates for %s..." % args["town"] pass except: print "Going ahead with condition updates for %s..." % args["town"] feed_cond = feed.entries[0].summary.split(" |") try: args["temperature"] = float(feed_cond[0].split(": ")[1][0:4]) except: args["temperature"] = float(feed_cond[0].split(": ")[1][0:3]) args["humidity"] = feed_cond[1].split(": ")[1] args["pressure"] = feed_cond[2].split(": ")[1].replace(" ", "") args["conditions"] = feed_cond[3].split(": ")[1] args["wind_dir"] = feed_cond[4].split(": ")[1] args["wind_speed"] = float(feed_cond[5].split(": ")[1].split("mph")[0]) condition = WeatherConditions.objects.create(**args) condition.save() # Now we try to get forecast updates which are everything after the current conditions: for entry in feed.entries[1:]: forecast_data = entry.summary.split(" - ") args = {} args["observation_time"] = parse(feed.feed.updated, ignoretz=True) print LOCATIONS.get(location) args["town"] = Town.objects.get(name=LOCATIONS.get(location)) args["period"] = forecast_data[0] try: WeatherForecast.objects.get( observation_time__exact=args["observation_time"], period=args["period"], town__exact=args["town"], ) print "Passing forecast update for %s..." % args["town"] pass except: print "Going ahead with forecasts for %s" % args["town"] try: args["conditions"] = forecast_data[1] forecast = WeatherForecast.objects.create(**args) forecast.save() except: print "Oops, no forecast data" pass update_conditions() def process_alerts(alerts, zone): root = alerts.getroot() if ( root[6][3].text.strip(" ").strip("\n ") == "There are no active watches, warnings or advisories" ): pass else: # We have a alert, so lets process updated = parse(root[6][1].text) zone_id = ALERT_ZONES[zone] zone = zone.replace("_", " ") summary = root[6][5].text.strip("\n") effective = parse(root[6][6].text) expires = parse(root[6][7].text) status = root[6][8].text.strip("\n") msg_type = root[6][9].text.strip("\n") urgency = root[6][11].text.strip("\n") severity = root[6][12].text.strip("\n") certainty = root[6][13].text.strip("\n") area = root[6][14].text.strip("\n") try: WeatherAlert.objects.get(summary__exact=summary) pass except: alert = WeatherAlert.objects.create( updated=updated, zone_id=zone_id, zone=zone, summary=summary, effective=effective, expires=expires, status=status, msg_type=msg_type, urgency=urgency, severity=severity, certainty=certainty, area=area, ) alert.save() # Add alerts for given state # for zone in ALERT_ZONES: # alerts=ET.parse(urllib.urlopen(alerts_url % ALERT_ZONES[zone])) # process_alerts(alerts, zone) # Update current forecasts """for loc in LOCATIONS: now=datetime.now() nowString=datetime.strftime(now,"%Y-%m-%dT%H:%M") laterString=datetime.strftime(now + timedelta(days=7),"%Y-%m-%dT%H:%M") coords=coords_for_zipcode(LOCATIONS[loc], NOAA) forecast=ET.parse(NOAA.service.NDFDgen(coords[0], coords[1], 'time-series', nowString, laterString, (1,1,1,1,1,1,1,1,1,1,1,1))) print forecast[0]""" # url = f_url % (lat, lon) # doc = ET.fromstring(urllib.urlopen(url)) # forecasts=[] # for node in dom.getElementsByTagNameNS