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 +1/−1
- Monky/Blkid.hs +1/−1
- Monky/Examples/Wifi.hs +7/−93
- Monky/Examples/Wifi/Event.hs +116/−0
- Monky/Examples/Wifi/Poll.hs +205/−0
- Monky/Memory.hs +4/−4
- Monky/Wifi.hs +28/−12
- monky.cabal +3/−2
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