module EIBd.Client.Groups (
GroupCache,
GroupM,
execGroupM,
tryGroupM,
tryGroupM_,
putGroup,
getGroup,
clearGroups,
uncacheGroup,
) where
import Control.Monad
import Control.Monad.State.Strict
import Control.Monad.Trans.Maybe
import Control.Applicative
import qualified Data.ByteString as B
import qualified Data.Map.Strict as M
import EIBd.Client.Types
import EIBd.Client.Address
import EIBd.Client.Connection
type GroupCache = M.Map GroupAddress B.ByteString
type GroupM = MaybeT (StateT GroupCache IO)
execGroupM :: GroupM a -> Connection -> GroupCache -> IO GroupCache
execGroupM handler conn cache = do
newCache <- execStateT (runMaybeT handler) cache
M.foldlWithKey' updateGroup (return True) (toBeUpdated newCache)
return newCache
where
toBeUpdated newCache = M.differenceWith (const . Just) newCache cache
updateGroup prev dst val = do
prev
sendMessage conn dst 0 GroupAddrWrite val
tryGroupM :: a -> GroupM a -> GroupM a
tryGroupM a ch = ch <|> return a
tryGroupM_ :: GroupM a -> GroupM ()
tryGroupM_ = tryGroupM () . void
putGroup :: DatapointType a => GroupAddress -> a -> GroupM ()
putGroup dst val = lift (modify (M.insert dst (fromDPT val)))
getGroup :: DatapointType a => GroupAddress -> GroupM a
getGroup adr = MaybeT (gets (\m -> M.lookup adr m >>= toDPT))
clearGroups :: GroupM ()
clearGroups = lift (put M.empty)
uncacheGroup :: GroupAddress -> GroupM ()
uncacheGroup = lift . modify . M.delete