diff --git a/bench/Bench.hs b/bench/Bench.hs
deleted file mode 100644
--- a/bench/Bench.hs
+++ /dev/null
@@ -1,7 +0,0 @@
-import BasicPrelude
-import Criterion.Main
-
-main :: IO ()
-main = defaultMain
-  [
-  ]
diff --git a/gnss-converters.cabal b/gnss-converters.cabal
--- a/gnss-converters.cabal
+++ b/gnss-converters.cabal
@@ -1,5 +1,5 @@
 name:                  gnss-converters
-version:               0.1.11
+version:               0.1.12
 synopsis:              GNSS Converters.
 description:           Haskell bindings for GNSS converters.
 homepage:              http://github.com/swift-nav/gnss-converters
@@ -18,16 +18,22 @@
 library
   hs-source-dirs:      src
   exposed-modules:     Data.RTCM3.SBP
+                     , Data.RTCM3.SBP.Types
                      , SwiftNav.SBP.RTCM3
   ghc-options:         -Wall
   build-depends:       base >= 4.7 && < 5
                      , basic-prelude
                      , conduit-extra
+                     , exceptions
                      , extra
                      , lens
+                     , monad-control
+                     , mtl
+                     , resourcet
                      , rtcm
                      , sbp
                      , time
+                     , transformers-base
                      , unordered-containers
   default-language:    Haskell2010
   default-extensions:  NoImplicitPrelude
@@ -64,32 +70,20 @@
   hs-source-dirs:      test
   main-is:             Test.hs
   other-modules:       Test.Data.RTCM3.SBP
-  build-depends:       base
+  build-depends:       HUnit-approx
+                     , base
                      , basic-prelude
                      , binary-conduit
                      , bytestring
                      , conduit
                      , conduit-extra
                      , gnss-converters
-                     , HUnit-approx
                      , lens
                      , resourcet
                      , sbp
                      , tasty
                      , tasty-hunit
                      , unordered-containers
-  ghc-options:         -threaded -rtsopts -with-rtsopts=-N -Wall
-  default-language:    Haskell2010
-  default-extensions:  NoImplicitPrelude
-
-benchmark bench
-  type:                exitcode-stdio-1.0
-  hs-source-dirs:      bench
-  main-is:             Bench.hs
-  build-depends:       base
-                     , basic-prelude
-                     , criterion
-                     , gnss-converters
   ghc-options:         -threaded -rtsopts -with-rtsopts=-N -Wall
   default-language:    Haskell2010
   default-extensions:  NoImplicitPrelude
diff --git a/main/RTCM32SBP.hs b/main/RTCM32SBP.hs
--- a/main/RTCM32SBP.hs
+++ b/main/RTCM32SBP.hs
@@ -8,20 +8,22 @@
 --
 -- RTCM3 to SBP tool.
 
-import BasicPrelude
-import Control.Monad.Trans.Resource
-import Data.Conduit
-import Data.Conduit.Binary
-import qualified Data.Conduit.List as CL
-import Data.Conduit.Serialization.Binary
-import Data.RTCM3.SBP
-import System.IO
+import           BasicPrelude
+import           Control.Monad.Trans.Resource
+import           Data.Conduit
+import           Data.Conduit.Binary
+import qualified Data.Conduit.List                 as CL
+import           Data.Conduit.Serialization.Binary
+import           Data.RTCM3.SBP
+import           Data.RTCM3.SBP.Types
+import           System.IO
 
 main :: IO ()
-main = runResourceT $
-  sourceHandle stdin   =$=
-  conduitDecode        =$=
-  CL.mapMaybeM convert =$=
-  CL.concat            =$=
-  conduitEncode        $$
-  sinkHandle stdout
+main = do
+  s <- liftIO $ newStore
+  runResourceT $ runConvertT s $
+    sourceHandle stdin    =$=
+    conduitDecode         =$=
+    CL.concatMapM convert =$=
+    conduitEncode         $$
+    sinkHandle stdout
diff --git a/src/Data/RTCM3/SBP.hs b/src/Data/RTCM3/SBP.hs
--- a/src/Data/RTCM3/SBP.hs
+++ b/src/Data/RTCM3/SBP.hs
@@ -12,15 +12,17 @@
 
 module Data.RTCM3.SBP where
 
