I don’t want to pay money to get weather feeds from a bunch of different
countries. So I took my hand at writing my own. It is for an ajax
service that grabs the XML.
If you use this, expand on it. If you expand on it, post it back on
here. There are somethings I haven’t gotten to yet. The usage of the
weather codes needs to get better too.
#!/usr/bin/ruby
require ‘rexml/document’
require ‘open-uri’
require ‘pp’
include REXML
class Weather
attr_reader :wind, :temperature, :dew_point, :sky, :sky_icon
def initialize(metar_string)
@metar_string = metar_string
@wind = self.set_wind()
@temperature, @dew_point = self.set_temperature()
@sky, @sky_icon = self.set_sky()
end
def set_wind
sample_string = $& if @metar_string =~
/(\d{3}|VRB)[G]{0,1}\d{1,4}KT/
direction = self.get_cardinal_direction(sample_string[0...3])
speed =
sample_string[sample_string.rindex(/\d{1,4}KT/)…sample_string.length-3].to_i
"#{direction} at #{speed}mph"
end
def get_cardinal_direction(degrees)
case degrees.to_i
when 0: “Variable”
when 1…4: “N”
when 5…35: “NNE”
when 36…55: “NE”
when 56…85: “ENE”
when 86…95: “E”
when 96…125: “ESE”
when 126…135: “SE”
when 136…175: “SSE”
when 176…185: “S”
when 185…215: “SSW”
when 216…225: “W”
when 226…265: “WSW”
when 265…275: “W”
when 275…295: “WNW”
when 296…305: “NW”
when 306…346: “NNW”
when 347…370: “N”
else “Gusty”
end
end
def set_temperature
sample_string = $&.strip if @metar_string =~ /
[M]{0,1}\d{2}/[M]{0,1}\d{2} /
celcius = sample_string[0..2].to_i
fahrenheit = ( ( celcius.to_i * 9 ) / 5 + 32 )
dew_point_celcius =
sample_string[3…sample_string.length-1].to_i
dew_point_fahrenheit = ( ( dew_point_celcius * 9 ) / 5 + 32)
["#{fahrenheit} F (#{celcius} C)", "#{dew_point_fahrenheit} F
(#{dew_point_celcius} C)"]
end
def set_sky
sky = $&.strip if @metar_string =~
/(SKC|FEW|SCT|BKN|OVC|CLR)[CB]{0,1}/
sky = $&.strip if @metar_string =~
/(RA|DZ|SN|GR|SQ|GS|SG|IC|PE|BR|FG|FU|HZ|VA|DU|SA|SS|DS|FC|MI|BC|DR|BL|SH|TS|FZ)+{1}/
weather_codes = { "SKC"=> ["Scattered Clouds", 30],
"FEW"=> ["Sunny" , 32],
"SCT"=> ["Partly Cloudy" , 29],
"BKN"=> ["Mostly Cloudy" , 28],
"OVC"=> ["Overcast" , 26],
"CLR"=> ["Sunny" , 32],
"RA"=> ["Raining" , 40],
"DZ"=> ["Drizzle" , 39],
"SN"=> ["Snow" , 16],
"GR"=> ["Hail" , 35],
"SQ"=> ["Squalls" , nil],
"GS"=> ["Small Hail" , 35],
"SG"=> ["Snow Grains" , 15],
"IC"=> ["Diamond Dust" , nil],
"PE"=> ["Ice Pellets" , nil],
"BR"=> ["Mist" , nil],
"FG"=> ["Fog" , 20],
"FU"=> ["Smoke" , 22],
"HZ"=> ["Haze" , 21],
"VA"=> ["Volcanic Ash" , nil],
"DU"=> ["Widespead dust" , nil],
"SA"=> ["Sand" , nil],
"SS"=> ["Sandstorm" , nil],
"DS"=> ["Duststorm" , nil],
"FC"=> ["Funnel Cloud" , nil],
"MI"=> ["Shallow" , nil],
"BC"=> ["Patches" , nil],
"DR"=> ["Drifting" , nil],
"BL"=> ["Blowing" , nil],
"SH"=> ["Showers" , nil],
"TS"=> ["Thunderstorm" , 1],
"FZ"=> ["Supercooled(Freezing)", nil],
"+" => ["Heavy" , nil],
"TCU"=> ["Towering Cumulonimbs", nil]
}
icon = ''
weather_codes.each do | code, description |
sky = sky.gsub(code, description[0])
icon = description[1] if !description[1].nil?
end
[sky, icon]
end
end
Set up the XML document
xml_write = REXML::Document.new(’’)
xml_write.elements["//method"].text = “updateWeather”
#Array of Cities and Local from the Weather xml information
cities_url = {“New York, NY” =>
“ftp://weather.noaa.gov/data/observations/metar/stations/KLGA.TXT”,
“London, UK” =>
“ftp://weather.noaa.gov/data/observations/metar/stations/EGLL.TXT”}
cities_url.each do |location, url|
current_weather = Element.new()
current_weather.add_element(“CurrentWeather”)
current_weather.elements["//CurrentWeather"].add_attribute(“label”,
location)
element_write =
current_weather.elements["//CurrentWeather[@label=’"+location+"’]"]
metar = Document.new(open(url))
weather = Weather.new(metar.to_s.gsub("\n", " "))
element_write.add_element(“DewPoint”).text =
weather.dew_point
element_write.add_element(“Temperature”).text =
weather.temperature
element_write.add_element(“Wind”).text = weather.wind
element_write.add_element(“SkyConditions”).text = weather.sky
element_write.add_element(“SkyConditionsIcon”).text = weather.sky_icon
element_write.add_element(“RelativeHumidity”).text = metar[0]
xml_write.elements["//result"].add_element(current_weather.elements["//CurrentWeather"])
end
xml_writable = File.new(“public_html/weather.xml”, “w+”)
xml_write.write(xml_writable, -1, true)