module Data.Aviation.Stratux.Websockets(
WSConnectionIO
, decodeWith
, decode
, decode'
, stratuxApp
, trafficAppWith
, trafficApp
, trafficApp'
) where
import Control.Category(Category((.)))
import Data.Aeson(FromJSON)
import qualified Data.Aeson as A(eitherDecode, eitherDecode')
import Control.Concurrent(forkIO)
import Control.Monad(Monad((>>=), (>>)), forever, unless)
import Control.Monad.Trans.Either(EitherT(EitherT))
import Control.Monad.Trans.Reader(ReaderT(ReaderT))
import Data.Aviation.Stratux.Types(Traffic)
import Data.Either(Either)
import Data.Function(($))
import Data.Functor(Functor(fmap))
import Data.Int(Int)
import Data.String(String)
import qualified Data.Text as T(null)
import qualified Data.Text.IO as T(getLine)
import Network.Socket (withSocketsDo)
import qualified Network.WebSockets as WS(Connection, WebSocketsData, ClientApp, receiveData, sendClose, sendTextData, runClient)
import System.IO(IO)
type WSConnectionIO f a =
ReaderT WS.Connection (f IO) a
decodeWith ::
WS.WebSocketsData a =>
(a -> b)
-> (IO b -> m c)
-> ReaderT WS.Connection m c
decodeWith d k =
ReaderT (k . fmap d . WS.receiveData)
decode ::
FromJSON a =>
WSConnectionIO (EitherT String) a
decode =
decodeWith A.eitherDecode EitherT
decode' ::
FromJSON a =>
WSConnectionIO (EitherT String) a
decode' =
decodeWith A.eitherDecode' EitherT
stratuxApp ::
(WS.WebSocketsData t, WS.WebSocketsData u) =>
(t -> IO b)
-> u
-> WS.ClientApp ()
stratuxApp k s c = do
_ <- forkIO . forever $ WS.receiveData c >>= k
let loop = do line <- T.getLine
unless (T.null line) $ WS.sendTextData c line >> loop
loop
WS.sendClose c s
trafficAppWith ::
(WS.WebSocketsData t, WS.WebSocketsData u) =>
(t -> Either String Traffic)
-> String
-> Int
-> (Either String Traffic -> IO b)
-> u
-> IO ()
trafficAppWith q host port k s =
withSocketsDo $ WS.runClient host port "/traffic" (stratuxApp (k . q) s)
trafficApp ::
WS.WebSocketsData u =>
String
-> Int
-> (Either String Traffic -> IO b)
-> u
-> IO ()
trafficApp =
trafficAppWith A.eitherDecode
trafficApp' ::
WS.WebSocketsData u =>
String
-> Int
-> (Either String Traffic -> IO b)
-> u
-> IO ()
trafficApp' =
trafficAppWith A.eitherDecode'