packages feed

obd 0.2.0.2 → 0.2.1.0

raw patch · 4 files changed

+62/−11 lines, 4 files

Files

obd.cabal view
@@ -1,5 +1,5 @@ name:                obd-version:             0.2.0.2+version:             0.2.1.0 synopsis:            Communicate to OBD interfaces over ELM327 description:     Haskell library to communicate with OBD-II over ELM327,
src/System/Hardware/ELM327.hs view
@@ -25,11 +25,11 @@                                , stopb = One                                , parity = NoParity                                , flowControl = NoFlowControl-                               , timeout = 5 {- 500ms -} }+                               , timeout = 50 {- 5000ms -} }     port <- openSerial fp s     is <- makeInputStream (produce port)     os <- makeOutputStream (consume port)-    initialize $ Con is os+    initialize $ Con is os (const $ return ())   where     produce port = do         b <- Port.recv port 8
src/System/Hardware/ELM327/Connection.hs view
@@ -1,9 +1,36 @@ {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE FlexibleContexts #-} -- | Basic interface for communication with the ELM327.-module System.Hardware.ELM327.Connection where+module System.Hardware.ELM327.Connection (+  -- * Basic types+  Con(..)+, ConT(..)+, withCon+, ConError(..) +  -- * Interacting with connections+, close+, close'+, send+, sendBytes+, sendString+, recvRaw+, recv+, flushOutputStream++  -- * Sending commands+, at+, obd++  -- * Logging+, fileLog+)+where++import Prelude hiding (log)+ import Control.Lens (re, (^.), (^?))+import Control.Monad (void) import Control.Monad.Except (ExceptT, MonadError, runExceptT, throwError) import Control.Monad.IO.Class (MonadIO, liftIO) import Control.Monad.Reader (ReaderT, MonadReader, runReaderT, ask)@@ -15,6 +42,7 @@ import Data.Word (Word8) import qualified Data.ByteString.Char8 as Char8 +import System.IO (openFile, IOMode(..), hPutStrLn, hFlush, hClose) import System.IO.Streams (InputStream, OutputStream) import qualified System.IO.Streams as Streams @@ -31,8 +59,10 @@ import System.Hardware.ELM327.Utils.Monad (maybeToExcept, orThrow)  -- | A connection to an ELM327 device that can be closed.-data Con = Con { conInput :: InputStream ByteString-               , conOutput :: OutputStream ByteString }+data Con = Con { conInput :: InputStream ByteString   -- ^ Input stream of the connection+               , conOutput :: OutputStream ByteString -- ^ Output stream of the connection+               , conLog :: Maybe ByteString -> IO ()  -- ^ Function that will be called with every byte sent or received, 'Nothing' indicates connection closed.+               }  -- | Monad transformer for connection operations. newtype ConT m a = ConT { runConT :: ReaderT Con (ExceptT ConError m) a }@@ -51,9 +81,12 @@ close :: MonadIO m => ConT m () close = ask >>= close' + -- | Close the connection close' :: MonadIO m => Con -> m ()-close' =  liftIO . Streams.write Nothing . conOutput+close' c = do+    liftIO . Streams.write Nothing . conOutput $ c+    liftIO $ conLog c Nothing  -- | Send an ELM327 command. send :: MonadIO m => Command -> ConT m ()@@ -64,7 +97,7 @@  -- | Send all bytes to the ELM327. sendBytes :: MonadIO m => ByteString -> ConT m ()-sendBytes x = ask >>= liftIO . Streams.write (Just x) . conOutput+sendBytes x = ask >>= liftIO . Streams.write (Just x) . conOutput >> void (log $ Just x)  -- | Send a string to the ELM327. sendString :: MonadIO m => String -> ConT m ()@@ -72,7 +105,7 @@  -- | Receive available ELM327 caracters as a byte string recvRaw :: MonadIO m => ConT m (Maybe ByteString)-recvRaw = ask >>= liftIO . Streams.read . conInput+recvRaw = ask >>= liftIO . Streams.read . conInput >>= log  -- | Receive an ELM327 response as a byte string. recv :: MonadIO m => ConT m (Maybe ByteString)@@ -81,7 +114,7 @@     if Char8.null s then return Nothing else return (Just s)   where     recv' xs = do-        bs <- ask >>= liftIO . Streams.read . conInput+        bs <- ask >>= liftIO . Streams.read . conInput >>= log         case bs of Nothing -> throwError ConTimeoutError                    Just bs' -> handle' xs bs'     handle' xs bs =@@ -118,3 +151,21 @@     removeStatusPrefixes x = foldl stripPrefix' x statusPrefixes     stripPrefix' x pref = fromMaybe x (stripPrefix pref x)     stripHeader = stripPrefix [0x40 + obdMode cmd, obdPID cmd]++-- | Log sent or received bytes+log :: MonadIO m => Maybe ByteString -> ConT m (Maybe ByteString)+log Nothing = return Nothing+log (Just x) = do+    log' <- conLog <$> ask+    liftIO $ log' (Just x)+    return $ Just x++-- | Create a file logger that can be used with 'conLog'.+fileLog :: FilePath -> IO (Maybe ByteString -> IO ())+fileLog fp = do+    fh <- openFile fp AppendMode+    hPutStrLn fh "Connecting..."+    return $ log' fh+  where+    log' fh Nothing = hClose fh+    log' fh (Just x) = Char8.hPut fh x >> hFlush fh
src/System/Hardware/ELM327/Simulator.hs view
@@ -83,7 +83,7 @@     is <- makeInputStream (produce c)     os <- makeOutputStream (consume c)     _ <- forkIO . void $ runStateT (runSimulator c) s-    return $ Con is os+    return $ Con is os (const $ return ())   where     produce = atomically . readTMChan . _conOutputBuffer     consume c Nothing = atomically $ closeTMChan (_conInputBuffer c)