diff --git a/ReadMe.md b/ReadMe.md
--- a/ReadMe.md
+++ b/ReadMe.md
@@ -7,8 +7,9 @@
 Clients
 -------
 
-The simple Kafka client that produces events from the joystick can be run, for example, as follows:
+The simple Kafka client that produces events from the joystick can be run, for example, as one of the following:
 
 	cabal run kafka-device-joystick -- /dev/input/js0 joystick-client localhost 9092 events joystick
+	cabal run kafka-device-joystick -- sample.yaml
 
 Also see https://hackage.haskell.org/package/kafka-device/.
diff --git a/kafka-device-joystick.cabal b/kafka-device-joystick.cabal
--- a/kafka-device-joystick.cabal
+++ b/kafka-device-joystick.cabal
@@ -1,12 +1,12 @@
 name:                kafka-device-joystick
-version:             0.1.5.0
+version:             0.2.1.0
 synopsis:            Linux joystick events via a Kafka message broker
 description:         This package contains functions for passing Linux joystick events to topics on a Kafka message broker \<<https://kafka.apache.org/>\>.  The joystick's driver must conform to the Linux Joystick API \<<https://www.kernel.org/doc/Documentation/input/joystick-api.txt>\>.  Also see \<<https://hackage.haskell.org/package/kafka-device/>\>.
 license:             MIT
 license-file:        LICENSE
 author:              Brian W Bush <consult@brianwbush.info>
 maintainer:          Brian W Bush <consult@brianwbush.info>
-copyright:           (c) 2016 Brian W Bush
+copyright:           (c) 2016-17 Brian W Bush
 category:            Hardware
 build-type:          Simple
 cabal-version:       >= 1.10
@@ -23,6 +23,7 @@
  
 library
   exposed-modules:  Network.UI.Kafka.Joystick
+                    Network.UI.Kafka.Joystick.Interpretation
                     System.Hardware.Linux.Joystick
   build-depends:    base         >= 4.8 && < 5
                ,    aeson
@@ -32,7 +33,7 @@
                ,    kafka-device
                ,    milena
   hs-source-dirs:   src
-  ghc-options:      -Wall
+  ghc-options:      -O2 -Wall
   default-language: Haskell2010
 
 executable kafka-device-joystick
@@ -44,6 +45,7 @@
                ,    cereal
                ,    kafka-device
                ,    milena
+               ,    yaml
   hs-source-dirs:   src
-  ghc-options:      -Wall
+  ghc-options:      -O2 -Wall -threaded
   default-language: Haskell2010
diff --git a/src/Main.hs b/src/Main.hs
--- a/src/Main.hs
+++ b/src/Main.hs
@@ -1,6 +1,6 @@
 {-|
-Module      :  Main
-Copyright   :  (c) 2016 Brian W Bush
+Module      :  $Header$
+Copyright   :  (c) 2016-17 Brian W Bush
 License     :  MIT
 Maintainer  :  Brian W Bush <consult@brianwbush.info>
 Stability   :  Experimental
@@ -16,11 +16,14 @@
 ) where
 
 
-import Data.String (IsString(fromString))
-import Network.UI.Kafka.Joystick (joystickLoop)
+import Data.Yaml.Config (loadYamlSettingsArgs, useEnv)
+import Network.UI.Kafka (TopicConnection(TopicConnection))
 import System.Environment (getArgs)
 
+import qualified Network.UI.Kafka.Joystick as Raw (joystickLoop)
+import qualified Network.UI.Kafka.Joystick.Interpretation as Interpreted (joystickLoop)
 
+
 -- The main action.
 main :: IO ()
 main =
@@ -35,12 +38,19 @@
           putStrLn $ "Kafka topic:   " ++ topic
           putStrLn $ "Sensor name:   " ++ sensor
           (_, loop) <-
-            joystickLoop
+            Raw.joystickLoop
               device
-              (fromString client)
-              (fromString host, toEnum $ read port)
-              (fromString topic)
+              (TopicConnection client (host, read port) topic)
               sensor
           result <- loop
           either print return result
