Displays the current METAR aviation weather information for the airport of your choice
#!/usr/bin/env ruby
# <xbar.title>Metar</xbar.title>
# <xbar.version>v1.0</xbar.version>
# <xbar.author>Michael Heijmans</xbar.author>
# <xbar.author.github>parabuzzle</xbar.author.github>
# <xbar.desc>Displays the current METAR aviation weather information for the airport of your choice</xbar.desc>
# <xbar.image>http://github.com/parabuzzle/bitbar_metar/raw/master/metar-ifr.png</xbar.image>
# <xbar.dependencies>ruby</xbar.dependencies>
# <xbar.abouturl>http://www.github.com/parabuzzle/bitbar_metar</xbar.abouturl>
# Handle RVM Machines
unless ENV['USING_RVM']
# Re-run this script with RVM's default Ruby, after setting up the RVM path,
# and setting USING_RVM to true, so that this sentry code won't run the second
# time through.
system(
<<-EOF
export USING_RVM=true
export PATH="~/.rvm/bin:$PATH"
rvm-auto-ruby #{File.expand_path(__FILE__)}
EOF
)
# Return the exit code from running the script with RVM:
exit $?.exitstatus.to_i
end
require 'bitbar'
require 'Base64'
require 'metar'
require 'inifile'
def flight_rules
c = ceiling
v = meters_to_miles(visibility)
return "LIFR" if c <= 500 || v <= 1
return "IFR" if c <= 1000 || v < 3
return "MVFR" if c <= 3000 || v < 5
return "VFR"
end
def ceiling
conditions = PARSED_METAR.sky_conditions
c = 300000
conditions.each do |condition|
if ["broken", "overcast"].include? condition.quantity
f = meters_to_feet(condition.height.value).to_i
c = f if f < c
end
end
return c
end
def airport_code
config = IniFile.load(ENV['HOME'] + '/.bitbarrc')['metar']
config['airport'].upcase
end
def visibility
PARSED_METAR.visibility.distance.value.to_i
end
def meters_to_feet(num)
num * 3.28084
end
def meters_to_miles(num)
(num * 0.000621371).round(1)
end
def celius_to_fahrenheit(num)
((num * 1.8) + 32).round(1)
end
def format_number(num)
num.to_s.reverse.gsub(/(\d{3})(?=\d)/, '\\1,').reverse
end
def color(fr)
case fr
when "LIFR"
return "#ff00ff"
when "IFR"
return :red
when "MVFR"
return :blue
else
return :green
end
end
def temperature
PARSED_METAR.temperature_and_dew_point.temperature.value.to_i if PARSED_METAR.temperature_and_dew_point.temperature
end
def dew_point
PARSED_METAR.temperature_and_dew_point.dew_point.value.to_i if PARSED_METAR.temperature_and_dew_point.dew_point
end
# String generation methods
def wind_gust_string
wind = PARSED_METAR.wind
" (Gusting at #{wind.gusts.value.round * 2})" if wind.gusts
end
def wind_string
wind = PARSED_METAR.wind
return unless wind
if wind.direction == :variable_direction
direction = "Wind: Variable Direction @ #{parsed.wind.speed.value.round * 2} Knots"
else
direction = "Wind #{wind.direction.value.round}° @ #{wind.speed.value.round * 2} Knots"
end
return "#{direction}#{wind_gust_string}"
end
def metar_issued_at_string
"Metar Issued: #{PARSED_METAR.time.localtime.strftime('%m/%d/%Y %I:%M %p')}"
end
def visibility_string
"Visibility #{meters_to_miles(visibility)} sm" if visibility
end
def temp_string
"Temp: #{celius_to_fahrenheit(temperature)}° F" if temperature
end
def dew_point_string
"Dew Point: #{celius_to_fahrenheit(dew_point)}° F" if dew_point
end
# setup variables
PARSED_METAR = Metar::Station.find_by_cccc(airport_code).parser
flight_rule = flight_rules
# Make the menu
BitBar::Menu.new do
item flight_rule, color: color(flight_rule)
item airport_code, color: color(flight_rule)
separator
item metar_issued_at_string, color: :black
item visibility_string, color: :black
item temp_string, color: :black
item dew_point_string, color: :black
item wind_string, color: :black
item "Sky Conditions" do
PARSED_METAR.sky_conditions.each do |condition|
if condition.height
item "#{condition.quantity} - #{format_number(meters_to_feet(condition.height.value).to_i)} ft", color: :black
else
item "Sky Clear", color: :blue
end
end
end
separator
end