packages feed

monky 2.1.3.0 → 2.2.0.0

raw patch · 8 files changed

+365/−113 lines, 8 filesdep ~netlinkPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: netlink

API changes (from Hackage documentation)

- Monky.Examples.Wifi: FormatRates :: WifiFormat
- Monky.Examples.Wifi: FormatSignal :: WifiFormat
- Monky.Examples.Wifi: data WifiHandle
- Monky.Examples.Wifi: instance Monky.Modules.EvtModule Monky.Examples.Wifi.WifiHandle
- Monky.Examples.Wifi: instance Monky.Modules.PollModule Monky.Examples.Wifi.WifiHandle
- Monky.Wifi: type SSIDSocket = NL80211Socket
+ Monky.Examples.Wifi: data WifiEvtHandle
+ Monky.Examples.Wifi: getWifiHandle' :: (WifiStats -> Text) -> Text -> String -> IO WifiEvtHandle
+ Monky.Examples.Wifi.Event: FormatChannel :: WifiFormat
+ Monky.Examples.Wifi.Event: FormatFreq :: WifiFormat
+ Monky.Examples.Wifi.Event: FormatName :: WifiFormat
+ Monky.Examples.Wifi.Event: FormatText :: Text -> WifiFormat
+ Monky.Examples.Wifi.Event: data WifiEvtHandle
+ Monky.Examples.Wifi.Event: data WifiFormat
+ Monky.Examples.Wifi.Event: getTextify :: WifiFormat -> WifiStats -> Text
+ Monky.Examples.Wifi.Event: getWifiHandle :: [WifiFormat] -> Text -> String -> IO WifiEvtHandle
+ Monky.Examples.Wifi.Event: getWifiHandle' :: (WifiStats -> Text) -> Text -> String -> IO WifiEvtHandle
+ Monky.Examples.Wifi.Event: instance Monky.Modules.EvtModule Monky.Examples.Wifi.Event.WifiEvtHandle
+ Monky.Examples.Wifi.Poll: DirRX :: Direction
+ Monky.Examples.Wifi.Poll: DirTX :: Direction
+ Monky.Examples.Wifi.Poll: FormatBitrate :: Direction -> WifiFormat
+ Monky.Examples.Wifi.Poll: FormatBitrateMin :: WifiFormat
+ Monky.Examples.Wifi.Poll: FormatChannel :: WifiFormat
+ Monky.Examples.Wifi.Poll: FormatFreq :: WifiFormat
+ Monky.Examples.Wifi.Poll: FormatMCS :: Direction -> WifiFormat
+ Monky.Examples.Wifi.Poll: FormatMCSMin :: WifiFormat
+ Monky.Examples.Wifi.Poll: FormatName :: WifiFormat
+ Monky.Examples.Wifi.Poll: FormatSignal :: WifiFormat
+ Monky.Examples.Wifi.Poll: FormatSignalAverage :: WifiFormat
+ Monky.Examples.Wifi.Poll: FormatText :: Text -> WifiFormat
+ Monky.Examples.Wifi.Poll: FormatWifiWidth :: WifiFormat
+ Monky.Examples.Wifi.Poll: data Direction
+ Monky.Examples.Wifi.Poll: data WifiFormat
+ Monky.Examples.Wifi.Poll: data WifiPollHandle
+ Monky.Examples.Wifi.Poll: getWifiHandle :: [WifiFormat] -> Text -> String -> IO WifiPollHandle
+ Monky.Examples.Wifi.Poll: getWifiHandle' :: ((WifiStats, Maybe NL80211Packet) -> Text) -> Text -> String -> IO WifiPollHandle
+ Monky.Examples.Wifi.Poll: instance GHC.Classes.Eq Monky.Examples.Wifi.Poll.Direction
+ Monky.Examples.Wifi.Poll: instance GHC.Classes.Eq Monky.Examples.Wifi.Poll.WifiFormat
+ Monky.Examples.Wifi.Poll: instance GHC.Show.Show Monky.Examples.Wifi.Poll.Direction
+ Monky.Examples.Wifi.Poll: instance GHC.Show.Show Monky.Examples.Wifi.Poll.WifiFormat
+ Monky.Examples.Wifi.Poll: instance Monky.Modules.PollModule Monky.Examples.Wifi.Poll.WifiPollHandle
+ Monky.Wifi: [wifiBSSID] :: WifiStats -> ByteString
+ Monky.Wifi: data SSIDSocket
+ Monky.Wifi: getExtendedWifi :: SSIDSocket -> Interface -> WifiStats -> IO (Maybe NL80211Packet)
- Monky.Examples.Wifi: getWifiHandle :: [WifiFormat] -> Text -> String -> IO WifiHandle
+ Monky.Examples.Wifi: getWifiHandle :: [WifiFormat] -> Text -> String -> IO WifiEvtHandle
- Monky.Wifi: WifiStats :: Word8 -> [Word32] -> String -> Word32 -> Signal -> WifiStats
+ Monky.Wifi: WifiStats :: Word8 -> [Word32] -> String -> Word32 -> Signal -> ByteString -> WifiStats