-      _ -> putStrLn "USAGE: kafka-device-joystick device client host port topic sensor"
+      [_] ->
+        do
+          interpretation <- loadYamlSettingsArgs [] useEnv
+          (_, loop) <- Interpreted.joystickLoop interpretation
+          either print return =<< loop
+      _ ->
+        do
+          putStrLn "USAGE: kafka-device-joystick device client host port topic sensor"
+          putStrLn "or"
+          putStrLn "USAGE: kafka-device-joystick interpretation.yaml"
diff --git a/src/Network/UI/Kafka/Joystick.hs b/src/Network/UI/Kafka/Joystick.hs
--- a/src/Network/UI/Kafka/Joystick.hs
+++ b/src/Network/UI/Kafka/Joystick.hs
@@ -1,6 +1,6 @@
 {-|
-Module      :  Network.UI.Kafka.Joystick
-Copyright   :  (c) 2016 Brian W Bush
+Module      :  $Header$
+Copyright   :  (c) 2016-17 Brian W Bush
 License     :  MIT
 Maintainer  :  Brian W Bush <consult@brianwbush.info>
 Stability   :  Experimental
@@ -22,9 +22,7 @@
 import Control.Monad (guard)
 import Data.ByteString.Lazy.Char8 (hGet)
 import Data.Maybe (catMaybes)
-import Network.Kafka (KafkaAddress, KafkaClientId)
-import Network.Kafka.Protocol (TopicName)
-import Network.UI.Kafka (ExitAction, LoopAction, Sensor, producerLoop)
+import Network.UI.Kafka (ExitAction, LoopAction, TopicConnection, Sensor, producerLoop)
 import Network.UI.Kafka.Types (Button(..), Event(..), Toggle(..))
 import System.Hardware.Linux.Joystick (Joystick(..), byteLength, interpretJoystick, maxValue)
 import System.IO (IOMode(ReadMode), hClose, openFile)
@@ -32,16 +30,14 @@
 
 -- | Produce events for a Kafka topic from a Linux Joystick.
 joystickLoop :: FilePath                    -- ^ The path to the joystick device, e.g. "\/dev\/input\/js0".
-             -> KafkaClientId               -- ^ A Kafka client identifier for the producer.
-             -> KafkaAddress                -- ^ The address of the Kafka broker.
-             -> TopicName                   -- ^ The Kafka topic name.
+             -> TopicConnection             -- ^ The Kafka topic name and connection information.
              -> Sensor                      -- ^ The name of the sensor producing events.
              -> IO (ExitAction, LoopAction) -- ^ Action to create the exit and loop actions.
-joystickLoop path client address topic sensor =
+joystickLoop path topicConnection sensor =
   do
     joystick <- openFile path ReadMode
     (exit, loop) <-
-      producerLoop client address topic sensor
+      producerLoop topicConnection sensor
         $ translate
         . interpretJoystick
         <$> hGet joystick byteLength
diff --git a/src/Network/UI/Kafka/Joystick/Interpretation.hs b/src/Network/UI/Kafka/Joystick/Interpretation.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/UI/Kafka/Joystick/Interpretation.hs
@@ -0,0 +1,49 @@
+{-|
+Module      :  $Header$
+Copyright   :  (c) 2016-17 Brian W Bush
+License     :  MIT
+Maintainer  :  Brian W Bush <consult@brianwbush.info>
+Stability   :  Experimental
+Portability :  Linux
+
+Produce interpreted events for a Kafka topic from a Linux joystick, which must conform to the Linux Joystick API \<<https://www.kernel.org/doc/Documentation/input/joystick-api.txt>\>.
+-}
+
+
+{-# LANGUAGE RecordWildCards #-}
+
+
+module Network.UI.Kafka.Joystick.Interpretation (
+-- * Event handling
+  joystickLoop
+) where
+
+
+import Data.ByteString.Lazy.Char8 (hGet)
+import Network.UI.Kafka (ExitAction, LoopAction)
+import Network.UI.Kafka.Interpretation (Interpretation(..), interpretationLoop)
+import System.Hardware.Linux.Joystick (Joystick(..), byteLength, interpretJoystick, maxValue)
+import System.IO (IOMode(ReadMode), hClose, openFile)
+
+
+-- | Interpret events from a Linux SpaceNav.
+joystickLoop :: Interpretation Double       -- ^ Instructions for interpretation.
+             -> IO (ExitAction, LoopAction) -- ^ Action to create the exit and loop actions.
+joystickLoop interpretation@TrackInterpretation{..} =
+  do
+    let
+      analogHandler (Joystick _ setting number False True  _) = Just (number, fromIntegral setting / fromIntegral maxValue)
+      analogHandler _                                         = Nothing
+      buttonHandler (Joystick _ pressed number True  False _) = Just (number, pressed /= 0)
+      buttonHandler _                                         = Nothing
+    joystick <- openFile path ReadMode
+    (exit, loop) <-
+      interpretationLoop analogHandler buttonHandler interpretation
+        $ interpretJoystick <$> hGet joystick byteLength
+    return
+      (
+        do
+          exit
+          hClose joystick
+      , loop
+      )
diff --git a/src/System/Hardware/Linux/Joystick.hs b/src/System/Hardware/Linux/Joystick.hs
--- a/src/System/Hardware/Linux/Joystick.hs
+++ b/src/System/Hardware/Linux/Joystick.hs
@@ -1,6 +1,6 @@
 {-|
-Module      :  System.Hardware.Linux.Joystick
-Copyright   :  (c) 2016 Brian W Bush
+Module      :  $Header$
+Copyright   :  (c) 2016-17 Brian W Bush
 License     :  MIT
 Maintainer  :  Brian W Bush <consult@brianwbush.info>
 Stability   :  Experimental