-import BasicPrelude
-import Control.Lens
-import Data.Bits
-import qualified Data.HashMap.Strict as H
-import Data.List.Extra hiding (concat, map)
-import Data.Time
-import Data.Word
-import Data.RTCM3
-import SwiftNav.SBP
+import           BasicPrelude
+import           Control.Lens
+import           Data.Bits
+import qualified Data.HashMap.Strict  as M
+import           Data.IORef
+import           Data.List.Extra      hiding (concat, map)
+import           Data.RTCM3
+import           Data.RTCM3.SBP.Types
+import           Data.Time
+import           Data.Word
+import           SwiftNav.SBP
 
 
 --------------------------------------------------------------------------------
@@ -104,17 +106,20 @@
 
 -- | Map L2 codes to SBP GnssSignal codes
 --
-l2codeToSBPSignalCode :: H.HashMap Word8 Word8
-l2codeToSBPSignalCode = H.fromList [(0, l2CMSidCode), (1, l2PSidCode)]
+l2codeToSBPSignalCode :: HashMap Word8 Word8
+l2codeToSBPSignalCode = M.fromList
+  [ (codeIndicator_L2C,  l2CMSidCode)
+  , (codeIndicator_L2PD, l2PSidCode)
+  ]
 
 -- | Maximum number of packed observations to allow in a single SBP message.
 --
 maxObsPerMessage :: Int
-maxObsPerMessage = floor $ (maxPayloadSize - headerSize) / packedObsSize
+maxObsPerMessage = (maxPayloadSize - headerSize) `div` packedObsSize
   where
     maxPayloadSize = 255
     headerSize     = 7
-    packedObsSize  = 16.0
+    packedObsSize  = 16
 
 
 --------------------------------------------------------------------------------
@@ -124,12 +129,12 @@
 fromEcefVal :: Int64 -> Double
 fromEcefVal x = fromIntegral x / 10000
 
-toGPSTime :: MonadIO m => GpsObservationHeader -> m ObsGPSTime
+toGPSTime :: MonadStore e m => GpsObservationHeader -> m ObsGPSTime
 toGPSTime hdr = do
-  today <- utctDay <$> liftIO getCurrentTime
+  wn <- view storeWn >>= liftIO . readIORef
   return ObsGPSTime
     { _obsGPSTime_tow = hdr ^. gpsObservationHeader_tow
-    , _obsGPSTime_wn  = fromIntegral $ div (diffDays today (fromGregorian 1980 1 6)) 7
+    , _obsGPSTime_wn  = wn
     }
 
 -- | Construct metric pseudorange (meters!) from L1 RTCM observation.
@@ -169,7 +174,7 @@
     lm = p + phaseRangeRes * fromIntegral (l1 ^. gpsL1Observation_carrierMinusCode)
     l = lm / (lightSpeedMS / l1frequency)
     li :: Int32
-    li = floor (l)
+    li = floor l
     lf :: Word8
     lf = truncate ((l - fromIntegral li) * q32Width)
 
@@ -181,7 +186,7 @@
        -> GpsL2Observation
        -> GpsL2ExtObservation
        -> CarrierPhase
-toL_L2 l1 l1e l2 l2e = CarrierPhase
+toL_L2 l1 l1e l2 _l2e = CarrierPhase
   { _carrierPhase_i = fromIntegral li
   , _carrierPhase_f = fromIntegral lf
   } where
@@ -192,7 +197,7 @@
     lm = p + phaseRangeRes * fromIntegral (l2 ^. gpsL2Observation_carrierMinusCode)
     l = lm / (lightSpeedMS / l2frequency)
     li :: Int32
-    li = floor (l)
+    li = floor l
     lf :: Word8
     lf = truncate ((l - fromIntegral li) * q32Width)
 
@@ -210,7 +215,7 @@
 
 -- | Construct sequenced SBP observation header
 --
-fromGpsObservationHeader :: MonadIO m
+fromGpsObservationHeader :: MonadStore e m
                          => Word8                -- ^ Total messages
                          -> Word8                -- ^ Message in sequence
                          -> GpsObservationHeader -- ^ RTCM observation header
