-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMain.hs
150 lines (133 loc) · 5.43 KB
/
Main.hs
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
143
144
145
146
147
148
149
150
module Main (main) where
import System.Console.GetOpt (OptDescr(Option), ArgDescr(ReqArg, NoArg), usageInfo, getOpt, ArgOrder(RequireOrder))
import System.Environment (getProgName, getArgs)
import System.Exit (exitSuccess)
import Data.List (intercalate)
import Control.Concurrent (threadDelay, forkIO, putMVar, takeMVar, newEmptyMVar)
import Control.Monad (forever)
import System.Directory (renameFile)
import qualified Data.ByteString.Char8 as BS
import System.INotify (initINotify, addWatch, EventVariety(..))
import System.Timeout (timeout)
import Thermometer
import Zone
import Override
import Thermostat
import Routine
import Control
import qualified Data.Map as Map
import Data.Maybe
data Options = Options { optConfigDir :: String
, optRunDir :: String
, optLibDir :: String
, optArexxDir :: Maybe String
, optOwDir :: Maybe String
, optUdinDir :: Maybe String
, optFht8vDir :: Maybe String
, optDkrDir :: Maybe String
}
startOptions = Options { optConfigDir = "/etc/bhp"
, optRunDir = "/var/run/bhp"
, optLibDir = "/var/lib/bhp"
, optArexxDir = Nothing
, optOwDir = Nothing
, optUdinDir = Nothing
, optFht8vDir = Nothing
, optDkrDir = Nothing
}
options =
[ Option "c" ["config-dir"]
(ReqArg
(\arg opt -> return opt { optConfigDir = arg })
"DIRECTORY")
"configuration directory (default /etc/bhp)"
, Option "r" ["runtime-dir"]
(ReqArg
(\arg opt -> return opt { optRunDir = arg })
"DIRECTORY")
"directory for runtime state files (default /var/run/bhp)"
, Option "l" ["lib-dir"]
(ReqArg
(\arg opt -> return opt { optLibDir = arg })
"DIRECTORY")
"drirectory for persistent state files (default /var/lib/bhp)"
, Option "a" ["arexx-dir"]
(ReqArg
(\arg opt -> return opt { optArexxDir = Just arg })
"DIRECTORY")
"arexx temperature sensor mount point"
, Option "o" ["ow-dir"]
(ReqArg
(\arg opt -> return opt { optOwDir = Just arg })
"DIRECTORY")
"1wire temperature sensor mount point"
, Option "u" ["udin-dir"]
(ReqArg
(\arg opt -> return opt { optUdinDir = Just arg })
"DIRECTORY")
"udin switch mount point"
, Option "f" ["fht-dir"]
(ReqArg
(\arg opt -> return opt { optFht8vDir = Just arg })
"DIRECTORY")
"fht8v (CUL) device mount point"
, Option "d" ["denkovi-dir"]
(ReqArg
(\arg opt -> return opt { optDkrDir = Just arg })
"DIRECTORY")
"Denkovi DAEnetIP2 switch mount point"
, Option "h" ["help"]
(NoArg
(\_ -> do
prg <- getProgName
putStrLn (usageInfo prg options)
exitSuccess))
"Show help"
]
main = do
args <- getArgs
let (actions, nonOptions, errors) = getOpt RequireOrder options args
opts <- foldl (>>=) (return startOptions) actions
mvar <- newEmptyMVar
inotify <- initINotify
addWatch inotify [MoveIn] (optLibDir opts) $ \e -> putMVar mvar e
daemon opts mvar
where
daemon opts mvar = do
let Options { optConfigDir = configDir
, optLibDir = libDir
, optRunDir = runDir
, optArexxDir = arexxDir
, optOwDir = owDir
, optUdinDir = udinDir
, optFht8vDir = fht8vDir
, optDkrDir = dkrDir } = opts
putStrLn "(Re)loading configuration"
zones <- loadZones (configDir ++ "/zones.xml")
routines <- loadRoutines (configDir ++ "/routines.xml") zones
overrides <- loadOverrides (libDir ++ "/overrides.xml") zones
thermometers <- loadThermometers (configDir ++ "/thermometers.xml") owDir arexxDir
thermostats <- loadThermostats (configDir ++ "/thermostats.xml") routines overrides
controls <- loadControls (configDir ++ "/controls.xml") udinDir fht8vDir dkrDir
loop thermometers thermostats controls runDir
daemon opts mvar
where
loop thermometers thermostats controls runDir = do
thermometers' <- readThermometers thermometers
saveState runDir "temperatures.xml" $ getTemperatureXml thermometers'
thermostats' <- testThermostats thermometers' thermostats
saveState runDir "state.xml" $ getThermostatStateXml thermostats'
controls' <- evalControlConditions thermostats' controls
saveState runDir "control-state.xml" $ getControlStateXml controls'
actuateControls controls'
reload <- timeout (5*10^6) (takeMVar mvar)
case reload of
Nothing -> loop thermometers' thermostats' controls' runDir
otherwise -> return ()
-- write to a temporary file and rename into place
saveState :: FilePath -> FilePath -> String -> IO ()
saveState dir fnam s = do
BS.writeFile tnam (BS.pack s)
renameFile tnam (dir ++ ('/':fnam))
where
tnam = dir ++ "/.bhp.tmp"