Metar Weather Grabber


#1

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)


#2

Chris W. wrote:

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.

Hi Chris,
is there something wrong with the decoded data?


require ‘open-uri’

url = ‘ftp://weather.noaa.gov/data/observations/metar/decoded/KLGA.TXT
open(url) do |f|
weather = f.read.to_a.map {|line| line.strip.split(’:’)}
label = weather.shift.first.split(’,’).first
date = weather.shift.first
puts %Q[]
weather.each do |w|
key = w.first.tr(’()’, ’ ‘).delete(’ ')
puts %Q[ <#{key}>#{w[1].strip}</#{key}>]
end
puts ‘’
end

output:


from the NW (320 degrees) at 9 MPH (8 KT)
10 mile(s)
partly cloudy
75.0 F (23.9 C)
35.1 F (1.7 C)
23%

cheers

Simon


#3

Nope.

I guess I just wanted to learn how to use regular expressions. I wish I
would have found those a couple of hours ago.

Thanks for the post, that will help a lot.

Simon Kröger wrote:

Chris W. wrote:

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.

Hi Chris,
is there something wrong with the decoded data?


require ‘open-uri’

url = ‘ftp://weather.noaa.gov/data/observations/metar/decoded/KLGA.TXT
open(url) do |f|
weather = f.read.to_a.map {|line| line.strip.split(’:’)}
label = weather.shift.first.split(’,’).first
date = weather.shift.first
puts %Q[]
weather.each do |w|
key = w.first.tr(’()’, ’ ‘).delete(’ ')
puts %Q[ <#{key}>#{w[1].strip}</#{key}>]
end
puts ‘’
end

output:


from the NW (320 degrees) at 9 MPH (8 KT)
10 mile(s)
partly cloudy
75.0 F (23.9 C)
35.1 F (1.7 C)
23%

cheers

Simon