@@ -234,41 +239,52 @@
 fromL1SatelliteObservation sat l1 l1e =
   -- Checks GPS L1 code indicator for RTCM message 1002.
   -- See DF016, pg. 3-17 of the RTCM3 spec.
-  if l1 ^. gpsL1Observation_code then
-    PackedObsContent
-      { _packedObsContent_P    = toP_L1 l1 l1e
-      , _packedObsContent_L    = toL_L1 l1 l1e
-      , _packedObsContent_cn0  = toCn0_L1 l1e
-      , _packedObsContent_lock = toLock_L1 l1
-      , _packedObsContent_sid  = GnssSignal
-        { _gnssSignal_sat      = fromIntegral $ sat - 1
-        , _gnssSignal_code     = l1PSidCode
-        , _gnssSignal_reserved = 0
-        }
+  PackedObsContent
+    { _packedObsContent_P    = toP_L1 l1 l1e
+    , _packedObsContent_L    = toL_L1 l1 l1e
+    , _packedObsContent_cn0  = toCn0_L1 l1e
+    , _packedObsContent_lock = toLock_L1 l1
+    , _packedObsContent_sid  = GnssSignal
+      { _gnssSignal_sat      = fromIntegral $ sat - 1
+      , _gnssSignal_code     = if l1 ^. gpsL1Observation_code then l1PSidCode else l1CSidCode
+      , _gnssSignal_reserved = 0
       }
-  else
-    PackedObsContent
-      { _packedObsContent_P    = toP_L1 l1 l1e
-      , _packedObsContent_L    = toL_L1 l1 l1e
-      , _packedObsContent_cn0  = toCn0_L1 l1e
-      , _packedObsContent_lock = toLock_L1 l1
-      , _packedObsContent_sid  = GnssSignal
-        { _gnssSignal_sat      = fromIntegral $ sat - 1
-        , _gnssSignal_code     = l1CSidCode
-        , _gnssSignal_reserved = 0
-        }
+    }
+
+-- | Construct an L2 SBP PackedObsContent an RTCM satellite vehicle observation
+--
+fromL2SatelliteObservation :: Word8                  -- ^ Satellite PRN
+                           -> GpsL1Observation
+                           -> GpsL1ExtObservation
+                           -> GpsL2Observation
+                           -> GpsL2ExtObservation
+                           -> Maybe PackedObsContent
+fromL2SatelliteObservation sat l1 l1e l2 l2e = do
+  -- Checks GPS L2 code indicator.
+  -- See DF016, pg. 3-17 of the RTCM3 spec.
+  code <- M.lookup (l2 ^. gpsL2Observation_code) l2codeToSBPSignalCode
+  return PackedObsContent
+    { _packedObsContent_P    = toP_L2 l1 l1e l2
+    , _packedObsContent_L    = toL_L2 l1 l1e l2 l2e
+    , _packedObsContent_cn0  = toCn0_L2 l2e
+    , _packedObsContent_lock = toLock_L2 l2
+    , _packedObsContent_sid  = GnssSignal
+      { _gnssSignal_sat      = fromIntegral $ sat - 1
+      , _gnssSignal_code     = code
+      , _gnssSignal_reserved = 0
       }
+    }
 
 -- | Construct SBP GPS observation message (possibly chunked).
 --
-chunkToMsgObs :: MonadIO m
-              => Msg1004            -- ^ RTCM 1004 observation message
-              -> Word8              -- ^ Total messages
-              -> Word8              -- ^ Message in sequence
+chunkToMsgObs :: MonadStore e m
+              => GpsObservationHeader -- ^ RTCM observation header
+              -> Word8                -- ^ Total messages
+              -> Word8                -- ^ Message in sequence
               -> [PackedObsContent]
               -> m MsgObs
-chunkToMsgObs m totalMsgs n packed = do
-  header <- fromGpsObservationHeader totalMsgs n $ m ^. msg1004_header
+chunkToMsgObs hdr totalMsgs n packed = do
+  header <- fromGpsObservationHeader totalMsgs n hdr
   return MsgObs
     { _msgObs_header = header
     , _msgObs_obs    = packed
@@ -287,72 +303,63 @@
 
 -- | Construct an L1 SBP PackedObsContent from an RTCM Msg 1002.
 --
-fromObservation1002 :: Observation1002 -> Maybe PackedObsContent
+fromObservation1002 :: Observation1002 -> [PackedObsContent]
 fromObservation1002 obs =
   -- Only lower set of PRN numbers (1-32) are supported
-  if sat > maxSats then Nothing else Just (fromL1SatelliteObservation sat l1 l1e)
+  if sat > maxSats then mempty else [fromL1SatelliteObservation sat l1 l1e]
     where
       sat = obs ^. observation1002_sat
       l1  = obs ^. observation1002_l1
       l1e = obs ^. observation1002_l1e
 
+
 -- | Convert an RTCM L1 1002 observation into an SBP MsgObs.
 --
-fromMsg1002 :: MonadIO m => Msg1002 -> m MsgObs
+-- This chunking takes places because the number of observations in a given 1002
+-- may very well exceed the maximum SBP supported payload size of 255 bytes.
+fromMsg1002 :: MonadStore e m => Msg1002 -> m [MsgObs]
 fromMsg1002 m = do
-  header <- fromGpsObservationHeader 1 0 (m ^. msg1002_header)
-  return MsgObs
-    { _msgObs_header = header
-    , _msgObs_obs    = mapMaybe fromObservation1002 $ m ^. msg1002_observations
-    }
+  let hdr       = m ^. msg1002_header
+      obs       = concatMap fromObservation1002 $ m ^. msg1002_observations
+      chunks    = zip [0..] $ chunksOf maxObsPerMessage obs
+      totalMsgs = fromIntegral $ length chunks
+  forM chunks $ uncurry $ chunkToMsgObs hdr totalMsgs
 
 -- | Construct an L1/L2 SBP PackedObsContent from an RTCM Msg 1004.
 --
-fromObservation1004 :: Observation1004 -> Maybe [PackedObsContent]
+fromObservation1004 :: Observation1004 -> [PackedObsContent]
 fromObservation1004 obs =
   -- Only lower set of PRN numbers (1-32) are supported
-  if sat > maxSats then Nothing else mapM id [obs1, obs2]
+  if sat > maxSats then mempty else
+    maybe [obs1] (: [obs1]) obs2
     where
       sat = obs ^. observation1004_sat
       l1  = obs ^. observation1004_l1
       l1e = obs ^. observation1004_l1e
       -- Checks GPS L1 code indicator for RTCM message 1004
       -- See DF016, pg. 3-17 of the RTCM3 spec.
-      obs1 = Just (fromL1SatelliteObservation sat l1 l1e)
+      obs1 = fromL1SatelliteObservation sat l1 l1e
       l2   = obs ^. observation1004_l2
       l2e  = obs ^. observation1004_l2e
-      code = l2 ^. gpsL2Observation_code
       -- Checks GPS L2 code indicator.
       -- See DF016, pg. 3-17 of the RTCM3 spec.
-      obs2 = if H.member code l2codeToSBPSignalCode then
-               Just PackedObsContent
-                 { _packedObsContent_P    = toP_L2 l1 l1e l2
-                 , _packedObsContent_L    = toL_L2 l1 l1e l2 l2e
-                 , _packedObsContent_cn0  = toCn0_L2 l2e
-                 , _packedObsContent_lock = toLock_L2 l2
-                 , _packedObsContent_sid  = GnssSignal
-                   { _gnssSignal_sat      = fromIntegral $ sat - 1
-                   , _gnssSignal_code     = l2codeToSBPSignalCode H.! code
-                   , _gnssSignal_reserved = 0
-                   }
-                 }
-             else
-               Nothing
+      obs2 = fromL2SatelliteObservation sat l1 l1e l2 l2e
 
 -- | Convert an RTCM L1+L2 1004 observation into multiple SBP MsgObs.
 --
 -- This chunking takes places because the number of observations in a given 1004
 -- may very well exceed the maximum SBP supported payload size of 255 bytes.
-fromMsg1004 :: MonadIO m => Msg1004 -> m [MsgObs]
+fromMsg1004 :: MonadStore e m => Msg1004 -> m [MsgObs]
 fromMsg1004 m = do
-  let obs       = concat $ mapMaybe fromObservation1004 $ m ^. msg1004_observations
+  let hdr       = m ^. msg1004_header
+      obs       = concatMap fromObservation1004 $ m ^. msg1004_observations
       chunks    = zip [0..] $ chunksOf maxObsPerMessage obs
       totalMsgs = fromIntegral $ length chunks
-  mapM (\(n, packed) -> chunkToMsgObs m totalMsgs n packed) chunks
+  forM chunks $ uncurry $ chunkToMsgObs hdr totalMsgs
 
 -- | Convert an RTCM 1005 antenna reference position message into an SBP
 -- MsgBasePosEcef.
-fromMsg1005 :: MonadIO m => Msg1005 -> m MsgBasePosEcef
+fromMsg1005 :: MonadStore e m => Msg1005 -> m MsgBasePosEcef
 fromMsg1005 m =
   return MsgBasePosEcef
     { _msgBasePosEcef_x = fromEcefVal $ m ^. msg1005_reference ^. antennaReference_ecef_x
@@ -362,7 +369,7 @@
 
 -- | Convert an RTCM 1006 antenna reference position message into an SBP
 -- MsgBasePosEcef.
-fromMsg1006 :: MonadIO m => Msg1006 -> m MsgBasePosEcef
+fromMsg1006 :: MonadStore e m => Msg1006 -> m MsgBasePosEcef
 fromMsg1006 m =
   return MsgBasePosEcef
     { _msgBasePosEcef_x = fromEcefVal $ m ^. msg1006_reference ^. antennaReference_ecef_x
@@ -372,22 +379,29 @@
 
 -- | Convert an RTCM message into possibly multiple SBP messages.
 --
-convert :: MonadIO m => RTCM3Msg -> m (Maybe [SBPMsg])
+convert :: MonadStore e m => RTCM3Msg -> m [SBPMsg]
 convert = \case
   (RTCM3Msg1002 m _rtcm3) -> do
     let sender = m ^. msg1002_header ^. gpsObservationHeader_station
     m' <- fromMsg1002 m
-    return $ Just [SBPMsgObs m' $ toSBP m' $ toSender sender]
+    return $ flip fmap m' $ \x -> SBPMsgObs x $ toSBP x $ toSender sender
   (RTCM3Msg1004 m _rtcm3) -> do
     let sender = m ^. msg1004_header ^. gpsObservationHeader_station
     m' <- fromMsg1004 m
-    return $ Just (fmap (\x -> SBPMsgObs x $ toSBP x $ toSender sender) m')
+    return $ flip fmap m' $ \x -> SBPMsgObs x $ toSBP x $ toSender sender
   (RTCM3Msg1005 m _rtcm3) -> do
     let sender =  m ^. msg1005_reference ^. antennaReference_station
     m' <- fromMsg1005 m
-    return $ Just [SBPMsgBasePosEcef m' $ toSBP m' $ toSender sender]
+    return [SBPMsgBasePosEcef m' $ toSBP m' $ toSender sender]
   (RTCM3Msg1006 m _rtcm3) -> do
     let sender = m ^. msg1006_reference ^. antennaReference_station
     m' <- fromMsg1006 m
-    return $ Just [SBPMsgBasePosEcef m' $ toSBP m' $ toSender sender]
-  _rtcm3Msg -> return Nothing
+    return [SBPMsgBasePosEcef m' $ toSBP m' $ toSender sender]
+  _rtcm3Msg -> return mempty
+
+newStore :: IO Store
+newStore = do
+  day <- utctDay <$> getCurrentTime
+  let wn = fromIntegral $ div (diffDays day (fromGregorian 1980 1 6)) 7
+  Store <$> newIORef wn
+
diff --git a/src/Data/RTCM3/SBP/Types.hs b/src/Data/RTCM3/SBP/Types.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/RTCM3/SBP/Types.hs
@@ -0,0 +1,74 @@
+{-# LANGUAGE ConstraintKinds            #-}
+{-# LANGUAGE FlexibleInstances          #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE MultiParamTypeClasses      #-}
+{-# LANGUAGE TemplateHaskell            #-}
+{-# LANGUAGE TypeFamilies               #-}
+{-# LANGUAGE UndecidableInstances       #-}
+
+-- |
+-- Module:      Data.RTCM3.SBP.Types
+-- Copyright:   Copyright (C) 2015 Swift Navigation, Inc.
+-- License:     LGPL-3
+-- Maintainer:  Mark Fine <dev@swiftnav.com>
+-- Stability:   experimental
+-- Portability: portable
+--
+-- Types for RTCMv3 to SBP Conversions.
+
+module Data.RTCM3.SBP.Types where
+
+import BasicPrelude
+import Control.Lens
+import Control.Monad.Base
+import Control.Monad.Catch
+import Control.Monad.Reader
+import Control.Monad.Trans.Control
+import Control.Monad.Trans.Resource
+import Data.IORef
+import Data.Word
+
+newtype ConvertT e m a = ConvertT { unConvertT :: ReaderT e m a }
+  deriving
+    ( Functor
+    , Applicative
+    , Monad
+    , MonadIO
+    , MonadTrans
+    )
+
+instance MonadThrow m => MonadThrow (ConvertT r m) where
+    throwM = lift . throwM
+
+instance MonadResource m => MonadResource (ConvertT r m) where
+  liftResourceT = lift . liftResourceT
+
+instance Monad m => MonadReader e (ConvertT e m) where
+    ask     = ConvertT ask
+    local f = ConvertT . local f . unConvertT
+    reader  = ConvertT . reader
+
+instance MonadTransControl (ConvertT r) where
+    type StT (ConvertT r) a = StT (ReaderT r) a
+
+    liftWith = defaultLiftWith ConvertT unConvertT
+    restoreT = defaultRestoreT ConvertT
+
+instance MonadBase b m => MonadBase b (ConvertT r m) where
+    liftBase = liftBaseDefault
+
+data Store = Store
+  { _storeWn :: IORef Word16
+  } deriving ( Eq )
+
+$(makeClassy ''Store)
+
+runConvertT :: HasStore e => e -> ConvertT e m a -> m a
+runConvertT e (ConvertT m) = runReaderT m e
+
+type MonadStore e m =
+  ( MonadIO m
+  , MonadReader e m
+  , MonadThrow m
+  , HasStore e
+  )
diff --git a/src/SwiftNav/SBP/RTCM3.hs b/src/SwiftNav/SBP/RTCM3.hs
--- a/src/SwiftNav/SBP/RTCM3.hs
+++ b/src/SwiftNav/SBP/RTCM3.hs
@@ -31,10 +31,10 @@
 
 convert :: SBPMsg -> Maybe RTCM3Msg
 convert = \case
-  (SBPMsgObs msg _sbp) -> Just $
-    RTCM3Msg1002 msg' $ toRTCM3 msg' where
-      msg' = fromMsgObs msg
-  (SBPMsgBasePosEcef msg _sbp) -> Just $
-    RTCM3Msg1005 msg' $ toRTCM3 msg' where
-      msg' = fromMsgBasePosEcef msg
+  (SBPMsgObs m _sbp) -> Just $
+    RTCM3Msg1002 m' $ toRTCM3 m' where
+      m' = fromMsgObs m
+  (SBPMsgBasePosEcef m _sbp) -> Just $
+    RTCM3Msg1005 m' $ toRTCM3 m' where
+      m' = fromMsgBasePosEcef m
   _sbpMsg -> Nothing
diff --git a/test/Test.hs b/test/Test.hs
--- a/test/Test.hs
+++ b/test/Test.hs
@@ -1,6 +1,3 @@
-{-# LANGUAGE NoImplicitPrelude #-}
-{-# LANGUAGE OverloadedStrings #-}
-
 -- |
 -- Module:      Test
 -- Copyright:   (c) 2016 Swift Navigation Inc.
diff --git a/test/Test/Data/RTCM3/SBP.hs b/test/Test/Data/RTCM3/SBP.hs
--- a/test/Test/Data/RTCM3/SBP.hs
+++ b/test/Test/Data/RTCM3/SBP.hs
@@ -1,8 +1,4 @@
-{-# LANGUAGE FlexibleContexts    #-}
-{-# LANGUAGE LambdaCase          #-}
-{-# LANGUAGE NoImplicitPrelude   #-}
-{-# LANGUAGE OverloadedStrings   #-}
-{-# LANGUAGE RecordWildCards     #-}
+{-# LANGUAGE FlexibleContexts #-}
 
 -- |
 -- Module:      Test.Data.RTCM3.SBP
@@ -16,30 +12,30 @@
   ( tests
   ) where
 
-import BasicPrelude
-import Control.Lens
-import Control.Monad.Trans.Resource
-import Data.Conduit
-import Data.Conduit.Binary
-import Data.Conduit.Serialization.Binary
-import Data.HashMap.Strict
-import Data.RTCM3.SBP
-import qualified Data.Conduit.List as CL
-import Data.Word
-import SwiftNav.SBP
-import Test.HUnit.Approx
-import Test.Tasty
-import Test.Tasty.HUnit
+import           BasicPrelude
+import           Control.Lens
+import           Control.Monad.Trans.Resource
+import           Data.Conduit
+import           Data.Conduit.Binary
+import qualified Data.Conduit.List                 as CL
+import           Data.Conduit.Serialization.Binary
+import           Data.HashMap.Strict
+import           Data.IORef
+import           Data.RTCM3.SBP
+import           Data.RTCM3.SBP.Types
+import           Data.Word
+import           SwiftNav.SBP
+import           Test.HUnit.Approx
+import           Test.Tasty
+import           Test.Tasty.HUnit
 
-decodeRTCMFile :: (MonadIO m, MonadBaseControl IO m, MonadThrow m)
-               => FilePath
-               -> m [SBPMsg]
-decodeRTCMFile filename =
-  runResourceT . runConduit  $
-    sourceFile filename     =$=
-    conduitDecode           =$=
-    CL.mapMaybeM convert    =$=
-    CL.concat               $$
+decodeRTCMFile :: FilePath -> IO [SBPMsg]
+decodeRTCMFile filename = do
+  wn <- liftIO $ newIORef 1906
+  runResourceT $ runConvertT (Store wn) $ runConduit  $
+    sourceFile filename   =$=
+    conduitDecode         =$=
+    CL.concatMapM convert $$
     CL.consume
 
 basePosition :: MsgBasePosEcef -> (Double, Double, Double)
@@ -160,39 +156,39 @@
         assertExpectedBase (msgs !! 5) expectedBasePos
         -- Message 1
         assertObsHeader (msgs !! 1) ObservationHeader {
-            _observationHeader_t     = ObsGPSTime 86354000 1905
+            _observationHeader_t     = ObsGPSTime 86354000 1906
           , _observationHeader_n_obs = 32
           }
         assertMsgObsLength (msgs !! 1) 15
         assertMsgObs (msgs !! 1)
         -- Message 2
         assertObsHeader (msgs !! 2) ObservationHeader {
-            _observationHeader_t     = ObsGPSTime 86354000 1905
+            _observationHeader_t     = ObsGPSTime 86354000 1906
           , _observationHeader_n_obs = 33
           }
         assertMsgObs (msgs !! 2)
         assertMsgObsLength (msgs !! 2) 1
         -- Message 3
         assertObsHeader (msgs !! 3) ObservationHeader {
-            _observationHeader_t     = ObsGPSTime 86355000 1905
+            _observationHeader_t     = ObsGPSTime 86355000 1906
           , _observationHeader_n_obs = 32
           }
         assertMsgObsLength (msgs !! 3) 15
         -- Message 4
         assertObsHeader (msgs !! 4) ObservationHeader {
-            _observationHeader_t     = ObsGPSTime 86355000 1905
+            _observationHeader_t     = ObsGPSTime 86355000 1906
           , _observationHeader_n_obs = 33
           }
         assertMsgObsLength (msgs !! 4) 1
         -- Message 6
         assertObsHeader (msgs !! 6) ObservationHeader {
-            _observationHeader_t     = ObsGPSTime 86356000 1905
+            _observationHeader_t     = ObsGPSTime 86356000 1906
           , _observationHeader_n_obs = 32
           }
         assertMsgObsLength (msgs !! 6) 15
         -- Message 7
         assertObsHeader (msgs !! 7) ObservationHeader {
-            _observationHeader_t     = ObsGPSTime 86356000 1905
+            _observationHeader_t     = ObsGPSTime 86356000 1906
           , _observationHeader_n_obs = 33
           }
         assertMsgObsLength (msgs !! 7) 1