Files

Monky/Alsa.hsc view
@@ -96,7 +96,7 @@ data Elem type ElemHandle = Ptr Elem -importLib "LibAlsa" "libasound.so"+importLib "LibAlsa" "libasound.so.2"   [ ("mixer_open", "snd_mixer_open", "MixerHandleAlloc -> Int -> IO CInt")   , ("mixer_attach", "snd_mixer_attach", "MixerHandle -> CString -> IO CInt")   , ("mixer_register", "snd_mixer_selem_register", "MixerHandle -> Ptr RegOpt -> Ptr MClass -> IO CInt")
Monky/Blkid.hs view
@@ -57,7 +57,7 @@  data Cache -importLib "LibBlkid" "libblkid.so"+importLib "LibBlkid" "libblkid.so.1"   [ ( "c_evt", "blkid_evaluate_tag", "CString -> CString -> Ptr Cache -> IO CString")   , ( "c_evs", "blkid_evaluate_spec", "CString -> Ptr Cache -> IO CString")   ]
Monky/Examples/Wifi.hs view
@@ -1,5 +1,5 @@ {--    Copyright 2016 Markus Ongyerth+    Copyright 2016,2017 Markus Ongyerth      This file is part of Monky. @@ -16,109 +16,23 @@     You should have received a copy of the GNU Lesser General Public License     along with Monky.  If not, see <http://www.gnu.org/licenses/>. -}+ {-| Module      : Monky.Examples.Wifi-Description : An example module instance for the wifi module+Description : Backwards compatability module for "Monky.Examples.Wifi.Event" Maintainer  : ongy Stability   : experimental Portability : Linux -FormatSignal only makes sense when used in a pollModule. But even in pollModule-context updates may take a while because of some buffering by drivers or-netlink subsystem. -}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE CPP #-} module Monky.Examples.Wifi   ( getWifiHandle-  , WifiHandle+  , getWifiHandle'++  , WifiEvtHandle   , WifiFormat(..)   ) where -import Formatting-import Data.Word (Word32, Word8)-import Data.Int (Int32)-import Data.Text (Text)-import qualified Data.Text as T-import Data.Maybe (fromMaybe)--import Monky.Modules-import Monky.Examples.Utility-import Monky.Wifi--#if MIN_VERSION_base(4,8,0)-#else-import Control.Applicative ((<$>))-#endif---- Socket Interface Conversion Offline--- |The handle type for this module-data WifiHandle = WH SSIDSocket Interface (WifiStats -> Text) Text---- |A typesafe version of a format string-data WifiFormat-  = FormatChannel -- ^Print the current networks channel-  | FormatRates -- ^Print the current network max supported rate (always 54Mbit/s for me)-  | FormatName -- ^Print the ESSID of the current network, may look weird because SSIDs are-  | FormatFreq -- ^Print the frequency the current network sends on (related to channel)-  | FormatSignal -- ^Print link quality (0-100)-  | FormatText Text -- ^Print a plaintext string--getFun :: WifiFormat -> WifiStats -> Text-getFun FormatChannel    = sformat int . wifiChannel-getFun FormatRates      = flip convertUnitSI "B" . maximum . wifiRates-getFun FormatName       = T.pack . wifiName-getFun FormatFreq       = sformat int . wifiFreq-getFun FormatSignal     = sformat int . doStrength . wifiSig-getFun (FormatText str) = const str--getFunction :: [WifiFormat] -> WifiStats -> Text-getFunction xs = T.concat . (\a -> map (($ a) . getFun) xs)---- |Do the calculation for MBM--- This is taken from NetworkManager-doMBM :: Word32 -> Word8-doMBM e =-  let noiseFloor = -90-      signalMax  = -20-      work :: Int32 = fromIntegral e-      clamped :: Float = min signalMax $ max noiseFloor $ fromIntegral $ work `div` 100-      in floor (100 - 70 * ((signalMax - clamped) / (signalMax - noiseFloor)))---- Helper for FormatSignal that splits signal types-doStrength :: Signal -> Word8-doStrength (SigMBM mbm) = doMBM mbm-doStrength (SigUNSPEC unspec) = unspec---- |Get a wifi handle-getWifiHandle-  :: [WifiFormat] -- ^Format "String" for output generation-  -> Text -- ^Text that should be displayed when wifi is disconnected-  -> String -- ^Name of the interface-  -> IO WifiHandle-getWifiHandle f d n = do-  let fun = getFunction f-  s <- getSSIDSocket-  i <- fromMaybe (error ("Could not find interface: " ++ n)) <$> getInterface s n-  return (WH s i fun d)--getEventOutput :: WifiHandle -> IO [MonkyOut]-getEventOutput (WH s i f d) = do-  new <- gotReadable s i-  case new of-    (WifiConnect x) -> return [MonkyPlain $ f x]-    WifiNone -> return []-    WifiDisconnect -> return [MonkyPlain d]--instance EvtModule WifiHandle where-  startEvtLoop h@(WH s _ _ _) r = do-    r =<< getOutput h-    prepareEvents s-    loopFd h (getWifiFd s) r getEventOutput+import Monky.Examples.Wifi.Event -instance PollModule WifiHandle where-  getOutput (WH s i f d) = do-    ret <- getCurrentWifiStats s i-    return [MonkyPlain $ maybe d f ret]
+ Monky/Examples/Wifi/Event.hs view
@@ -0,0 +1,116 @@+{-+    Copyright 2016 Markus Ongyerth++    This file is part of Monky.++    Monky is free software: you can redistribute it and/or modify+    it under the terms of the GNU Lesser General Public License as published by+    the Free Software Foundation, either version 3 of the License, or+    (at your option) any later version.++    Monky is distributed in the hope that it will be useful,+    but WITHOUT ANY WARRANTY; without even the implied warranty of+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+    GNU Lesser General Public License for more details.++    You should have received a copy of the GNU Lesser General Public License+    along with Monky.  If not, see <http://www.gnu.org/licenses/>.+-}+{-|+Module      : Monky.Examples.Wifi.Event+Description : The event based wifi module interface+Maintainer  : ongy+Stability   : experimental+Portability : Linux++This module provides the event based interface to wifi information.+It is rather limited because of some technical stuff with 802.11.+If you need more information about your wifi use the "Monky.Exmaple.Wifi.Poll" module.+-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE CPP #-}+module Monky.Examples.Wifi.Event+  ( getWifiHandle+  , getWifiHandle'++  , getTextify++  , WifiEvtHandle+  , WifiFormat(..)+  )+where++import Formatting+import Data.Text (Text)+import qualified Data.Text as T+import Data.Maybe (fromMaybe)++import Monky.Modules+import Monky.Examples.Utility+import Monky.Wifi++#if MIN_VERSION_base(4,8,0)+#else+import Control.Applicative ((<$>), pure)+#endif++-- Socket Interface Conversion Offline+-- |The handle type for this module+data WifiEvtHandle = WH SSIDSocket Interface (WifiStats -> Text) Text++-- NOTE: If you extend this, also extend the type in Monky.Examples.Wifi.Poll+-- |A typesafe version of a format string+data WifiFormat+  = FormatChannel -- ^Print the current networks channel+  | FormatName -- ^Print the ESSID of the current network, may look weird because SSIDs are+  | FormatFreq -- ^Print the frequency the current network sends on (related to channel)+  | FormatText Text -- ^Print a plaintext string++-- | Apply the 'WifiFormat' to show some 'WifiStats' information as text.+getTextify :: WifiFormat -> WifiStats -> Text+getTextify FormatChannel    = sformat int . wifiChannel+getTextify FormatName       = T.pack . wifiName+getTextify FormatFreq       = sformat int . wifiFreq+getTextify (FormatText str) = const str++getFunction :: [WifiFormat] -> WifiStats -> Text+getFunction xs = T.concat . (\a -> map (($ a) . getTextify) xs)++-- |Get a wifi handle+getWifiHandle+  :: [WifiFormat] -- ^Format "String" for output generation+  -> Text -- ^Text that should be displayed when wifi is disconnected+  -> String -- ^Name of the interface+  -> IO WifiEvtHandle+getWifiHandle f d n =+  getWifiHandle' (getFunction f) d n++-- | Lower level version of 'getWifiHandle' if you need exted information.+getWifiHandle'+    :: (WifiStats -> Text)+    -> Text+    -> String+    -> IO WifiEvtHandle+getWifiHandle' f d n = do+    s <- getSSIDSocket+    i <- fromMaybe (error ("Could not find interface: " ++ n)) <$> getInterface s n+    return (WH s i f d)++getEventOutput :: WifiEvtHandle -> IO [MonkyOut]+getEventOutput (WH s i f d) = do+  new <- gotReadable s i+  case new of+    (WifiConnect x) -> do+        return [MonkyPlain $ f x]+    WifiNone -> return []+    WifiDisconnect -> return [MonkyPlain d]++instance EvtModule WifiEvtHandle where+  startEvtLoop h@(WH s i f d) r = do+    ret <- getCurrentWifiStats s i+    r . pure $ case ret of+            Nothing -> MonkyPlain d+            Just x -> MonkyPlain $ f x+    prepareEvents s+    loopFd h (getWifiFd s) r getEventOutput
+ Monky/Examples/Wifi/Poll.hs view
@@ -0,0 +1,205 @@+{-+    Copyright 2017 Markus Ongyerth++    This file is part of Monky.++    Monky is free software: you can redistribute it and/or modify+    it under the terms of the GNU Lesser General Public License as published by+    the Free Software Foundation, either version 3 of the License, or+    (at your option) any later version.++    Monky is distributed in the hope that it will be useful,+    but WITHOUT ANY WARRANTY; without even the implied warranty of+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+    GNU Lesser General Public License for more details.++    You should have received a copy of the GNU Lesser General Public License+    along with Monky.  If not, see <http://www.gnu.org/licenses/>.+-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE NumDecimals #-}+{-|+Module      : Monky.Examples.Wifi.Poll+Description : The polling api for wifi information+Maintainer  : ongy+Stability   : experimental+Portability : Linux++This provides polling access to wifi information.+For the event based version look at "Monky.Examples.Wifi.Event"+-}+module Monky.Examples.Wifi.Poll+    ( WifiFormat (..)+    , WifiPollHandle+    , Direction(..)++    , getWifiHandle+    , getWifiHandle'+    )+where++import Debug.Trace++import Data.Int (Int8)++import Data.Maybe (fromMaybe)+import Data.Word (Word8)+import Formatting+import Monky.Examples.Utility+import qualified Monky.Examples.Wifi.Event as E+import Monky.Modules+import Monky.Wifi+import System.Linux.Netlink.GeNetlink.NL80211+import System.Linux.Netlink.GeNetlink.NL80211.StaInfo++import Data.Text (Text)+import qualified Data.Text as T++import Control.Applicative ((<|>), (<$>), (<*>), pure)++-- | The type for polling wifi information+data WifiPollHandle = WH SSIDSocket Interface ((WifiStats, Maybe NL80211Packet) -> Text) Text++-- TODO: Find out which of RX and TX is which from *our* side and document it+-- | Helper type for WifiFormat to specify direction+data Direction+    -- | Use TX information+    = DirTX+    -- | Use TX information+    | DirRX+    deriving (Show, Eq)++-- | Enum-ish type for converting Wifi information to text+data WifiFormat+    -- | The MCSIndex for our connection+    = FormatMCS Direction+    -- | The minimum MCSIndex for our connection+    | FormatMCSMin+    -- | The Signal width (in MHz)+    | FormatWifiWidth+    -- | The Bitrate of our connection+    | FormatBitrate Direction+    -- | Minimum of TX/RX Bitrate for this station+    | FormatBitrateMin+    -- | Signal strength from other source+    | FormatSignal+    -- | Signal strength average+    | FormatSignalAverage++    | FormatChannel -- ^Print the current networks channel+    | FormatName -- ^Print the ESSID of the current network, may look weird because SSIDs are+    | FormatFreq -- ^Print the frequency the current network sends on (related to channel)+    | FormatText Text -- ^Print a plaintext string+    deriving (Show, Eq)++-- |Do the calculation for MBM+-- This is taken from NetworkManager+doMBM :: Int8 -> Word8+doMBM e =+  let noiseFloor = -90+      signalMax  = -20+      clamped = min signalMax $ max noiseFloor $ e+   in fromIntegral $ 100 - (signalMax - clamped)++getFromDir :: Direction -> StaInfo -> Maybe StaRate+getFromDir DirTX = staTXRate+getFromDir DirRX = staRXRate++pollToEvt :: WifiFormat -> E.WifiFormat+pollToEvt FormatChannel  = E.FormatChannel+pollToEvt FormatName     = E.FormatName+pollToEvt FormatFreq     = E.FormatFreq+pollToEvt (FormatText t) = E.FormatText t+pollToEvt x = error $ "Tried to convert " ++ show x ++ "to Evt? This really shouldn't ever happen"++getExtFun :: WifiFormat -> (WifiStats, StaInfo) -> Text+getExtFun (FormatMCS dir) (_, info) =+    case getFromDir dir info of+        Nothing -> "No Rate"+        Just x -> case rateMCS x <|> rateVHTMCS x of+            Nothing -> "No MCS"+            Just y -> sformat int y+getExtFun FormatMCSMin (_, info) = fromMaybe "No Rate" $ do+    rx <- staRXRate info+    tx <- staTXRate info+    rmcs <- getMCS rx+    tmcs <- getMCS tx+    pure . sformat int $ min rmcs tmcs+    where getMCS x = rateMCS x <|> rateVHTMCS x+getExtFun FormatWifiWidth (_, info) = -- Width is also in TXRate+    case staTXRate info of+        Nothing -> "No Rate"+        Just x -> case rateWidthFlag x of+            Width5MHz -> "5MHz"+            Width10MHz -> "10MHz"+            Width20MHz -> "20MHz"+            Width40MHz -> "40MHz"+            Width80MHz -> "80MHz"+            Width160MHz -> "160MHz"+getExtFun (FormatBitrate dir) (_, info) = -- Bitrate is in TXRate+    case getFromDir dir info of+        Nothing -> "No Rate"+        Just x -> maybe+            "No Bitrate"+            (flip convertUnitSI "b" . (* 1e5))+            (rateBitrate x)+getExtFun FormatBitrateMin (_, info) = -- Bitrate from RX/TX Rate+    let tx = rateBitrate =<< staTXRate info+        rx = rateBitrate =<< staRXRate info+    in case min <$> rx <*> tx of+        Nothing -> "No rates"+        Just x -> convertUnitSI (x * 1e5) "b"+getExtFun FormatSignal (_, info) =+    case staSignalMBM info of+        Nothing -> "No strength"+        Just x -> sformat int . doMBM . traceShowId $ fromIntegral x+getExtFun FormatSignalAverage (_, info) =+    case staSignalMBMA info of+        Nothing -> "No strength"+        Just x -> sformat int . doMBM $ fromIntegral x+getExtFun x (stats, _) = E.getTextify (pollToEvt x) stats++getExtFunction :: [WifiFormat] -> (WifiStats, StaInfo) -> Text+getExtFunction xs = T.concat . (sequence . map getExtFun $ xs)++{- |This function is the easiest, but also a bit limited way to get extended wifi information.++With this, all "normal" information will be first, and the extended information will be appended.+-}+getCombiFun :: [WifiFormat] -> ((WifiStats, Maybe NL80211Packet) -> Text)+getCombiFun xs (stat, ext) =+    let fun = getExtFunction xs+        info = staInfoFromPacket =<< ext+     in case info of+            Just x -> fun (stat, x)+            Nothing -> "Couldn't get wifi station info"++instance PollModule WifiPollHandle where+  getOutput (WH s i f d) = do+    ret <- getCurrentWifiStats s i+    case ret of+        Nothing -> pure . pure $ MonkyPlain d+        Just x -> do+            ext <- getExtendedWifi s i x+            pure . pure . MonkyPlain $ f (x, ext)++-- | Lower level version of 'getWifiHandle' if you need exted information.+getWifiHandle'+    :: ((WifiStats, Maybe NL80211Packet) -> Text)+    -> Text+    -> String+    -> IO WifiPollHandle+getWifiHandle' f d n = do+    s <- getSSIDSocket+    i <- fromMaybe (error ("Could not find interface: " ++ n)) <$> getInterface s n+    return (WH s i f d)++-- |Get a wifi handle+getWifiHandle+  :: [WifiFormat] -- ^Format "String" for output generation+  -> Text -- ^Text that should be displayed when wifi is disconnected+  -> String -- ^Name of the interface+  -> IO WifiPollHandle+getWifiHandle f d n =+  getWifiHandle' (getCombiFun f) d n
Monky/Memory.hs view
@@ -44,7 +44,7 @@   -- |The memory handle used for all functions-data MemoryHandle = MemoryH File+newtype MemoryHandle = MemoryH File  path :: String path = "/proc/meminfo"@@ -86,8 +86,8 @@ -- |Get the amount of memory rported as free by the kernel getMemoryFree :: MemoryHandle -> IO Int getMemoryFree (MemoryH f) = do-  contents <- readContent f-  return . getVal . fromMaybe err . findLine "MemFree" $ contents+    contents <- readContent f+    return . getVal . fromMaybe err . findLine "MemFree" $ contents     where err = error "Could not find MemFree in /proc/meminfo. Please report this bug with the content of /proc/meminfo"  -- |Get the amount of memory used by the kernel and processes@@ -103,7 +103,7 @@   let avail = getVal . fromMaybe "a 0" . findLine "MemAvailable" $ contents       total = getVal . fromMaybe "a 0" . findLine "MemTotal" $ contents       free = getVal . fromMaybe "a 0" . findLine "MemFree" $ contents-      used = (total - avail)+      used = total - avail   return (total, avail, free, used)  
Monky/Wifi.hs view
@@ -35,6 +35,7 @@   , SSIDSocket   , getWifiFd   , prepareEvents+  , getExtendedWifi    , Signal(..)   , WifiStats(..)@@ -42,8 +43,6 @@   ) where -import Debug.Trace- import Data.Bits ((.&.)) import Data.Word (Word8, Word32) import Data.Maybe (listToMaybe, fromMaybe)@@ -62,6 +61,7 @@  import Data.Serialize (Serialize, decode) import Data.Serialize.Get (runGet, getWord32host)+import Data.Serialize.Put (runPut, putWord32host)  #if MIN_VERSION_base(4,8,0) #else@@ -70,8 +70,12 @@  -- |The interface identifier type Interface = Word32+ -- |The socket type for this module-type SSIDSocket = NL80211Socket+-- The first socket is general operation/event based+-- the seconds socket will be used to get extended information.+-- We use 2 sockets, to not get event/request mixed up.+data SSIDSocket = SSIDSocket NL80211Socket NL80211Socket  -- |Enum for connection change data WifiConn@@ -91,6 +95,7 @@   , wifiName :: String   , wifiFreq :: Word32   , wifiSig :: Signal+  , wifiBSSID :: ByteString   }  -- Unsafe decode, we rely on kernel to be sensible@@ -124,6 +129,7 @@   rate <- M.lookup eWLAN_EID_SUPP_RATES attrs    freq <- uDecode . M.lookup eNL80211_BSS_FREQUENCY $ pattrs+  ssid <- M.lookup eNL80211_BSS_BSSID pattrs   let mbm = uGetWord32 . M.lookup eNL80211_BSS_SIGNAL_MBM $ pattrs   let sig = uDecode . M.lookup eNL80211_BSS_SIGNAL_UNSPEC $ pattrs @@ -131,13 +137,13 @@   let ratL = rate `BS.append` fromMaybe BS.empty bs   let rates = map (\y -> fromIntegral (y .&. 0x7F) * (500000 :: Word32)) . BS.unpack $ ratL -  return $ WifiStats channel rates name freq $getSignal mbm sig+  return $ WifiStats channel rates name freq (getSignal mbm sig) ssid  -- |Get the stats of a currently connected wifi network getCurrentWifiStats :: SSIDSocket -> Interface -> IO (Maybe WifiStats)-getCurrentWifiStats s i = do+getCurrentWifiStats (SSIDSocket _ s) i = do   wifis <- getConnectedWifi s i-  return $ attrToStat =<< listToMaybe (trace ("conn: " ++ show wifis) wifis)+  return $ attrToStat =<< listToMaybe  wifis   -- |Get only the name of the currently connected wifi@@ -147,21 +153,21 @@  -- |Get the interface id by name getInterface :: SSIDSocket -> String -> IO (Maybe Interface)-getInterface s n = do+getInterface (SSIDSocket s _) n = do   interfaces <- getInterfaceList s   return $ snd <$> listToMaybe (filter ((==) n . fst) interfaces)   -- |get the raw fd for eventing getWifiFd :: SSIDSocket -> Fd-getWifiFd = getFd+getWifiFd (SSIDSocket s _) = getFd s  -- We are only looking for ESSID right now, if we want to -- make this module more general, we will have to extend the -- return type of this function -- |This should be called when the fd returned by 'getWifiFd' got readable gotReadable :: SSIDSocket -> Interface -> IO WifiConn-gotReadable s i = do+gotReadable b@(SSIDSocket s _) i = do -- we only care for ESSID and connect updates are a single message -- so this *should* be fine   ps <- getPacket s@@ -172,7 +178,7 @@       let cmd = genlCmd . genlDataHeader . packetCustom $ packet       if cmd == eNL80211_CMD_CONNECT         then do-          wifi <- getCurrentWifiStats s i+          wifi <- getCurrentWifiStats b i           return $ case wifi of             Nothing -> WifiDisconnect             Just x -> WifiConnect x@@ -183,13 +189,23 @@               else return WifiNone           else return WifiNone +getStation :: NL80211Socket -> Word32 -> ByteString -> IO [NL80211Packet]+getStation s i m = query s eNL80211_CMD_GET_STATION False attrs+    where attrs = M.fromList [(eNL80211_ATTR_IFINDEX, runPut . putWord32host $ i), (eNL80211_ATTR_MAC, m)]++-- | Get some additional information about the currently connected wifi+getExtendedWifi :: SSIDSocket -> Interface -> WifiStats -> IO (Maybe NL80211Packet)+getExtendedWifi (SSIDSocket _ s) i stats =+    listToMaybe <$> getStation s i (wifiBSSID stats)+ -- |Subscribe to multicast group prepareEvents :: SSIDSocket -> IO ()-prepareEvents s = joinMulticastByName s "mlme"+prepareEvents (SSIDSocket s _) = joinMulticastByName s "mlme"  -- |Get a netlink socket bound to nl80211 -- Before this is used event based, call 'prepareEvents' getSSIDSocket :: IO SSIDSocket getSSIDSocket = do   s <- makeNL80211Socket-  return s+  e <- makeNL80211Socket+  return $ SSIDSocket s e
monky.cabal view
@@ -10,7 +10,7 @@ -- PVP summary:      +-+------- breaking API changes --                   | | +----- non-breaking API additions --                   | | | +--- code changes with no API change-version:             2.1.3.0+version:             2.2.0.0  -- The ABOVE LINE has to stay AS IS (except for version changes) for the -- template to work properly@@ -135,7 +135,8 @@   exposed-modules: Monky.Examples.Battery Monky.Examples.CPU Monky.Examples.Disk Monky.Examples.Network Monky.Examples.Time Monky.Examples.Memory   exposed-modules: Monky.Disk.Btrfs Monky.Disk.Device   exposed-modules: Monky.Examples.Prepend Monky.Connectivity-  exposed-modules: Monky.Wifi Monky.Examples.Wifi+  exposed-modules: Monky.Wifi Monky.Examples.Wifi Monky.Examples.Wifi.Poll+  exposed-modules: Monky.Examples.Wifi.Event   exposed-modules: Monky.Examples.Connectivity Monky.Network.Dynamic   exposed-modules: Monky.Network.Static Monky.Examples.File Monky.Examples.Utility   exposed-modules: Monky.Examples.Sound.Alsa  Monky.Examples.Alsa