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{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeOperators #-}
module System.Smartmon.Parser
( getSmartInfo
, parseFile
, parseSmart
, mkSmartInfo
, smPowOnTime
, smDriveModel
, smRotRate
, smDrvSerial
, SmartInfo(..)
, SmartValue(..)
) where
import System.Smartmon.Datatypes
import Control.Lens
import Data.Aeson (Value (..), decode)
import Data.Aeson.AutoType.Alternative
import qualified Data.ByteString.Lazy.Char8 as BSL
import qualified Data.Text as T (Text)
data SmartInfo = SmartInfo
{ _smPowOnTime :: SmartValue Int,
_smDriveModel :: SmartValue T.Text,
_smRotRate :: SmartValue Int,
_smDrvSerial :: SmartValue T.Text
} deriving (Eq)
data SmartValue a = Unknown
| DecodeError
| SmartValue a
deriving (Eq)
instance (Ord a,Num a) => Num (SmartValue a) where
(+) (SmartValue x) (SmartValue y) = SmartValue $ x + y
(+) _ _ = Unknown
(*) (SmartValue x) (SmartValue y) = SmartValue $ x * y
(*) _ _ = Unknown
(-) (SmartValue x) (SmartValue y) = SmartValue $ x - y
(-) _ _ = Unknown
abs (SmartValue x) = SmartValue $ abs x
abs _ = Unknown
fromInteger = SmartValue . fromInteger
signum (SmartValue x)
| x < 0 = SmartValue (-1)
| x == 0 = SmartValue 0
| otherwise = SmartValue 1
signum _ = Unknown
makeLenses ''SmartInfo
mkSmartInfo :: SmartInfo
mkSmartInfo = SmartInfo Unknown Unknown Unknown Unknown
fetchBy :: (a -> b) -> Maybe (a :|: [Maybe Value]) -> SmartValue b
fetchBy _ Nothing = Unknown
fetchBy f (Just (AltLeft x)) = SmartValue $ f x
fetchBy _ (Just (AltRight _)) = DecodeError
getSmartInfo :: Smart -> SmartInfo
getSmartInfo sd = SmartInfo {
_smPowOnTime = fetchBy (round . powerOnTimeHours) . topLevelPowerOnTime $ sd,
_smDriveModel = fetchBy id . topLevelModelName $ sd,
_smRotRate = fetchBy round . topLevelRotationRate $ sd,
_smDrvSerial = fetchBy id . topLevelSerialNumber $ sd
}
parseSmart :: BSL.ByteString -> Maybe Smart
parseSmart = decode
parseFile :: FilePath -> IO (Maybe Smart)
parseFile filename = BSL.readFile filename >>= return . parseSmart
{-
main โท IO ()
main = do
filenames <- getArgs
forM_ filenames (\f -> parse f >>= (\p -> p `seq` putStrLn $ "Successfully parsed " ++ f))
exitSuccess
-}