123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- """
- 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
|