----------------------------------------------------------------------------- -- | -- Module : Monitors.Weather -- Copyright : (c) Andrea Rossato -- License : BSD-style (see LICENSE) -- -- Maintainer : Andrea Rossato -- Stability : unstable -- Portability : unportable -- -- A weather monitor for XMobar -- ----------------------------------------------------------------------------- module Main where import Monitors.Common import Data.IORef import System.Process import System.Exit import System.IO import Text.ParserCombinators.Parsec monitorConfig :: IO MConfig monitorConfig = do lc <- newIORef "#BFBFBF" l <- newIORef 15 nc <- newIORef "#00FF00" h <- newIORef 27 hc <- newIORef "#FF0000" t <- newIORef ": C, rh % ()" p <- newIORef package u <- newIORef "station ID" a <- newIORef [] e <- newIORef ["station" , "stationState" , "year" , "month" , "day" , "hour" , "wind" , "visibility" , "skyCondition" , "tempC" , "tempF" , "dewPoint" , "rh" ,"pressure" ] return $ MC nc l lc h hc t p u a e data WeatherInfo = WI { stationPlace :: String , stationState :: String , year :: String , month :: String , day :: String , hour :: String , wind :: String , visibility :: String , skyCondition :: String , temperature :: Float , dewPoint :: String , humidity :: Float , pressure :: String } deriving (Show) pTime :: Parser (String, String, String, String) pTime = do y <- getNumbersAsString char '.' m <- getNumbersAsString char '.' d <- getNumbersAsString char ' ' (h:hh:mi:mimi) <- getNumbersAsString char ' ' return (y, m, d ,([h]++[hh]++":"++[mi]++mimi)) pTemp :: Parser Float pTemp = do string ": " manyTill anyChar $ char '(' s <- manyTill digit $ (char ' ' <|> char '.') skipRestOfLine return $read s pRh :: Parser Float pRh = do string ": " s <- manyTill digit $ (char '%' <|> char '.') return $ read s parseData :: Parser [WeatherInfo] parseData = do st <- getAllBut "," space ss <- getAllBut "(" skipRestOfLine >> getAllBut "/" (y,m,d,h) <- pTime skipRestOfLine >> string "Wind: " w <- manyTill anyChar $ newline manyTill skipRestOfLine $ string "Visibility: " v <- manyTill anyChar $ newline manyTill skipRestOfLine $ string "Sky conditions: " sk <- manyTill anyChar $ newline manyTill skipRestOfLine $ string "Temperature" temp <- pTemp manyTill skipRestOfLine $ string "Dew Point: " dp <- manyTill anyChar $ newline manyTill skipRestOfLine $ string "Relative Humidity" rh <- pRh manyTill skipRestOfLine $ string "Pressure (altimeter): " p <- manyTill anyChar $ newline manyTill skipRestOfLine eof return $ [WI st ss y m d h w v sk temp dp rh p] defUrl :: String defUrl = "http://weather.noaa.gov/pub/data/observations/metar/decoded/" getData :: String -> IO String getData url= do (i,o,e,p) <- runInteractiveCommand ("curl " ++ defUrl ++ url ++ ".TXT") exit <- waitForProcess p let closeHandles = do hClose o hClose i hClose e case exit of ExitSuccess -> do str <- hGetContents o return str _ -> do closeHandles return "Could not retrieve data" formatWeather :: [WeatherInfo] -> Monitor String formatWeather [(WI st ss y m d h w v sk temp dp r p)] = do cel <- showWithColors show temp far <- showWithColors (show . takeDigits 1) (((9 / 5) * temp) + 32) rh <- showWithColors show r parseTemplate [st, ss, y, m, d, h, w, v, sk, cel, far, dp, rh , p ] formatWeather _ = return "N/A" runWeather :: [String] -> Monitor String runWeather str = do d <- io $ getData $ head str i <- io $ runP parseData d formatWeather i package :: String package = "xmb-weather" main :: IO () main = do let af = return "No station ID specified" runMonitor monitorConfig af runWeather