kafka-device 0.2.1.0 → 0.2.1.2
raw patch · 2 files changed
+64/−50 lines, 2 filesdep ~aesondep ~binarydep ~bytestringPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependency ranges changed: aeson, binary, bytestring, cereal, linear, milena, mtl
API changes (from Hackage documentation)
- Network.UI.Kafka.Interpretation: [path] :: Interpretation a -> FilePath
- Network.UI.Kafka.Interpretation: instance Data.Aeson.Types.FromJSON.FromJSON a => Data.Aeson.Types.FromJSON.FromJSON (Network.UI.Kafka.Interpretation.Interpretation a)
- Network.UI.Kafka.Interpretation: instance Data.Aeson.Types.ToJSON.ToJSON a => Data.Aeson.Types.ToJSON.ToJSON (Network.UI.Kafka.Interpretation.Interpretation a)
- Network.UI.Kafka.Interpretation: instance GHC.Classes.Eq a => GHC.Classes.Eq (Network.UI.Kafka.Interpretation.Interpretation a)
- Network.UI.Kafka.Interpretation: instance GHC.Generics.Generic (Network.UI.Kafka.Interpretation.Interpretation a)
- Network.UI.Kafka.Interpretation: instance GHC.Read.Read a => GHC.Read.Read (Network.UI.Kafka.Interpretation.Interpretation a)
- Network.UI.Kafka.Interpretation: instance GHC.Show.Show a => GHC.Show.Show (Network.UI.Kafka.Interpretation.Interpretation a)
+ Network.UI.Kafka.Interpretation: [device] :: Interpretation a b -> a
+ Network.UI.Kafka.Interpretation: instance (Data.Aeson.Types.FromJSON.FromJSON a, Data.Aeson.Types.FromJSON.FromJSON b) => Data.Aeson.Types.FromJSON.FromJSON (Network.UI.Kafka.Interpretation.Interpretation a b)
+ Network.UI.Kafka.Interpretation: instance (Data.Aeson.Types.ToJSON.ToJSON a, Data.Aeson.Types.ToJSON.ToJSON b) => Data.Aeson.Types.ToJSON.ToJSON (Network.UI.Kafka.Interpretation.Interpretation a b)
+ Network.UI.Kafka.Interpretation: instance (GHC.Classes.Eq b, GHC.Classes.Eq a) => GHC.Classes.Eq (Network.UI.Kafka.Interpretation.Interpretation a b)
+ Network.UI.Kafka.Interpretation: instance (GHC.Read.Read b, GHC.Read.Read a) => GHC.Read.Read (Network.UI.Kafka.Interpretation.Interpretation a b)
+ Network.UI.Kafka.Interpretation: instance (GHC.Show.Show b, GHC.Show.Show a) => GHC.Show.Show (Network.UI.Kafka.Interpretation.Interpretation a b)
+ Network.UI.Kafka.Interpretation: instance GHC.Generics.Generic (Network.UI.Kafka.Interpretation.Interpretation a b)
- Network.UI.Kafka.Interpretation: TrackInterpretation :: TopicConnection -> Sensor -> FilePath -> AxisInterpretation a -> AxisInterpretation a -> AxisInterpretation a -> AxisInterpretation a -> AxisInterpretation a -> AxisInterpretation a -> V3 a -> V3 a -> Bool -> Maybe Int -> Interpretation a
+ Network.UI.Kafka.Interpretation: TrackInterpretation :: TopicConnection -> Sensor -> a -> AxisInterpretation b -> AxisInterpretation b -> AxisInterpretation b -> AxisInterpretation b -> AxisInterpretation b -> AxisInterpretation b -> V3 b -> V3 b -> Bool -> Maybe Int -> Interpretation a b
- Network.UI.Kafka.Interpretation: [flying] :: Interpretation a -> Bool
+ Network.UI.Kafka.Interpretation: [flying] :: Interpretation a b -> Bool
- Network.UI.Kafka.Interpretation: [kafka] :: Interpretation a -> TopicConnection
+ Network.UI.Kafka.Interpretation: [kafka] :: Interpretation a b -> TopicConnection
- Network.UI.Kafka.Interpretation: [location] :: Interpretation a -> V3 a
+ Network.UI.Kafka.Interpretation: [location] :: Interpretation a b -> V3 b
- Network.UI.Kafka.Interpretation: [orientation] :: Interpretation a -> V3 a
+ Network.UI.Kafka.Interpretation: [orientation] :: Interpretation a b -> V3 b
- Network.UI.Kafka.Interpretation: [phiAxis] :: Interpretation a -> AxisInterpretation a
+ Network.UI.Kafka.Interpretation: [phiAxis] :: Interpretation a b -> AxisInterpretation b
- Network.UI.Kafka.Interpretation: [psiAxis] :: Interpretation a -> AxisInterpretation a
+ Network.UI.Kafka.Interpretation: [psiAxis] :: Interpretation a b -> AxisInterpretation b
- Network.UI.Kafka.Interpretation: [resetButton] :: Interpretation a -> Maybe Int
+ Network.UI.Kafka.Interpretation: [resetButton] :: Interpretation a b -> Maybe Int
- Network.UI.Kafka.Interpretation: [sensor] :: Interpretation a -> Sensor
+ Network.UI.Kafka.Interpretation: [sensor] :: Interpretation a b -> Sensor
- Network.UI.Kafka.Interpretation: [thetaAxis] :: Interpretation a -> AxisInterpretation a
+ Network.UI.Kafka.Interpretation: [thetaAxis] :: Interpretation a b -> AxisInterpretation b
- Network.UI.Kafka.Interpretation: [xAxis] :: Interpretation a -> AxisInterpretation a
+ Network.UI.Kafka.Interpretation: [xAxis] :: Interpretation a b -> AxisInterpretation b
- Network.UI.Kafka.Interpretation: [yAxis] :: Interpretation a -> AxisInterpretation a
+ Network.UI.Kafka.Interpretation: [yAxis] :: Interpretation a b -> AxisInterpretation b
- Network.UI.Kafka.Interpretation: [zAxis] :: Interpretation a -> AxisInterpretation a
+ Network.UI.Kafka.Interpretation: [zAxis] :: Interpretation a b -> AxisInterpretation b
- Network.UI.Kafka.Interpretation: data Interpretation a
+ Network.UI.Kafka.Interpretation: data Interpretation a b
- Network.UI.Kafka.Interpretation: interpretationLoop :: (Conjugate a, Epsilon a, Num a, Ord a, RealFloat a) => AnalogHandler a b -> ButtonHandler a b -> Interpretation a -> IO b -> IO (ExitAction, LoopAction)
+ Network.UI.Kafka.Interpretation: interpretationLoop :: (Conjugate b, Epsilon b, Num b, Ord b, RealFloat b) => AnalogHandler b c -> ButtonHandler b c -> Interpretation a b -> IO c -> IO (ExitAction, LoopAction)
- Network.UI.Kafka.Interpretation: type AnalogHandler a b = b -> Maybe (Int, a)
+ Network.UI.Kafka.Interpretation: type AnalogHandler a b = b The raw event. -> Maybe (Int, a) The axis number and value.
- Network.UI.Kafka.Interpretation: type ButtonHandler a b = b -> Maybe (Int, Bool)
+ Network.UI.Kafka.Interpretation: type ButtonHandler a b = b The raw event. -> Maybe (Int, Bool) The button number and whether the button is depressed.
Files
- kafka-device.cabal +12/−12
- src/Network/UI/Kafka/Interpretation.hs +52/−38
kafka-device.cabal view
@@ -1,5 +1,5 @@ name: kafka-device-version: 0.2.1.0+version: 0.2.1.2 synopsis: UI device events via a Kafka message broker description: This package contains functions for passing UI device events to topics on a Kafka message broker \<<https://kafka.apache.org/>\>. Also see \<<https://hackage.haskell.org/package/kafka-device-joystick/>\>, \<<https://hackage.haskell.org/package/kafka-device-glut/>\>, \<<https://hackage.haskell.org/package/kafka-device-spacenav/>\>, \<<https://hackage.haskell.org/package/kafka-device-leap/>\>. license: MIT@@ -13,7 +13,7 @@ stability: Experimental homepage: https://bitbucket.org/functionally/kafka-device bug-reports: https://bwbush.atlassian.net/projects/HKAFDEV/issues/-package-url: https://bitbucket.org/functionally/kafka-device/downloads/kafka-device-0.1.5.0.tar.gz+package-url: https://bitbucket.org/functionally/kafka-device/downloads/kafka-device-$version.tar.gz extra-source-files: ReadMe.md @@ -27,15 +27,15 @@ Network.UI.Kafka.Keyboard Network.UI.Kafka.Types build-depends: base >= 4.8 && < 5- , aeson- , binary- , bytestring- , cereal- , linear- , milena- , mtl+ , aeson >= 0.11.3+ , binary >= 0.7.2+ , bytestring >= 0.10.6+ , cereal >= 0.5.4+ , linear >= 1.20.5+ , milena >= 0.5.0+ , mtl >= 2.2.1 hs-source-dirs: src- ghc-options: -O2 -Wall+ ghc-options: -Wall default-language: Haskell2010 executable kafka-device@@ -49,7 +49,7 @@ , milena , mtl hs-source-dirs: src- ghc-options: -O2 -Wall -threaded+ ghc-options: -Wall -threaded default-language: Haskell2010 executable kafka-device-keyboard@@ -63,5 +63,5 @@ , milena , mtl hs-source-dirs: src- ghc-options: -O2 -Wall -threaded+ ghc-options: -Wall -threaded default-language: Haskell2010
src/Network/UI/Kafka/Interpretation.hs view
@@ -10,7 +10,6 @@ -} - {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-}@@ -53,28 +52,28 @@ -- | Instructions for interpreting user-interface events from Kafka.-data Interpretation a =+data Interpretation a b = TrackInterpretation { kafka :: TopicConnection -- ^ How to connect to Kafka. , sensor :: Sensor -- ^ The name of the sensor.- , path :: FilePath -- ^ The path the the device.- , xAxis :: AxisInterpretation a -- ^ Interpretation for the x-axis.- , yAxis :: AxisInterpretation a -- ^ Interpretation for the y-axis.- , zAxis :: AxisInterpretation a -- ^ Interpretation for the z-axis.- , phiAxis :: AxisInterpretation a -- ^ Interpretation for the Euler angle about the x-axis.- , thetaAxis :: AxisInterpretation a -- ^ Interpretation for the Euler angle about the y-axis.- , psiAxis :: AxisInterpretation a -- ^ Interpretation for the Euler angle about the z-axis.- , location :: V3 a -- ^ The initial location, (x, y, z).- , orientation :: V3 a -- ^ The initial orientation, (phi, theta, psi).+ , device :: a -- ^ The device.+ , xAxis :: AxisInterpretation b -- ^ Interpretation for the x-axis.+ , yAxis :: AxisInterpretation b -- ^ Interpretation for the y-axis.+ , zAxis :: AxisInterpretation b -- ^ Interpretation for the z-axis.+ , phiAxis :: AxisInterpretation b -- ^ Interpretation for the Euler angle about the x-axis.+ , thetaAxis :: AxisInterpretation b -- ^ Interpretation for the Euler angle about the y-axis.+ , psiAxis :: AxisInterpretation b -- ^ Interpretation for the Euler angle about the z-axis.+ , location :: V3 b -- ^ The initial location, (x, y, z).+ , orientation :: V3 b -- ^ The initial orientation, (phi, theta, psi). , flying :: Bool -- ^ Whether to interpret displacements as being relative to the current orientation. , resetButton :: Maybe Int -- ^ The button number for resetting the location and orientation to their initial values. } deriving (Eq, Generic, Read, Show) -instance FromJSON a => FromJSON (Interpretation a)+instance (FromJSON a, FromJSON b) => FromJSON (Interpretation a b) -instance ToJSON a => ToJSON (Interpretation a)+instance (ToJSON a, ToJSON b) => ToJSON (Interpretation a b) -- | Instructions for interpreting an axis.@@ -95,13 +94,13 @@ -- | Translate a SpaceNavigator event on Linux into events for Kafka.-translate :: (Conjugate a, Epsilon a, Num a, Ord a, RealFloat a)- => MVar (State a) -- ^ Reference to the current location and orientation.- -> AnalogHandler a b -- ^ How to handle raw analog events.- -> ButtonHandler a b -- ^ How to handle raw button events.- -> Interpretation a -- ^ The interpretation.- -> b -- ^ A raw event.- -> IO [Event] -- ^ The corresponding events for Kafka.+translate :: (Conjugate b, Epsilon b, Num b, Ord b, RealFloat b)+ => MVar (State b) -- ^ Reference to the current location and orientation.+ -> AnalogHandler b c -- ^ How to handle raw analog events.+ -> ButtonHandler b c -- ^ How to handle raw button events.+ -> Interpretation a b -- ^ The interpretation.+ -> c -- ^ A raw event.+ -> IO [Event] -- ^ The corresponding events for Kafka. translate state analogHandler buttonHandler TrackInterpretation{..} event = do (location0, orientation0) <- readMVar state@@ -113,10 +112,10 @@ clamp AxisInterpretation{..} = maybe id ((maximum .) . (. return) . (:)) lowerBound . maybe id ((minimum .) . (. return) . (:)) upperBound- (location1@(V3 x y z), orientation1@(Quaternion q0 (V3 qx qy qz))) =+ (location1, orientation1) = case (buttonHandler event, analogHandler event) of (Just (number, pressed), _) -> if pressed && Just number == resetButton- then (location, eulerToQuaternion orientation)+ then (location, fromEuler orientation) else (location0, orientation0) (_, Just (number, setting)) -> let euler = adjust number setting <$> V3 phiAxis thetaAxis psiAxis@@ -128,52 +127,67 @@ <$> axes <*> location0 ^+^ (if flying then (orientation0 `rotate`) else id) delta- , eulerToQuaternion euler+ , fromEuler euler * orientation0 ) (_, _) -> (location0, orientation0)- [x', y', z', q0', qx', qy', qz'] = realToFrac <$> [x, y, z, q0, qx, qy, qz] unless (location0 == location1 && orientation0 == orientation1) . void $ swapMVar state (location1, orientation1) return- . (if location0 /= location1 then (LocationEvent ( x' , y' , z' ) :) else id)- . (if orientation0 /= orientation1 then (OrientationEvent (q0', qx', qy', qz') :) else id)+ . (if location0 /= location1 then (fromV3 location1 :) else id)+ . (if orientation0 /= orientation1 then (fromQuaternion orientation1 :) else id) $ case buttonHandler event of Just (number, pressed) -> [ButtonEvent (IndexButton number, if pressed then Down else Up)] Nothing -> [] -- | Convert from Euler angles to a quaternion.-eulerToQuaternion :: (Epsilon a, Num a, RealFloat a) => V3 a -> Quaternion a-eulerToQuaternion (V3 phi theta psi) =+fromEuler :: (Epsilon a, Num a, RealFloat a) => V3 a -> Quaternion a+fromEuler (V3 phi theta psi) = let [ex, ey, ez] = basis in ez `axisAngle` psi * ey `axisAngle` theta * ex `axisAngle` phi +-- | Convert from 'V3' to 'Event'.+fromV3 :: Real a => V3 a -> Event+fromV3 (V3 x y z) = LocationEvent (realToFrac x, realToFrac y, realToFrac z)+++-- | Convert from 'Quaternion' to 'Event'.+fromQuaternion :: Real a => Quaternion a -> Event+fromQuaternion (Quaternion w (V3 x y z)) = OrientationEvent (realToFrac w, realToFrac x, realToFrac y, realToFrac z)++ -- | Location and orientation. type State a = (V3 a, Quaternion a) -- | How to handle raw analog events.-type AnalogHandler a b = b -> Maybe (Int, a)+type AnalogHandler a b = b -- ^ The raw event.+ -> Maybe (Int, a) -- ^ The axis number and value. -- | How to handle raw button events.-type ButtonHandler a b = b -> Maybe (Int, Bool)+type ButtonHandler a b = b -- ^ The raw event.+ -> Maybe (Int, Bool) -- ^ The button number and whether the button is depressed. -- | Repeatedly interpret events.-interpretationLoop :: (Conjugate a, Epsilon a, Num a, Ord a, RealFloat a)- => AnalogHandler a b -- ^ How to handle raw analog events.- -> ButtonHandler a b -- ^ How to handle raw button events.- -> Interpretation a -- ^ The interpretation.- -> IO b -- ^ Action for getting the next raw event.+interpretationLoop :: (Conjugate b, Epsilon b, Num b, Ord b, RealFloat b)+ => AnalogHandler b c -- ^ How to handle raw analog events.+ -> ButtonHandler b c -- ^ How to handle raw button events.+ -> Interpretation a b -- ^ The interpretation.+ -> IO c -- ^ Action for getting the next raw event. -> IO (ExitAction, LoopAction) -- ^ Action to create the exit and loop actions. interpretationLoop analogHandler buttonHandler interpretation@TrackInterpretation{..} action = do- state <- newMVar (location, eulerToQuaternion orientation)+ first <- newMVar True+ state <- newMVar (location, fromEuler orientation) producerLoop kafka sensor- $ translate state analogHandler buttonHandler interpretation- =<< action+ $ do+ isFirst <- readMVar first+ if isFirst+ then swapMVar first False >> return [fromV3 location, fromQuaternion $ fromEuler orientation]+ else action >>= translate state analogHandler buttonHandler interpretation