summaryrefslogtreecommitdiffhomepage
path: root/Plugins/Monitors/Weather.hs
blob: ec5606e447a440b5cdfa02969d678daac5ca5e0e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
-----------------------------------------------------------------------------
-- |
-- Module      :  Plugins.Monitors.Weather
-- Copyright   :  (c) Andrea Rossato
-- License     :  BSD-style (see LICENSE)
-- 
-- Maintainer  :  Andrea Rossato <andrea.rossato@unibz.it>
-- Stability   :  unstable
-- Portability :  unportable
--
-- A weather monitor for Xmobar
--
-----------------------------------------------------------------------------

module Plugins.Monitors.Weather where

import Plugins.Monitors.Common

import System.Process
import System.Exit
import System.IO

import Text.ParserCombinators.Parsec


weatherConfig :: IO MConfig
weatherConfig = mkMConfig
       "<station>: <tempC>C, rh <rh>% (<hour>)" -- template
       ["station"                               -- available replacements
       , "stationState"
       , "year"
       , "month"
       , "day"
       , "hour"
       , "wind"
       , "visibility"
       , "skyCondition"
       , "tempC"
       , "tempF"
       , "dewPoint"
       , "rh"
       ,"pressure"
       ]

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 manyTill anyChar $ char '('
           s <- manyTill digit $ (char ' ' <|> char '.')
           skipRestOfLine
           return $read s

pRh :: Parser Float
pRh = do 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
       w <- getAfterString "Wind: "
       v <- getAfterString "Visibility: "
       sk <- getAfterString "Sky conditions: "
       skipTillString "Temperature: "
       temp <- pTemp
       dp <- getAfterString "Dew Point: "
       skipTillString "Relative Humidity: "
       rh <- pRh
       p <- getAfterString "Pressure (altimeter): "
       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