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
130
131
132
133
134
135
136
137
138
139
140
141
142
|
-----------------------------------------------------------------------------
-- |
-- Module : Monitors.Cpu
-- Copyright : (c) Andrea Rossato
-- License : BSD-style (see LICENSE)
--
-- Maintainer : Andrea Rossato <andrea.rossato@unibz.it>
-- Stability : unstable
-- Portability : unportable
--
-- A net device monitor for XMobar
--
-----------------------------------------------------------------------------
module Main where
import Numeric
import Control.Concurrent
import Text.ParserCombinators.Parsec
import System.Environment
data Config =
Config { intervall :: Int
, netDevice :: String
, netNormal :: Integer
, netNormalColor :: String
, netCritical :: Integer
, netCriticalColor :: String
}
defaultConfig :: Config
defaultConfig =
Config { intervall = 500000
, netDevice = "eth1"
, netNormal = 0
, netNormalColor = "#00FF00"
, netCritical = 50
, netCriticalColor = "#FF0000"
}
config :: Config
config = defaultConfig
-- Utilities
interSec :: IO ()
interSec = threadDelay (intervall config)
takeDigits :: Int -> Float -> Float
takeDigits d n =
read $ showFFloat (Just d) n ""
floatToPercent :: Float -> String
floatToPercent n =
showFFloat (Just 2) (n*100) "%"
run :: Parser [a] -> IO String -> IO [a]
run p input
= do a <- input
case (parse p "" a) of
Left _ -> return []
Right x -> return x
fileNET :: IO String
fileNET =
do f <- readFile "/proc/net/dev"
return $ unlines $ drop 2 $ lines f
-- CPU
getNumbers :: Parser Float
getNumbers = skipMany space >> many1 digit >>= \n -> return $ read n
-- Net Devices
data NetDev = NA
| ND { netDev :: String
, netRx :: Float
, netTx :: Float
} deriving (Eq,Read)
instance Show NetDev where
show NA = "N/A"
show (ND nd rx tx) =
nd ++ ": " ++ (formatNet rx) ++ "|" ++ formatNet tx
formatNet :: Float -> String
formatNet d | d > fromInteger (netCritical config) = setColor str netCriticalColor
| d > fromInteger (netNormal config) = setColor str netNormalColor
| otherwise = str
where str = show d ++ "Kb"
pNetDev :: Parser NetDev
pNetDev =
do { skipMany1 space
; dn <- manyTill alphaNum $ char ':'
; [rx] <- count 1 getNumbers
; _ <- count 7 getNumbers
; [tx] <- count 1 getNumbers
; _ <- count 7 getNumbers
; char '\n'
; return $ ND dn (rx / 1024) (tx / 1024)
}
parserNet :: Parser [NetDev]
parserNet = manyTill pNetDev eof
parseNET :: String -> IO [NetDev]
parseNET nd =
do a <- run parserNet fileNET
interSec
b <- run parserNet fileNET
let netRate f da db = takeDigits 2 $ ((f db) - (f da)) * fromIntegral (1000000 `div` (intervall config))
diffRate (da,db) = ND (netDev da)
(netRate netRx da db)
(netRate netTx da db)
return $ filter (\d -> netDev d == nd) $ map diffRate $ zip a b
-- Formattings
setColor :: String -> (Config -> String) -> String
setColor str ty =
"<fc=" ++ ty config ++ ">" ++
str ++ "</fc>"
net :: String -> IO String
net nd =
do pn <- parseNET nd
n <- case pn of
[x] -> return x
_ -> return $ NA
return $ show n
main :: IO ()
main =
do args <- getArgs
n <-
if length args /= 1
then error "No device specified.\nUsage: net dev"
else net (args!!0)
putStrLn n
|