{-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE OverloadedRecordDot #-} {-# LANGUAGE OverloadedStrings #-} module Hsm.Command.Command ( Direction(X, Z) , Angle(CW, CCW) , Speed(Slow, Mid, Fast) , Command(Move, Rotate) , commandStream ) where import Data.Binary (Binary) import Data.ByteString (ByteString) import Data.Maybe (fromJust, isJust) import Data.Text (Text, pack) import Effectful (Eff, (:>)) import Effectful.Log (Log, logAttention_, logTrace_) import Effectful.Reader.Static (Reader, ask) import GHC.Generics (Generic) import GHC.Records (HasField) import Hsm.Command.Readline (Readline, readline) import Hsm.Core.Message (message) import Streamly.Data.Stream qualified as S import Text.Read (readEither) data Direction = X | Z deriving (Binary, Generic, Read, Show) data Angle = CW | CCW deriving (Binary, Generic, Read, Show) data Speed = Slow | Mid | Fast deriving (Binary, Generic, Read, Show) data Command = Move Direction Speed Int | Rotate Angle Speed Int deriving (Binary, Generic, Read, Show) commandStream :: forall env es. ( HasField "name" env Text , Log :> es , Reader env :> es , Readline :> es ) => S.Stream (Eff es) ByteString commandStream = S.mapMaybeM (parse . fromJust) $ S.takeWhile isJust $ S.repeatM readline where parse string = do case readEither @Command string of Left err -> do logAttention_ $ pack err return Nothing Right command -> do env <- ask @env logTrace_ $ "Sending command: " <> pack (show command) return $ Just $ message env.name command