module Lifx.Lan (
sendMessage,
Message (..),
HSBK (..),
Duration (..),
Lifx,
runLifx,
LifxT (..),
runLifxT,
LifxError (..),
MonadLifx (..),
LightState (..),
StatePower (..),
encodeMessage,
Header (..),
) where
import Control.Monad
import Control.Monad.Except
import Control.Monad.Reader
import Control.Monad.State hiding (get, put)
import Data.Binary
import Data.Binary.Get hiding (label)
import Data.Binary.Put
import Data.Bits
import Data.ByteString qualified as BS
import Data.ByteString.Lazy qualified as BL
import Data.Either.Extra
import Data.Function
import Data.Tuple.Extra
import GHC.Generics (Generic)
import GHC.IO.Exception
import Network.Socket
import Network.Socket.ByteString
import System.Random
import System.Timeout
lifxPort :: PortNumber
lifxPort :: PortNumber
lifxPort = PortNumber
56700
sendMessage :: MonadLifx m => HostAddress -> Message a -> m a
sendMessage :: HostAddress -> Message a -> m a
sendMessage HostAddress
lightAddr Message a
msg = do
Socket
sock <- m Socket
forall (m :: * -> *). MonadLifx m => m Socket
getSocket
HostAddress
source <- m HostAddress
forall (m :: * -> *). MonadLifx m => m HostAddress
getSource
Int
timeoutDuration <- m Int
forall (m :: * -> *). MonadLifx m => m Int
getTimeout
Word8
counter <- m Word8
forall (m :: * -> *). MonadLifx m => m Word8
getCounter
m ()
forall (m :: * -> *). MonadLifx m => m ()
incrementCounter
let receiver :: SockAddr
receiver = PortNumber -> HostAddress -> SockAddr
SockAddrInet PortNumber
lifxPort HostAddress
lightAddr
m Int -> m ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (m Int -> m ()) -> (IO Int -> m Int) -> IO Int -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO Int -> m Int
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Int -> m ()) -> IO Int -> m ()
forall a b. (a -> b) -> a -> b
$
Socket -> ByteString -> SockAddr -> IO Int
sendTo
Socket
sock
(ByteString -> ByteString
BL.toStrict (ByteString -> ByteString) -> ByteString -> ByteString
forall a b. (a -> b) -> a -> b
$ Bool -> Word8 -> HostAddress -> Message a -> ByteString
forall a. Bool -> Word8 -> HostAddress -> Message a -> ByteString
encodeMessage Bool
False Word8
counter HostAddress
source Message a
msg)
SockAddr
receiver
Message a -> Either a (Word16, Int, Get a)
forall a. Message a -> Either a (Word16, Int, Get a)
getResponse' Message a
msg Either a (Word16, Int, Get a)
-> (Either a (Word16, Int, Get a) -> m a) -> m a
forall a b. a -> (a -> b) -> b
& (a -> m a)
-> ((Word16, Int, Get a) -> m a)
-> Either a (Word16, Int, Get a)
-> m a
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure \(Word16
expectedPacketType, Int
messageSize, Get a
getBody) -> do
(ByteString
bs, SockAddr
sender) <-
m (Either LifxError (ByteString, SockAddr))
-> m (ByteString, SockAddr)
forall (m :: * -> *) b.
MonadLifx m =>
m (Either LifxError b) -> m b
throwEither (m (Either LifxError (ByteString, SockAddr))
-> m (ByteString, SockAddr))
-> (Int -> m (Either LifxError (ByteString, SockAddr)))
-> Int
-> m (ByteString, SockAddr)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO (Either LifxError (ByteString, SockAddr))
-> m (Either LifxError (ByteString, SockAddr))
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Either LifxError (ByteString, SockAddr))
-> m (Either LifxError (ByteString, SockAddr)))
-> (Int -> IO (Either LifxError (ByteString, SockAddr)))
-> Int
-> m (Either LifxError (ByteString, SockAddr))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Maybe (ByteString, SockAddr)
-> Either LifxError (ByteString, SockAddr))
-> IO (Maybe (ByteString, SockAddr))
-> IO (Either LifxError (ByteString, SockAddr))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (LifxError
-> Maybe (ByteString, SockAddr)
-> Either LifxError (ByteString, SockAddr)
forall a b. a -> Maybe b -> Either a b
maybeToEither LifxError
RecvTimeout)
(IO (Maybe (ByteString, SockAddr))
-> IO (Either LifxError (ByteString, SockAddr)))
-> (Int -> IO (Maybe (ByteString, SockAddr)))
-> Int
-> IO (Either LifxError (ByteString, SockAddr))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int
-> IO (ByteString, SockAddr) -> IO (Maybe (ByteString, SockAddr))
forall a. Int -> IO a -> IO (Maybe a)
timeout Int
timeoutDuration
(IO (ByteString, SockAddr) -> IO (Maybe (ByteString, SockAddr)))
-> (Int -> IO (ByteString, SockAddr))
-> Int
-> IO (Maybe (ByteString, SockAddr))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Socket -> Int -> IO (ByteString, SockAddr)
recvFrom Socket
sock
(Int -> m (ByteString, SockAddr))
-> Int -> m (ByteString, SockAddr)
forall a b. (a -> b) -> a -> b
$ Int
forall a. Num a => a
headerSize Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
messageSize
Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (SockAddr
sender SockAddr -> SockAddr -> Bool
forall a. Eq a => a -> a -> Bool
/= SockAddr
receiver) (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ LifxError -> m ()
forall (m :: * -> *) a. MonadLifx m => LifxError -> m a
lifxThrow (LifxError -> m ()) -> LifxError -> m ()
forall a b. (a -> b) -> a -> b
$ SockAddr -> SockAddr -> LifxError
WrongSender SockAddr
receiver SockAddr
sender
case Get Header
-> ByteString
-> Either
(ByteString, ByteOffset, String) (ByteString, ByteOffset, Header)
forall a.
Get a
-> ByteString
-> Either
(ByteString, ByteOffset, String) (ByteString, ByteOffset, a)
runGetOrFail Get Header
forall t. Binary t => Get t
get (ByteString
-> Either
(ByteString, ByteOffset, String) (ByteString, ByteOffset, Header))
-> ByteString
-> Either
(ByteString, ByteOffset, String) (ByteString, ByteOffset, Header)
forall a b. (a -> b) -> a -> b
$ ByteString -> ByteString
BL.fromStrict ByteString
bs of
Left (ByteString, ByteOffset, String)
e -> (ByteString, ByteOffset, String) -> m a
forall (m :: * -> *) a.
MonadLifx m =>
(ByteString, ByteOffset, String) -> m a
throwDecodeFailure (ByteString, ByteOffset, String)
e
Right (ByteString
bs', ByteOffset
_, Header{Word16
$sel:packetType:Header :: Header -> Word16
packetType :: Word16
packetType, Word8
$sel:sequenceCounter:Header :: Header -> Word8
sequenceCounter :: Word8
sequenceCounter}) -> do
Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Word8
sequenceCounter Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
/= Word8
counter) (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ LifxError -> m ()
forall (m :: * -> *) a. MonadLifx m => LifxError -> m a
lifxThrow (LifxError -> m ()) -> LifxError -> m ()
forall a b. (a -> b) -> a -> b
$ Word8 -> Word8 -> LifxError
WrongSequenceNumber Word8
counter Word8
sequenceCounter
Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Word16
packetType Word16 -> Word16 -> Bool
forall a. Eq a => a -> a -> Bool
/= Word16
expectedPacketType) (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ LifxError -> m ()
forall (m :: * -> *) a. MonadLifx m => LifxError -> m a
lifxThrow (LifxError -> m ()) -> LifxError -> m ()
forall a b. (a -> b) -> a -> b
$ Word16 -> Word16 -> LifxError
WrongPacketType Word16
packetType Word16
expectedPacketType
case Get a
-> ByteString
-> Either
(ByteString, ByteOffset, String) (ByteString, ByteOffset, a)
forall a.
Get a
-> ByteString
-> Either
(ByteString, ByteOffset, String) (ByteString, ByteOffset, a)
runGetOrFail Get a
getBody ByteString
bs' of
Left (ByteString, ByteOffset, String)
e -> (ByteString, ByteOffset, String) -> m a
forall (m :: * -> *) a.
MonadLifx m =>
(ByteString, ByteOffset, String) -> m a
throwDecodeFailure (ByteString, ByteOffset, String)
e
Right (ByteString
_, ByteOffset
_, a
res) -> a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure a
res
where
throwDecodeFailure :: (ByteString, ByteOffset, String) -> m a
throwDecodeFailure (ByteString
bs, ByteOffset
bo, String
e) = LifxError -> m a
forall (m :: * -> *) a. MonadLifx m => LifxError -> m a
lifxThrow (LifxError -> m a) -> LifxError -> m a
forall a b. (a -> b) -> a -> b
$ ByteString -> ByteOffset -> String -> LifxError
DecodeFailure (ByteString -> ByteString
BL.toStrict ByteString
bs) ByteOffset
bo String
e
throwEither :: m (Either LifxError b) -> m b
throwEither m (Either LifxError b)
x =
m (Either LifxError b)
x m (Either LifxError b) -> (Either LifxError b -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Left LifxError
e -> LifxError -> m b
forall (m :: * -> *) a. MonadLifx m => LifxError -> m a
lifxThrow LifxError
e
Right b
r -> b -> m b
forall (f :: * -> *) a. Applicative f => a -> f a
pure b
r
data HSBK = HSBK
{ HSBK -> Word16
hue :: Word16
, HSBK -> Word16
saturation :: Word16
, HSBK -> Word16
brightness :: Word16
, HSBK -> Word16
kelvin :: Word16
}
deriving (HSBK -> HSBK -> Bool
(HSBK -> HSBK -> Bool) -> (HSBK -> HSBK -> Bool) -> Eq HSBK
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: HSBK -> HSBK -> Bool
$c/= :: HSBK -> HSBK -> Bool
== :: HSBK -> HSBK -> Bool
$c== :: HSBK -> HSBK -> Bool
Eq, Eq HSBK
Eq HSBK
-> (HSBK -> HSBK -> Ordering)
-> (HSBK -> HSBK -> Bool)
-> (HSBK -> HSBK -> Bool)
-> (HSBK -> HSBK -> Bool)
-> (HSBK -> HSBK -> Bool)
-> (HSBK -> HSBK -> HSBK)
-> (HSBK -> HSBK -> HSBK)
-> Ord HSBK
HSBK -> HSBK -> Bool
HSBK -> HSBK -> Ordering
HSBK -> HSBK -> HSBK
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: HSBK -> HSBK -> HSBK
$cmin :: HSBK -> HSBK -> HSBK
max :: HSBK -> HSBK -> HSBK
$cmax :: HSBK -> HSBK -> HSBK
>= :: HSBK -> HSBK -> Bool
$c>= :: HSBK -> HSBK -> Bool
> :: HSBK -> HSBK -> Bool
$c> :: HSBK -> HSBK -> Bool
<= :: HSBK -> HSBK -> Bool
$c<= :: HSBK -> HSBK -> Bool
< :: HSBK -> HSBK -> Bool
$c< :: HSBK -> HSBK -> Bool
compare :: HSBK -> HSBK -> Ordering
$ccompare :: HSBK -> HSBK -> Ordering
$cp1Ord :: Eq HSBK
Ord, Int -> HSBK -> ShowS
[HSBK] -> ShowS
HSBK -> String
(Int -> HSBK -> ShowS)
-> (HSBK -> String) -> ([HSBK] -> ShowS) -> Show HSBK
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [HSBK] -> ShowS
$cshowList :: [HSBK] -> ShowS
show :: HSBK -> String
$cshow :: HSBK -> String
showsPrec :: Int -> HSBK -> ShowS
$cshowsPrec :: Int -> HSBK -> ShowS
Show, (forall x. HSBK -> Rep HSBK x)
-> (forall x. Rep HSBK x -> HSBK) -> Generic HSBK
forall x. Rep HSBK x -> HSBK
forall x. HSBK -> Rep HSBK x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep HSBK x -> HSBK
$cfrom :: forall x. HSBK -> Rep HSBK x
Generic)
newtype Duration = Duration Word32
deriving (Duration -> Duration -> Bool
(Duration -> Duration -> Bool)
-> (Duration -> Duration -> Bool) -> Eq Duration
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Duration -> Duration -> Bool
$c/= :: Duration -> Duration -> Bool
== :: Duration -> Duration -> Bool
$c== :: Duration -> Duration -> Bool
Eq, Eq Duration
Eq Duration
-> (Duration -> Duration -> Ordering)
-> (Duration -> Duration -> Bool)
-> (Duration -> Duration -> Bool)
-> (Duration -> Duration -> Bool)
-> (Duration -> Duration -> Bool)
-> (Duration -> Duration -> Duration)
-> (Duration -> Duration -> Duration)
-> Ord Duration
Duration -> Duration -> Bool
Duration -> Duration -> Ordering
Duration -> Duration -> Duration
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Duration -> Duration -> Duration
$cmin :: Duration -> Duration -> Duration
max :: Duration -> Duration -> Duration
$cmax :: Duration -> Duration -> Duration
>= :: Duration -> Duration -> Bool
$c>= :: Duration -> Duration -> Bool
> :: Duration -> Duration -> Bool
$c> :: Duration -> Duration -> Bool
<= :: Duration -> Duration -> Bool
$c<= :: Duration -> Duration -> Bool
< :: Duration -> Duration -> Bool
$c< :: Duration -> Duration -> Bool
compare :: Duration -> Duration -> Ordering
$ccompare :: Duration -> Duration -> Ordering
$cp1Ord :: Eq Duration
Ord, Int -> Duration -> ShowS
[Duration] -> ShowS
Duration -> String
(Int -> Duration -> ShowS)
-> (Duration -> String) -> ([Duration] -> ShowS) -> Show Duration
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Duration] -> ShowS
$cshowList :: [Duration] -> ShowS
show :: Duration -> String
$cshow :: Duration -> String
showsPrec :: Int -> Duration -> ShowS
$cshowsPrec :: Int -> Duration -> ShowS
Show, (forall x. Duration -> Rep Duration x)
-> (forall x. Rep Duration x -> Duration) -> Generic Duration
forall x. Rep Duration x -> Duration
forall x. Duration -> Rep Duration x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Duration x -> Duration
$cfrom :: forall x. Duration -> Rep Duration x
Generic)
data Message a where
GetPower :: Message StatePower
SetPower :: Bool -> Message ()
GetColor :: Message LightState
SetColor :: HSBK -> Duration -> Message ()
SetLightPower :: Bool -> Duration -> Message ()
deriving instance (Eq (Message a))
deriving instance (Ord (Message a))
deriving instance (Show (Message a))
newtype StatePower = StatePower
{ StatePower -> Word16
power :: Word16
}
deriving (StatePower -> StatePower -> Bool
(StatePower -> StatePower -> Bool)
-> (StatePower -> StatePower -> Bool) -> Eq StatePower
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: StatePower -> StatePower -> Bool
$c/= :: StatePower -> StatePower -> Bool
== :: StatePower -> StatePower -> Bool
$c== :: StatePower -> StatePower -> Bool
Eq, Eq StatePower
Eq StatePower
-> (StatePower -> StatePower -> Ordering)
-> (StatePower -> StatePower -> Bool)
-> (StatePower -> StatePower -> Bool)
-> (StatePower -> StatePower -> Bool)
-> (StatePower -> StatePower -> Bool)
-> (StatePower -> StatePower -> StatePower)
-> (StatePower -> StatePower -> StatePower)
-> Ord StatePower
StatePower -> StatePower -> Bool
StatePower -> StatePower -> Ordering
StatePower -> StatePower -> StatePower
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: StatePower -> StatePower -> StatePower
$cmin :: StatePower -> StatePower -> StatePower
max :: StatePower -> StatePower -> StatePower
$cmax :: StatePower -> StatePower -> StatePower
>= :: StatePower -> StatePower -> Bool
$c>= :: StatePower -> StatePower -> Bool
> :: StatePower -> StatePower -> Bool
$c> :: StatePower -> StatePower -> Bool
<= :: StatePower -> StatePower -> Bool
$c<= :: StatePower -> StatePower -> Bool
< :: StatePower -> StatePower -> Bool
$c< :: StatePower -> StatePower -> Bool
compare :: StatePower -> StatePower -> Ordering
$ccompare :: StatePower -> StatePower -> Ordering
$cp1Ord :: Eq StatePower
Ord, Int -> StatePower -> ShowS
[StatePower] -> ShowS
StatePower -> String
(Int -> StatePower -> ShowS)
-> (StatePower -> String)
-> ([StatePower] -> ShowS)
-> Show StatePower
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [StatePower] -> ShowS
$cshowList :: [StatePower] -> ShowS
show :: StatePower -> String
$cshow :: StatePower -> String
showsPrec :: Int -> StatePower -> ShowS
$cshowsPrec :: Int -> StatePower -> ShowS
Show, (forall x. StatePower -> Rep StatePower x)
-> (forall x. Rep StatePower x -> StatePower) -> Generic StatePower
forall x. Rep StatePower x -> StatePower
forall x. StatePower -> Rep StatePower x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep StatePower x -> StatePower
$cfrom :: forall x. StatePower -> Rep StatePower x
Generic)
data LightState = LightState
{ LightState -> HSBK
hsbk :: HSBK
, LightState -> Word16
power :: Word16
, LightState -> ByteString
label :: BS.ByteString
}
deriving (LightState -> LightState -> Bool
(LightState -> LightState -> Bool)
-> (LightState -> LightState -> Bool) -> Eq LightState
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: LightState -> LightState -> Bool
$c/= :: LightState -> LightState -> Bool
== :: LightState -> LightState -> Bool
$c== :: LightState -> LightState -> Bool
Eq, Eq LightState
Eq LightState
-> (LightState -> LightState -> Ordering)
-> (LightState -> LightState -> Bool)
-> (LightState -> LightState -> Bool)
-> (LightState -> LightState -> Bool)
-> (LightState -> LightState -> Bool)
-> (LightState -> LightState -> LightState)
-> (LightState -> LightState -> LightState)
-> Ord LightState
LightState -> LightState -> Bool
LightState -> LightState -> Ordering
LightState -> LightState -> LightState
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: LightState -> LightState -> LightState
$cmin :: LightState -> LightState -> LightState
max :: LightState -> LightState -> LightState
$cmax :: LightState -> LightState -> LightState
>= :: LightState -> LightState -> Bool
$c>= :: LightState -> LightState -> Bool
> :: LightState -> LightState -> Bool
$c> :: LightState -> LightState -> Bool
<= :: LightState -> LightState -> Bool
$c<= :: LightState -> LightState -> Bool
< :: LightState -> LightState -> Bool
$c< :: LightState -> LightState -> Bool
compare :: LightState -> LightState -> Ordering
$ccompare :: LightState -> LightState -> Ordering
$cp1Ord :: Eq LightState
Ord, Int -> LightState -> ShowS
[LightState] -> ShowS
LightState -> String
(Int -> LightState -> ShowS)
-> (LightState -> String)
-> ([LightState] -> ShowS)
-> Show LightState
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [LightState] -> ShowS
$cshowList :: [LightState] -> ShowS
show :: LightState -> String
$cshow :: LightState -> String
showsPrec :: Int -> LightState -> ShowS
$cshowsPrec :: Int -> LightState -> ShowS
Show, (forall x. LightState -> Rep LightState x)
-> (forall x. Rep LightState x -> LightState) -> Generic LightState
forall x. Rep LightState x -> LightState
forall x. LightState -> Rep LightState x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep LightState x -> LightState
$cfrom :: forall x. LightState -> Rep LightState x
Generic)
data LifxError
= DecodeFailure BS.ByteString ByteOffset String
| RecvTimeout
| WrongPacketType Word16 Word16
| WrongSender SockAddr SockAddr
| WrongSequenceNumber Word8 Word8
deriving (LifxError -> LifxError -> Bool
(LifxError -> LifxError -> Bool)
-> (LifxError -> LifxError -> Bool) -> Eq LifxError
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: LifxError -> LifxError -> Bool
$c/= :: LifxError -> LifxError -> Bool
== :: LifxError -> LifxError -> Bool
$c== :: LifxError -> LifxError -> Bool
Eq, Eq LifxError
Eq LifxError
-> (LifxError -> LifxError -> Ordering)
-> (LifxError -> LifxError -> Bool)
-> (LifxError -> LifxError -> Bool)
-> (LifxError -> LifxError -> Bool)
-> (LifxError -> LifxError -> Bool)
-> (LifxError -> LifxError -> LifxError)
-> (LifxError -> LifxError -> LifxError)
-> Ord LifxError
LifxError -> LifxError -> Bool
LifxError -> LifxError -> Ordering
LifxError -> LifxError -> LifxError
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: LifxError -> LifxError -> LifxError
$cmin :: LifxError -> LifxError -> LifxError
max :: LifxError -> LifxError -> LifxError
$cmax :: LifxError -> LifxError -> LifxError
>= :: LifxError -> LifxError -> Bool
$c>= :: LifxError -> LifxError -> Bool
> :: LifxError -> LifxError -> Bool
$c> :: LifxError -> LifxError -> Bool
<= :: LifxError -> LifxError -> Bool
$c<= :: LifxError -> LifxError -> Bool
< :: LifxError -> LifxError -> Bool
$c< :: LifxError -> LifxError -> Bool
compare :: LifxError -> LifxError -> Ordering
$ccompare :: LifxError -> LifxError -> Ordering
$cp1Ord :: Eq LifxError
Ord, Int -> LifxError -> ShowS
[LifxError] -> ShowS
LifxError -> String
(Int -> LifxError -> ShowS)
-> (LifxError -> String)
-> ([LifxError] -> ShowS)
-> Show LifxError
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [LifxError] -> ShowS
$cshowList :: [LifxError] -> ShowS
show :: LifxError -> String
$cshow :: LifxError -> String
showsPrec :: Int -> LifxError -> ShowS
$cshowsPrec :: Int -> LifxError -> ShowS
Show, (forall x. LifxError -> Rep LifxError x)
-> (forall x. Rep LifxError x -> LifxError) -> Generic LifxError
forall x. Rep LifxError x -> LifxError
forall x. LifxError -> Rep LifxError x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep LifxError x -> LifxError
$cfrom :: forall x. LifxError -> Rep LifxError x
Generic)
class Response a where
getResponse :: Either a (Word16, Int, Get a)
instance Response () where
getResponse :: Either () (Word16, Int, Get ())
getResponse = () -> Either () (Word16, Int, Get ())
forall a b. a -> Either a b
Left ()
instance Response LightState where
getResponse :: Either LightState (Word16, Int, Get LightState)
getResponse = (Word16, Int, Get LightState)
-> Either LightState (Word16, Int, Get LightState)
forall a b. b -> Either a b
Right ((Word16, Int, Get LightState)
-> Either LightState (Word16, Int, Get LightState))
-> (Word16, Int, Get LightState)
-> Either LightState (Word16, Int, Get LightState)
forall a b. (a -> b) -> a -> b
$ (Word16
107,Int
52,) do
HSBK
hsbk <- Word16 -> Word16 -> Word16 -> Word16 -> HSBK
HSBK (Word16 -> Word16 -> Word16 -> Word16 -> HSBK)
-> Get Word16 -> Get (Word16 -> Word16 -> Word16 -> HSBK)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Get Word16
getWord16le Get (Word16 -> Word16 -> Word16 -> HSBK)
-> Get Word16 -> Get (Word16 -> Word16 -> HSBK)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Get Word16
getWord16le Get (Word16 -> Word16 -> HSBK)
-> Get Word16 -> Get (Word16 -> HSBK)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Get Word16
getWord16le Get (Word16 -> HSBK) -> Get Word16 -> Get HSBK
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Get Word16
getWord16le
Int -> Get ()
skip Int
2
Word16
power <- Get Word16
getWord16le
ByteString
label <- (Word8 -> Bool) -> ByteString -> ByteString
BS.takeWhile (Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
/= Word8
0) (ByteString -> ByteString) -> Get ByteString -> Get ByteString
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> Get ByteString
getByteString Int
32
Int -> Get ()
skip Int
8
LightState -> Get LightState
forall (f :: * -> *) a. Applicative f => a -> f a
pure LightState :: HSBK -> Word16 -> ByteString -> LightState
LightState{Word16
ByteString
HSBK
label :: ByteString
power :: Word16
hsbk :: HSBK
$sel:label:LightState :: ByteString
$sel:power:LightState :: Word16
$sel:hsbk:LightState :: HSBK
..}
instance Response StatePower where
getResponse :: Either StatePower (Word16, Int, Get StatePower)
getResponse =
(Word16, Int, Get StatePower)
-> Either StatePower (Word16, Int, Get StatePower)
forall a b. b -> Either a b
Right ((Word16, Int, Get StatePower)
-> Either StatePower (Word16, Int, Get StatePower))
-> (Get StatePower -> (Word16, Int, Get StatePower))
-> Get StatePower
-> Either StatePower (Word16, Int, Get StatePower)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Word16
22,Int
2,) (Get StatePower -> Either StatePower (Word16, Int, Get StatePower))
-> Get StatePower
-> Either StatePower (Word16, Int, Get StatePower)
forall a b. (a -> b) -> a -> b
$
Word16 -> StatePower
StatePower (Word16 -> StatePower) -> Get Word16 -> Get StatePower
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Get Word16
getWord16le
getResponse' :: Message a -> Either a (Word16, Int, Get a)
getResponse' :: Message a -> Either a (Word16, Int, Get a)
getResponse' = \case
GetPower{} -> Either a (Word16, Int, Get a)
forall a. Response a => Either a (Word16, Int, Get a)
getResponse
SetPower{} -> Either a (Word16, Int, Get a)
forall a. Response a => Either a (Word16, Int, Get a)
getResponse
GetColor{} -> Either a (Word16, Int, Get a)
forall a. Response a => Either a (Word16, Int, Get a)
getResponse
SetColor{} -> Either a (Word16, Int, Get a)
forall a. Response a => Either a (Word16, Int, Get a)
getResponse
SetLightPower{} -> Either a (Word16, Int, Get a)
forall a. Response a => Either a (Word16, Int, Get a)
getResponse
type Lifx = LifxT IO
newtype LifxT m a = LifxT
{ LifxT m a
-> StateT
Word8 (ReaderT (Socket, HostAddress, Int) (ExceptT LifxError m)) a
unLifxT ::
StateT
Word8
( ReaderT
(Socket, Word32, Int)
( ExceptT
LifxError
m
)
)
a
}
deriving newtype
( a -> LifxT m b -> LifxT m a
(a -> b) -> LifxT m a -> LifxT m b
(forall a b. (a -> b) -> LifxT m a -> LifxT m b)
-> (forall a b. a -> LifxT m b -> LifxT m a) -> Functor (LifxT m)
forall a b. a -> LifxT m b -> LifxT m a
forall a b. (a -> b) -> LifxT m a -> LifxT m b
forall (m :: * -> *) a b. Functor m => a -> LifxT m b -> LifxT m a
forall (m :: * -> *) a b.
Functor m =>
(a -> b) -> LifxT m a -> LifxT m b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: a -> LifxT m b -> LifxT m a
$c<$ :: forall (m :: * -> *) a b. Functor m => a -> LifxT m b -> LifxT m a
fmap :: (a -> b) -> LifxT m a -> LifxT m b
$cfmap :: forall (m :: * -> *) a b.
Functor m =>
(a -> b) -> LifxT m a -> LifxT m b
Functor
, Functor (LifxT m)
a -> LifxT m a
Functor (LifxT m)
-> (forall a. a -> LifxT m a)
-> (forall a b. LifxT m (a -> b) -> LifxT m a -> LifxT m b)
-> (forall a b c.
(a -> b -> c) -> LifxT m a -> LifxT m b -> LifxT m c)
-> (forall a b. LifxT m a -> LifxT m b -> LifxT m b)
-> (forall a b. LifxT m a -> LifxT m b -> LifxT m a)
-> Applicative (LifxT m)
LifxT m a -> LifxT m b -> LifxT m b
LifxT m a -> LifxT m b -> LifxT m a
LifxT m (a -> b) -> LifxT m a -> LifxT m b
(a -> b -> c) -> LifxT m a -> LifxT m b -> LifxT m c
forall a. a -> LifxT m a
forall a b. LifxT m a -> LifxT m b -> LifxT m a
forall a b. LifxT m a -> LifxT m b -> LifxT m b
forall a b. LifxT m (a -> b) -> LifxT m a -> LifxT m b
forall a b c. (a -> b -> c) -> LifxT m a -> LifxT m b -> LifxT m c
forall (m :: * -> *). Monad m => Functor (LifxT m)
forall (m :: * -> *) a. Monad m => a -> LifxT m a
forall (m :: * -> *) a b.
Monad m =>
LifxT m a -> LifxT m b -> LifxT m a
forall (m :: * -> *) a b.
Monad m =>
LifxT m a -> LifxT m b -> LifxT m b
forall (m :: * -> *) a b.
Monad m =>
LifxT m (a -> b) -> LifxT m a -> LifxT m b
forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> c) -> LifxT m a -> LifxT m b -> LifxT m c
forall (f :: * -> *).
Functor f
-> (forall a. a -> f a)
-> (forall a b. f (a -> b) -> f a -> f b)
-> (forall a b c. (a -> b -> c) -> f a -> f b -> f c)
-> (forall a b. f a -> f b -> f b)
-> (forall a b. f a -> f b -> f a)
-> Applicative f
<* :: LifxT m a -> LifxT m b -> LifxT m a
$c<* :: forall (m :: * -> *) a b.
Monad m =>
LifxT m a -> LifxT m b -> LifxT m a
*> :: LifxT m a -> LifxT m b -> LifxT m b
$c*> :: forall (m :: * -> *) a b.
Monad m =>
LifxT m a -> LifxT m b -> LifxT m b
liftA2 :: (a -> b -> c) -> LifxT m a -> LifxT m b -> LifxT m c
$cliftA2 :: forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> c) -> LifxT m a -> LifxT m b -> LifxT m c
<*> :: LifxT m (a -> b) -> LifxT m a -> LifxT m b
$c<*> :: forall (m :: * -> *) a b.
Monad m =>
LifxT m (a -> b) -> LifxT m a -> LifxT m b
pure :: a -> LifxT m a
$cpure :: forall (m :: * -> *) a. Monad m => a -> LifxT m a
$cp1Applicative :: forall (m :: * -> *). Monad m => Functor (LifxT m)
Applicative
, Applicative (LifxT m)
a -> LifxT m a
Applicative (LifxT m)
-> (forall a b. LifxT m a -> (a -> LifxT m b) -> LifxT m b)
-> (forall a b. LifxT m a -> LifxT m b -> LifxT m b)
-> (forall a. a -> LifxT m a)
-> Monad (LifxT m)
LifxT m a -> (a -> LifxT m b) -> LifxT m b
LifxT m a -> LifxT m b -> LifxT m b
forall a. a -> LifxT m a
forall a b. LifxT m a -> LifxT m b -> LifxT m b
forall a b. LifxT m a -> (a -> LifxT m b) -> LifxT m b
forall (m :: * -> *). Monad m => Applicative (LifxT m)
forall (m :: * -> *) a. Monad m => a -> LifxT m a
forall (m :: * -> *) a b.
Monad m =>
LifxT m a -> LifxT m b -> LifxT m b
forall (m :: * -> *) a b.
Monad m =>
LifxT m a -> (a -> LifxT m b) -> LifxT m b
forall (m :: * -> *).
Applicative m
-> (forall a b. m a -> (a -> m b) -> m b)
-> (forall a b. m a -> m b -> m b)
-> (forall a. a -> m a)
-> Monad m
return :: a -> LifxT m a
$creturn :: forall (m :: * -> *) a. Monad m => a -> LifxT m a
>> :: LifxT m a -> LifxT m b -> LifxT m b
$c>> :: forall (m :: * -> *) a b.
Monad m =>
LifxT m a -> LifxT m b -> LifxT m b
>>= :: LifxT m a -> (a -> LifxT m b) -> LifxT m b
$c>>= :: forall (m :: * -> *) a b.
Monad m =>
LifxT m a -> (a -> LifxT m b) -> LifxT m b
$cp1Monad :: forall (m :: * -> *). Monad m => Applicative (LifxT m)
Monad
, Monad (LifxT m)
Monad (LifxT m)
-> (forall a. IO a -> LifxT m a) -> MonadIO (LifxT m)
IO a -> LifxT m a
forall a. IO a -> LifxT m a
forall (m :: * -> *).
Monad m -> (forall a. IO a -> m a) -> MonadIO m
forall (m :: * -> *). MonadIO m => Monad (LifxT m)
forall (m :: * -> *) a. MonadIO m => IO a -> LifxT m a
liftIO :: IO a -> LifxT m a
$cliftIO :: forall (m :: * -> *) a. MonadIO m => IO a -> LifxT m a
$cp1MonadIO :: forall (m :: * -> *). MonadIO m => Monad (LifxT m)
MonadIO
)
runLifx :: Lifx a -> IO a
runLifx :: Lifx a -> IO a
runLifx Lifx a
m =
Int -> Lifx a -> IO (Either LifxError a)
forall (m :: * -> *) a.
MonadIO m =>
Int -> LifxT m a -> m (Either LifxError a)
runLifxT Int
1_000_000 Lifx a
m IO (Either LifxError a) -> (Either LifxError a -> IO a) -> IO a
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Left LifxError
e ->
IOError -> IO a
forall a. IOError -> IO a
ioError
IOError :: Maybe Handle
-> IOErrorType
-> String
-> String
-> Maybe CInt
-> Maybe String
-> IOError
IOError
{ ioe_handle :: Maybe Handle
ioe_handle = Maybe Handle
forall a. Maybe a
Nothing
, ioe_type :: IOErrorType
ioe_type = IOErrorType
OtherError
, ioe_location :: String
ioe_location = String
"LIFX"
, ioe_description :: String
ioe_description = LifxError -> String
forall a. Show a => a -> String
show LifxError
e
, ioe_errno :: Maybe CInt
ioe_errno = Maybe CInt
forall a. Maybe a
Nothing
, ioe_filename :: Maybe String
ioe_filename = Maybe String
forall a. Maybe a
Nothing
}
Right a
x -> a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure a
x
runLifxT :: MonadIO m => Int -> LifxT m a -> m (Either LifxError a)
runLifxT :: Int -> LifxT m a -> m (Either LifxError a)
runLifxT Int
timeoutDuration (LifxT StateT
Word8 (ReaderT (Socket, HostAddress, Int) (ExceptT LifxError m)) a
x) = do
Socket
sock <- IO Socket -> m Socket
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Socket -> m Socket) -> IO Socket -> m Socket
forall a b. (a -> b) -> a -> b
$ Family -> SocketType -> CInt -> IO Socket
socket Family
AF_INET SocketType
Datagram CInt
defaultProtocol
IO () -> m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> (SockAddr -> IO ()) -> SockAddr -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Socket -> SockAddr -> IO ()
bind Socket
sock (SockAddr -> m ()) -> SockAddr -> m ()
forall a b. (a -> b) -> a -> b
$ PortNumber -> HostAddress -> SockAddr
SockAddrInet PortNumber
defaultPort HostAddress
0
HostAddress
source <- m HostAddress
forall a (m :: * -> *). (Random a, MonadIO m) => m a
randomIO
ExceptT LifxError m a -> m (Either LifxError a)
forall e (m :: * -> *) a. ExceptT e m a -> m (Either e a)
runExceptT (ExceptT LifxError m a -> m (Either LifxError a))
-> ExceptT LifxError m a -> m (Either LifxError a)
forall a b. (a -> b) -> a -> b
$ ReaderT (Socket, HostAddress, Int) (ExceptT LifxError m) a
-> (Socket, HostAddress, Int) -> ExceptT LifxError m a
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT (StateT
Word8 (ReaderT (Socket, HostAddress, Int) (ExceptT LifxError m)) a
-> Word8
-> ReaderT (Socket, HostAddress, Int) (ExceptT LifxError m) a
forall (m :: * -> *) s a. Monad m => StateT s m a -> s -> m a
evalStateT StateT
Word8 (ReaderT (Socket, HostAddress, Int) (ExceptT LifxError m)) a
x Word8
0) (Socket
sock, HostAddress
source, Int
timeoutDuration)
class MonadIO m => MonadLifx m where
getSocket :: m Socket
getSource :: m Word32
getTimeout :: m Int
incrementCounter :: m ()
getCounter :: m Word8
lifxThrow :: LifxError -> m a
instance MonadIO m => MonadLifx (LifxT m) where
getSocket :: LifxT m Socket
getSocket = StateT
Word8
(ReaderT (Socket, HostAddress, Int) (ExceptT LifxError m))
Socket
-> LifxT m Socket
forall (m :: * -> *) a.
StateT
Word8 (ReaderT (Socket, HostAddress, Int) (ExceptT LifxError m)) a
-> LifxT m a
LifxT (StateT
Word8
(ReaderT (Socket, HostAddress, Int) (ExceptT LifxError m))
Socket
-> LifxT m Socket)
-> StateT
Word8
(ReaderT (Socket, HostAddress, Int) (ExceptT LifxError m))
Socket
-> LifxT m Socket
forall a b. (a -> b) -> a -> b
$ ((Socket, HostAddress, Int) -> Socket)
-> StateT
Word8
(ReaderT (Socket, HostAddress, Int) (ExceptT LifxError m))
Socket
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks (Socket, HostAddress, Int) -> Socket
forall a b c. (a, b, c) -> a
fst3
getSource :: LifxT m HostAddress
getSource = StateT
Word8
(ReaderT (Socket, HostAddress, Int) (ExceptT LifxError m))
HostAddress
-> LifxT m HostAddress
forall (m :: * -> *) a.
StateT
Word8 (ReaderT (Socket, HostAddress, Int) (ExceptT LifxError m)) a
-> LifxT m a
LifxT (StateT
Word8
(ReaderT (Socket, HostAddress, Int) (ExceptT LifxError m))
HostAddress
-> LifxT m HostAddress)
-> StateT
Word8
(ReaderT (Socket, HostAddress, Int) (ExceptT LifxError m))
HostAddress
-> LifxT m HostAddress
forall a b. (a -> b) -> a -> b
$ ((Socket, HostAddress, Int) -> HostAddress)
-> StateT
Word8
(ReaderT (Socket, HostAddress, Int) (ExceptT LifxError m))
HostAddress
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks (Socket, HostAddress, Int) -> HostAddress
forall a b c. (a, b, c) -> b
snd3
getTimeout :: LifxT m Int
getTimeout = StateT
Word8
(ReaderT (Socket, HostAddress, Int) (ExceptT LifxError m))
Int
-> LifxT m Int
forall (m :: * -> *) a.
StateT
Word8 (ReaderT (Socket, HostAddress, Int) (ExceptT LifxError m)) a
-> LifxT m a
LifxT (StateT
Word8
(ReaderT (Socket, HostAddress, Int) (ExceptT LifxError m))
Int
-> LifxT m Int)
-> StateT
Word8
(ReaderT (Socket, HostAddress, Int) (ExceptT LifxError m))
Int
-> LifxT m Int
forall a b. (a -> b) -> a -> b
$ ((Socket, HostAddress, Int) -> Int)
-> StateT
Word8
(ReaderT (Socket, HostAddress, Int) (ExceptT LifxError m))
Int
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks (Socket, HostAddress, Int) -> Int
forall a b c. (a, b, c) -> c
thd3
incrementCounter :: LifxT m ()
incrementCounter = StateT
Word8 (ReaderT (Socket, HostAddress, Int) (ExceptT LifxError m)) ()
-> LifxT m ()
forall (m :: * -> *) a.
StateT
Word8 (ReaderT (Socket, HostAddress, Int) (ExceptT LifxError m)) a
-> LifxT m a
LifxT (StateT
Word8 (ReaderT (Socket, HostAddress, Int) (ExceptT LifxError m)) ()
-> LifxT m ())
-> StateT
Word8 (ReaderT (Socket, HostAddress, Int) (ExceptT LifxError m)) ()
-> LifxT m ()
forall a b. (a -> b) -> a -> b
$ (Word8 -> Word8)
-> StateT
Word8 (ReaderT (Socket, HostAddress, Int) (ExceptT LifxError m)) ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify Word8 -> Word8
forall a. (Eq a, Bounded a, Enum a) => a -> a
succ'
getCounter :: LifxT m Word8
getCounter = StateT
Word8
(ReaderT (Socket, HostAddress, Int) (ExceptT LifxError m))
Word8
-> LifxT m Word8
forall (m :: * -> *) a.
StateT
Word8 (ReaderT (Socket, HostAddress, Int) (ExceptT LifxError m)) a
-> LifxT m a
LifxT (StateT
Word8
(ReaderT (Socket, HostAddress, Int) (ExceptT LifxError m))
Word8
-> LifxT m Word8)
-> StateT
Word8
(ReaderT (Socket, HostAddress, Int) (ExceptT LifxError m))
Word8
-> LifxT m Word8
forall a b. (a -> b) -> a -> b
$ (Word8 -> Word8)
-> StateT
Word8
(ReaderT (Socket, HostAddress, Int) (ExceptT LifxError m))
Word8
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets Word8 -> Word8
forall a. a -> a
id
lifxThrow :: LifxError -> LifxT m a
lifxThrow = StateT
Word8 (ReaderT (Socket, HostAddress, Int) (ExceptT LifxError m)) a
-> LifxT m a
forall (m :: * -> *) a.
StateT
Word8 (ReaderT (Socket, HostAddress, Int) (ExceptT LifxError m)) a
-> LifxT m a
LifxT (StateT
Word8 (ReaderT (Socket, HostAddress, Int) (ExceptT LifxError m)) a
-> LifxT m a)
-> (LifxError
-> StateT
Word8 (ReaderT (Socket, HostAddress, Int) (ExceptT LifxError m)) a)
-> LifxError
-> LifxT m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LifxError
-> StateT
Word8 (ReaderT (Socket, HostAddress, Int) (ExceptT LifxError m)) a
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError
instance MonadLifx m => MonadLifx (StateT s m) where
getSocket :: StateT s m Socket
getSocket = m Socket -> StateT s m Socket
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m Socket
forall (m :: * -> *). MonadLifx m => m Socket
getSocket
getSource :: StateT s m HostAddress
getSource = m HostAddress -> StateT s m HostAddress
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m HostAddress
forall (m :: * -> *). MonadLifx m => m HostAddress
getSource
getTimeout :: StateT s m Int
getTimeout = m Int -> StateT s m Int
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m Int
forall (m :: * -> *). MonadLifx m => m Int
getTimeout
incrementCounter :: StateT s m ()
incrementCounter = m () -> StateT s m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m ()
forall (m :: * -> *). MonadLifx m => m ()
incrementCounter
getCounter :: StateT s m Word8
getCounter = m Word8 -> StateT s m Word8
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m Word8
forall (m :: * -> *). MonadLifx m => m Word8
getCounter
lifxThrow :: LifxError -> StateT s m a
lifxThrow = m a -> StateT s m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m a -> StateT s m a)
-> (LifxError -> m a) -> LifxError -> StateT s m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LifxError -> m a
forall (m :: * -> *) a. MonadLifx m => LifxError -> m a
lifxThrow
instance MonadLifx m => MonadLifx (ReaderT e m) where
getSocket :: ReaderT e m Socket
getSocket = m Socket -> ReaderT e m Socket
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m Socket
forall (m :: * -> *). MonadLifx m => m Socket
getSocket
getSource :: ReaderT e m HostAddress
getSource = m HostAddress -> ReaderT e m HostAddress
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m HostAddress
forall (m :: * -> *). MonadLifx m => m HostAddress
getSource
getTimeout :: ReaderT e m Int
getTimeout = m Int -> ReaderT e m Int
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m Int
forall (m :: * -> *). MonadLifx m => m Int
getTimeout
incrementCounter :: ReaderT e m ()
incrementCounter = m () -> ReaderT e m ()
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m ()
forall (m :: * -> *). MonadLifx m => m ()
incrementCounter
getCounter :: ReaderT e m Word8
getCounter = m Word8 -> ReaderT e m Word8
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m Word8
forall (m :: * -> *). MonadLifx m => m Word8
getCounter
lifxThrow :: LifxError -> ReaderT e m a
lifxThrow = m a -> ReaderT e m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m a -> ReaderT e m a)
-> (LifxError -> m a) -> LifxError -> ReaderT e m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LifxError -> m a
forall (m :: * -> *) a. MonadLifx m => LifxError -> m a
lifxThrow
encodeMessage :: Bool -> Word8 -> Word32 -> Message a -> BL.ByteString
encodeMessage :: Bool -> Word8 -> HostAddress -> Message a -> ByteString
encodeMessage Bool
ackRequired Word8
sequenceCounter HostAddress
source Message a
msg =
Put -> ByteString
runPut (Put -> ByteString) -> Put -> ByteString
forall a b. (a -> b) -> a -> b
$ Header -> Put
forall t. Binary t => t -> Put
put (Bool -> Word8 -> HostAddress -> Message a -> Header
forall a. Bool -> Word8 -> HostAddress -> Message a -> Header
messageHeader Bool
ackRequired Word8
sequenceCounter HostAddress
source Message a
msg) Put -> Put -> Put
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Message a -> Put
forall a. Message a -> Put
putMessagePayload Message a
msg
data =
{ :: Word16
, :: Word16
, :: Bool
, :: Bool
, :: Word8
, :: Word32
, :: Word64
, :: Bool
, :: Bool
, :: Word8
, :: Word16
}
deriving (Header -> Header -> Bool
(Header -> Header -> Bool)
-> (Header -> Header -> Bool) -> Eq Header
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Header -> Header -> Bool
$c/= :: Header -> Header -> Bool
== :: Header -> Header -> Bool
$c== :: Header -> Header -> Bool
Eq, Eq Header
Eq Header
-> (Header -> Header -> Ordering)
-> (Header -> Header -> Bool)
-> (Header -> Header -> Bool)
-> (Header -> Header -> Bool)
-> (Header -> Header -> Bool)
-> (Header -> Header -> Header)
-> (Header -> Header -> Header)
-> Ord Header
Header -> Header -> Bool
Header -> Header -> Ordering
Header -> Header -> Header
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Header -> Header -> Header
$cmin :: Header -> Header -> Header
max :: Header -> Header -> Header
$cmax :: Header -> Header -> Header
>= :: Header -> Header -> Bool
$c>= :: Header -> Header -> Bool
> :: Header -> Header -> Bool
$c> :: Header -> Header -> Bool
<= :: Header -> Header -> Bool
$c<= :: Header -> Header -> Bool
< :: Header -> Header -> Bool
$c< :: Header -> Header -> Bool
compare :: Header -> Header -> Ordering
$ccompare :: Header -> Header -> Ordering
$cp1Ord :: Eq Header
Ord, Int -> Header -> ShowS
[Header] -> ShowS
Header -> String
(Int -> Header -> ShowS)
-> (Header -> String) -> ([Header] -> ShowS) -> Show Header
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Header] -> ShowS
$cshowList :: [Header] -> ShowS
show :: Header -> String
$cshow :: Header -> String
showsPrec :: Int -> Header -> ShowS
$cshowsPrec :: Int -> Header -> ShowS
Show, (forall x. Header -> Rep Header x)
-> (forall x. Rep Header x -> Header) -> Generic Header
forall x. Rep Header x -> Header
forall x. Header -> Rep Header x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Header x -> Header
$cfrom :: forall x. Header -> Rep Header x
Generic)
instance Binary Header where
get :: Get Header
get = do
Word16
size <- Get Word16
getWord16le
Word16
protBytes <- Get Word16
getWord16le
let protocol :: Word16
protocol = (Word16 -> Int -> Word16) -> Int -> Word16 -> Word16
forall a b c. (a -> b -> c) -> b -> a -> c
flip Word16 -> Int -> Word16
forall a. Bits a => a -> Int -> a
clearBit Int
12 (Word16 -> Word16) -> (Word16 -> Word16) -> Word16 -> Word16
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Word16 -> Int -> Word16) -> Int -> Word16 -> Word16
forall a b c. (a -> b -> c) -> b -> a -> c
flip Word16 -> Int -> Word16
forall a. Bits a => a -> Int -> a
clearBit Int
13 (Word16 -> Word16) -> (Word16 -> Word16) -> Word16 -> Word16
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Word16 -> Int -> Word16) -> Int -> Word16 -> Word16
forall a b c. (a -> b -> c) -> b -> a -> c
flip Word16 -> Int -> Word16
forall a. Bits a => a -> Int -> a
clearBit Int
14 (Word16 -> Word16) -> (Word16 -> Word16) -> Word16 -> Word16
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Word16 -> Int -> Word16) -> Int -> Word16 -> Word16
forall a b c. (a -> b -> c) -> b -> a -> c
flip Word16 -> Int -> Word16
forall a. Bits a => a -> Int -> a
clearBit Int
15 (Word16 -> Word16) -> Word16 -> Word16
forall a b. (a -> b) -> a -> b
$ Word16
protBytes
addressable :: Bool
addressable = Word16 -> Int -> Bool
forall a. Bits a => a -> Int -> Bool
testBit Word16
protBytes Int
12
tagged :: Bool
tagged = Word16 -> Int -> Bool
forall a. Bits a => a -> Int -> Bool
testBit Word16
protBytes Int
13
origin :: Word8
origin = (if Word16 -> Int -> Bool
forall a. Bits a => a -> Int -> Bool
testBit Word16
protBytes Int
14 then Word8
0 else Word8
1) Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
+ (if Word16 -> Int -> Bool
forall a. Bits a => a -> Int -> Bool
testBit Word16
protBytes Int
15 then Word8
0 else Word8
2)
HostAddress
source <- Get HostAddress
getWord32le
Word64
target <- Get Word64
getWord64be
Int -> Get ()
skip Int
6
Word8
resAckByte <- Get Word8
getWord8
let resRequired :: Bool
resRequired = Word8 -> Int -> Bool
forall a. Bits a => a -> Int -> Bool
testBit Word8
resAckByte Int
0
ackRequired :: Bool
ackRequired = Word8 -> Int -> Bool
forall a. Bits a => a -> Int -> Bool
testBit Word8
resAckByte Int
1
Word8
sequenceCounter <- Get Word8
getWord8
Int -> Get ()
skip Int
8
Word16
packetType <- Get Word16
getWord16le
Int -> Get ()
skip Int
2
Header -> Get Header
forall (f :: * -> *) a. Applicative f => a -> f a
pure Header :: Word16
-> Word16
-> Bool
-> Bool
-> Word8
-> HostAddress
-> Word64
-> Bool
-> Bool
-> Word8
-> Word16
-> Header
Header{Bool
Word8
Word16
HostAddress
Word64
packetType :: Word16
sequenceCounter :: Word8
ackRequired :: Bool
resRequired :: Bool
target :: Word64
source :: HostAddress
origin :: Word8
tagged :: Bool
addressable :: Bool
protocol :: Word16
size :: Word16
$sel:ackRequired:Header :: Bool
$sel:resRequired:Header :: Bool
$sel:target:Header :: Word64
$sel:source:Header :: HostAddress
$sel:origin:Header :: Word8
$sel:tagged:Header :: Bool
$sel:addressable:Header :: Bool
$sel:protocol:Header :: Word16
$sel:size:Header :: Word16
$sel:sequenceCounter:Header :: Word8
$sel:packetType:Header :: Word16
..}
put :: Header -> Put
put Header{Bool
Word8
Word16
HostAddress
Word64
packetType :: Word16
sequenceCounter :: Word8
ackRequired :: Bool
resRequired :: Bool
target :: Word64
source :: HostAddress
origin :: Word8
tagged :: Bool
addressable :: Bool
protocol :: Word16
size :: Word16
$sel:ackRequired:Header :: Header -> Bool
$sel:resRequired:Header :: Header -> Bool
$sel:target:Header :: Header -> Word64
$sel:source:Header :: Header -> HostAddress
$sel:origin:Header :: Header -> Word8
$sel:tagged:Header :: Header -> Bool
$sel:addressable:Header :: Header -> Bool
$sel:protocol:Header :: Header -> Word16
$sel:size:Header :: Header -> Word16
$sel:sequenceCounter:Header :: Header -> Word8
$sel:packetType:Header :: Header -> Word16
..} = do
Word16 -> Put
putWord16le Word16
size
Word16 -> Put
putWord16le (Word16 -> Put) -> Word16 -> Put
forall a b. (a -> b) -> a -> b
$
Word16
protocol
Word16 -> Word16 -> Word16
forall a. Bits a => a -> a -> a
.|. Bool -> Int -> Word16
forall p. Bits p => Bool -> Int -> p
bitIf Bool
addressable Int
12
Word16 -> Word16 -> Word16
forall a. Bits a => a -> a -> a
.|. Bool -> Int -> Word16
forall p. Bits p => Bool -> Int -> p
bitIf Bool
tagged Int
13
Word16 -> Word16 -> Word16
forall a. Bits a => a -> a -> a
.|. Bool -> Int -> Word16
forall p. Bits p => Bool -> Int -> p
bitIf (Word8 -> Int -> Bool
forall a. Bits a => a -> Int -> Bool
testBit Word8
origin Int
0) Int
14
Word16 -> Word16 -> Word16
forall a. Bits a => a -> a -> a
.|. Bool -> Int -> Word16
forall p. Bits p => Bool -> Int -> p
bitIf (Word8 -> Int -> Bool
forall a. Bits a => a -> Int -> Bool
testBit Word8
origin Int
1) Int
15
HostAddress -> Put
putWord32le HostAddress
source
Word64 -> Put
putWord64be Word64
target
Int -> Put -> Put
forall (m :: * -> *) a. Applicative m => Int -> m a -> m ()
replicateM_ Int
6 (Put -> Put) -> Put -> Put
forall a b. (a -> b) -> a -> b
$ Word8 -> Put
putWord8 Word8
0
Word8 -> Put
putWord8 (Word8 -> Put) -> Word8 -> Put
forall a b. (a -> b) -> a -> b
$
Word8
forall a. Bits a => a
zeroBits
Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.|. Bool -> Int -> Word8
forall p. Bits p => Bool -> Int -> p
bitIf Bool
resRequired Int
0
Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.|. Bool -> Int -> Word8
forall p. Bits p => Bool -> Int -> p
bitIf Bool
ackRequired Int
1
Word8 -> Put
putWord8 Word8
sequenceCounter
Int -> Put -> Put
forall (m :: * -> *) a. Applicative m => Int -> m a -> m ()
replicateM_ Int
8 (Put -> Put) -> Put -> Put
forall a b. (a -> b) -> a -> b
$ Word8 -> Put
putWord8 Word8
0
Word16 -> Put
putWord16le Word16
packetType
Int -> Put -> Put
forall (m :: * -> *) a. Applicative m => Int -> m a -> m ()
replicateM_ Int
2 (Put -> Put) -> Put -> Put
forall a b. (a -> b) -> a -> b
$ Word8 -> Put
putWord8 Word8
0
where
bitIf :: Bool -> Int -> p
bitIf Bool
b Int
n = if Bool
b then Int -> p
forall a. Bits a => Int -> a
bit Int
n else p
forall a. Bits a => a
zeroBits
messageHeader :: Bool -> Word8 -> Word32 -> Message a -> Header
Bool
ackRequired Word8
sequenceCounter HostAddress
source = \case
GetPower{} ->
Header :: Word16
-> Word16
-> Bool
-> Bool
-> Word8
-> HostAddress
-> Word64
-> Bool
-> Bool
-> Word8
-> Word16
-> Header
Header
{ $sel:size:Header :: Word16
size = Word16
forall a. Num a => a
headerSize
, $sel:packetType:Header :: Word16
packetType = Word16
20
, Bool
Word8
Word16
HostAddress
Word64
resRequired :: Bool
origin :: Word8
addressable :: Bool
tagged :: Bool
protocol :: Word16
target :: Word64
source :: HostAddress
sequenceCounter :: Word8
ackRequired :: Bool
$sel:ackRequired:Header :: Bool
$sel:resRequired:Header :: Bool
$sel:target:Header :: Word64
$sel:source:Header :: HostAddress
$sel:origin:Header :: Word8
$sel:tagged:Header :: Bool
$sel:addressable:Header :: Bool
$sel:protocol:Header :: Word16
$sel:sequenceCounter:Header :: Word8
..
}
SetPower{} ->
Header :: Word16
-> Word16
-> Bool
-> Bool
-> Word8
-> HostAddress
-> Word64
-> Bool
-> Bool
-> Word8
-> Word16
-> Header
Header
{ $sel:size:Header :: Word16
size = Word16
forall a. Num a => a
headerSize Word16 -> Word16 -> Word16
forall a. Num a => a -> a -> a
+ Word16
2
, $sel:packetType:Header :: Word16
packetType = Word16
21
, Bool
Word8
Word16
HostAddress
Word64
resRequired :: Bool
origin :: Word8
addressable :: Bool
tagged :: Bool
protocol :: Word16
target :: Word64
source :: HostAddress
sequenceCounter :: Word8
ackRequired :: Bool
$sel:ackRequired:Header :: Bool
$sel:resRequired:Header :: Bool
$sel:target:Header :: Word64
$sel:source:Header :: HostAddress
$sel:origin:Header :: Word8
$sel:tagged:Header :: Bool
$sel:addressable:Header :: Bool
$sel:protocol:Header :: Word16
$sel:sequenceCounter:Header :: Word8
..
}
GetColor{} ->
Header :: Word16
-> Word16
-> Bool
-> Bool
-> Word8
-> HostAddress
-> Word64
-> Bool
-> Bool
-> Word8
-> Word16
-> Header
Header
{ $sel:size:Header :: Word16
size = Word16
forall a. Num a => a
headerSize
, $sel:packetType:Header :: Word16
packetType = Word16
101
, Bool
Word8
Word16
HostAddress
Word64
resRequired :: Bool
origin :: Word8
addressable :: Bool
tagged :: Bool
protocol :: Word16
target :: Word64
source :: HostAddress
sequenceCounter :: Word8
ackRequired :: Bool
$sel:ackRequired:Header :: Bool
$sel:resRequired:Header :: Bool
$sel:target:Header :: Word64
$sel:source:Header :: HostAddress
$sel:origin:Header :: Word8
$sel:tagged:Header :: Bool
$sel:addressable:Header :: Bool
$sel:protocol:Header :: Word16
$sel:sequenceCounter:Header :: Word8
..
}
SetColor{} ->
Header :: Word16
-> Word16
-> Bool
-> Bool
-> Word8
-> HostAddress
-> Word64
-> Bool
-> Bool
-> Word8
-> Word16
-> Header
Header
{ $sel:size:Header :: Word16
size = Word16
forall a. Num a => a
headerSize Word16 -> Word16 -> Word16
forall a. Num a => a -> a -> a
+ Word16
13
, $sel:packetType:Header :: Word16
packetType = Word16
102
, Bool
Word8
Word16
HostAddress
Word64
resRequired :: Bool
origin :: Word8
addressable :: Bool
tagged :: Bool
protocol :: Word16
target :: Word64
source :: HostAddress
sequenceCounter :: Word8
ackRequired :: Bool
$sel:ackRequired:Header :: Bool
$sel:resRequired:Header :: Bool
$sel:target:Header :: Word64
$sel:source:Header :: HostAddress
$sel:origin:Header :: Word8
$sel:tagged:Header :: Bool
$sel:addressable:Header :: Bool
$sel:protocol:Header :: Word16
$sel:sequenceCounter:Header :: Word8
..
}
SetLightPower{} ->
Header :: Word16
-> Word16
-> Bool
-> Bool
-> Word8
-> HostAddress
-> Word64
-> Bool
-> Bool
-> Word8
-> Word16
-> Header
Header
{ $sel:size:Header :: Word16
size = Word16
forall a. Num a => a
headerSize Word16 -> Word16 -> Word16
forall a. Num a => a -> a -> a
+ Word16
6
, $sel:packetType:Header :: Word16
packetType = Word16
117
, Bool
Word8
Word16
HostAddress
Word64
resRequired :: Bool
origin :: Word8
addressable :: Bool
tagged :: Bool
protocol :: Word16
target :: Word64
source :: HostAddress
sequenceCounter :: Word8
ackRequired :: Bool
$sel:ackRequired:Header :: Bool
$sel:resRequired:Header :: Bool
$sel:target:Header :: Word64
$sel:source:Header :: HostAddress
$sel:origin:Header :: Word8
$sel:tagged:Header :: Bool
$sel:addressable:Header :: Bool
$sel:protocol:Header :: Word16
$sel:sequenceCounter:Header :: Word8
..
}
where
target :: Word64
target = Word64
0 :: Word64
protocol :: Word16
protocol = Word16
1024 :: Word16
tagged :: Bool
tagged = Bool
True
addressable :: Bool
addressable = Bool
True
origin :: Word8
origin = Word8
0 :: Word8
resRequired :: Bool
resRequired = Bool
False
putMessagePayload :: Message a -> Put
putMessagePayload :: Message a -> Put
putMessagePayload = \case
Message a
GetPower -> Put
forall a. Monoid a => a
mempty
SetPower Bool
b ->
Word16 -> Put
putWord16le if Bool
b then Word16
forall a. Bounded a => a
maxBound else Word16
forall a. Bounded a => a
minBound
Message a
GetColor -> Put
forall a. Monoid a => a
mempty
SetColor HSBK{Word16
kelvin :: Word16
brightness :: Word16
saturation :: Word16
hue :: Word16
$sel:kelvin:HSBK :: HSBK -> Word16
$sel:brightness:HSBK :: HSBK -> Word16
$sel:saturation:HSBK :: HSBK -> Word16
$sel:hue:HSBK :: HSBK -> Word16
..} (Duration HostAddress
d) -> do
Word8 -> Put
putWord8 Word8
0
Word16 -> Put
putWord16le Word16
hue
Word16 -> Put
putWord16le Word16
saturation
Word16 -> Put
putWord16le Word16
brightness
Word16 -> Put
putWord16le Word16
kelvin
HostAddress -> Put
putWord32le HostAddress
d
SetLightPower Bool
b (Duration HostAddress
d) -> do
Word16 -> Put
putWord16le if Bool
b then Word16
forall a. Bounded a => a
maxBound else Word16
forall a. Bounded a => a
minBound
HostAddress -> Put
putWord32le HostAddress
d
succ' :: (Eq a, Bounded a, Enum a) => a -> a
succ' :: a -> a
succ' a
e
| a
e a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
forall a. Bounded a => a
maxBound = a
forall a. Bounded a => a
minBound
| Bool
otherwise = a -> a
forall a. Enum a => a -> a
succ a
e
headerSize :: Num a => a
= a
36