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
|