module Network.MQTT
(
run
, Terminated(..)
, disconnect
, Config
, defaultConfig
, Commands
, mkCommands
, cHost
, cPort
, cClean
, cWill
, cUsername
, cPassword
, cKeepAlive
, cClientID
, cLogDebug
, cPublished
, cCommands
, cInputBufferSize
, subscribe
, unsubscribe
, publish
, module Network.MQTT.Types
) where
import Control.Applicative ((<$>))
import Control.Concurrent
import Control.Concurrent.STM
import Control.Exception (finally)
import Control.Monad (void)
import Data.ByteString (ByteString)
import Data.Maybe (fromJust)
import Data.Unique
import Network
import System.IO (hSetBinaryMode)
import Network.MQTT.Internal
import Network.MQTT.Types
defaultConfig :: Commands -> TChan (Message 'PUBLISH) -> Config
defaultConfig commands published = Config
{ cHost = "localhost"
, cPort = 1883
, cClean = True
, cWill = Nothing
, cUsername = Nothing
, cPassword = Nothing
, cKeepAlive = Nothing
, cClientID = "mqtt-haskell"
, cResendTimeout = 20
, cLogDebug = const $ return ()
, cCommands = commands
, cPublished = published
, cInputBufferSize = 0x1000
}
run :: Config -> IO Terminated
run conf = do
h <- connectTo (cHost conf) (PortNumber $ cPort conf)
hSetBinaryMode h True
terminatedVar <- newEmptyTMVarIO
sendSignal <- newEmptyMVar
mainLoop conf h (readTMVar terminatedVar) sendSignal
`finally` atomically (putTMVar terminatedVar ())
disconnect :: Config -> IO ()
disconnect mqtt = writeCmd mqtt CmdDisconnect
subscribe :: Config -> [(Topic, QoS)] -> IO [QoS]
subscribe mqtt topics = do
msgID <- fromIntegral . hashUnique <$> newUnique
msg <- sendAwait mqtt
(Message
(Header False Confirm False)
(Subscribe msgID topics))
SSUBACK
return $ granted $ body $ msg
unsubscribe :: Config -> [Topic] -> IO ()
unsubscribe mqtt topics = do
msgID <- fromIntegral . hashUnique <$> newUnique
void $ sendAwait mqtt
(Message (Header False Confirm False) (Unsubscribe msgID topics))
SUNSUBACK
publish :: Config -> QoS -> Bool -> Topic -> ByteString -> IO ()
publish mqtt qos retain topic body = do
msgID <- if qos > NoConfirm
then Just . fromIntegral . hashUnique <$> newUnique
else return Nothing
let pub = Message (Header False qos retain) (Publish topic msgID body)
case qos of
NoConfirm -> send mqtt pub
Confirm -> void $ sendAwait mqtt pub SPUBACK
Handshake -> do
void $ sendAwait mqtt pub SPUBREC
void $ sendAwait mqtt
(Message (Header False Confirm False)
(PubRel (fromJust msgID)))
SPUBCOMP