mercury-api-0.1.0.0: examples/ExampleUtil.hs
{-# LANGUAGE OverloadedStrings #-}
module ExampleUtil
( createAndConnect
, createConnectAndParams
, optUri
, optRegion
, optPower
, optListen
) where
import Control.Exception ( throw, try )
import Control.Monad ( when, void, forM_ )
import Data.Int ( Int32 )
import Data.Monoid ( (<>) )
import qualified Data.Text as T ( replicate, pack, length )
import qualified Data.Text.IO as T ( putStrLn )
import Options.Applicative
( Parser,
value,
switch,
strOption,
short,
option,
metavar,
long,
help,
auto )
import qualified System.Hardware.MercuryApi as TMR
import qualified System.Hardware.MercuryApi.Params as TMR
import System.Exit ( exitFailure )
import System.Info ( os )
import System.IO ( stdout )
printRegionsAndFail :: TMR.Reader -> IO a
printRegionsAndFail rdr = do
rgns <- TMR.paramGetRegionSupportedRegions rdr
T.putStrLn "Region must be one of:"
forM_ rgns $ \rgn -> do
let dr = TMR.displayRegion rgn
nSpaces = 6 - T.length dr
spaces = T.replicate nSpaces " "
T.putStrLn $ " " <> dr <> spaces <> TMR.displayRegionDescription rgn
exitFailure
parseRegionOrFail :: TMR.Reader -> String -> IO TMR.Region
parseRegionOrFail rdr s =
case TMR.parseRegion (T.pack s) of
Nothing -> printRegionsAndFail rdr
Just rgn -> return rgn
printPowerAndFail :: TMR.Reader -> IO a
printPowerAndFail rdr = do
lo <- TMR.paramGetRadioPowerMin rdr
hi <- TMR.paramGetRadioPowerMax rdr
putStrLn $ "Power must be between " ++ show lo ++ " and " ++ show hi
exitFailure
handleParamError :: TMR.Reader -> Either TMR.MercuryException () -> IO ()
handleParamError _ (Right _) = return ()
handleParamError rdr (Left err) = hpe (TMR.meStatus err)
where hpe TMR.ERROR_INVALID_REGION = printRegionsAndFail rdr
hpe TMR.ERROR_MSG_POWER_TOO_HIGH = printPowerAndFail rdr
hpe TMR.ERROR_MSG_POWER_TOO_LOW = printPowerAndFail rdr
hpe _ = throw err
createAndConnect :: String -> Bool -> IO TMR.Reader
createAndConnect uri listen = do
rdr <- TMR.create $ T.pack uri
when (listen) $ do
listener <- TMR.opcodeListener stdout
void $ TMR.addTransportListener rdr listener
TMR.paramSetTransportTimeout rdr 10000
TMR.connect rdr
return rdr
createConnectAndParams :: String -> Bool -> String -> Int32 -> IO TMR.Reader
createConnectAndParams uri listen region power = do
rdr <- createAndConnect uri listen
rgn <- parseRegionOrFail rdr region
eth <- try $ TMR.paramSetBasics rdr rgn power TMR.sparkFunAntennas
handleParamError rdr eth
TMR.paramSetTagReadDataRecordHighestRssi rdr True
return rdr
defUri :: String
defUri = case os of
"darwin" -> "tmr:///dev/cu.SLAB_USBtoUART"
"mingw32" -> "tmr:///COM4"
_ -> "tmr:///dev/ttyUSB0"
defRegion :: String
defRegion = "na2"
defPower :: Int32
defPower = 2300
optUri :: Parser String
optUri = strOption (long "uri" <>
short 'u' <>
metavar "URI" <>
help ("Reader to connect to (default " ++ defUri ++ ")") <>
value defUri)
optRegion :: Parser String
optRegion = strOption (long "region" <>
short 'r' <>
metavar "REGION" <>
help ("Regulatory region (default " ++ defRegion ++ ")") <>
value defRegion)
optPower :: Parser Int32
optPower = option auto (long "power" <>
short 'p' <>
metavar "CENTI-DBM" <>
help ("Power level (0-2700, default " ++ show defPower ++ ")") <>
value defPower)
optListen :: Parser Bool
optListen = switch (long "transport-listener" <>
short 't' <>
help "Print bytes sent on serial port")