module Monky.Battery
( getBatteryHandle
, getBatteryHandle'
, getCurrentStatus
, getCurrentLevel
, BatteryHandle
, getTimeLeft
, getLoading
, BatteryState(..)
)
where
#if MIN_VERSION_base(4,8,0)
#else
import Control.Applicative ((<$>))
#endif
import Data.Maybe (fromMaybe)
import Data.IORef
import System.Directory
import Monky.Utility
data BatteryHandle = BatH FilesArray (IORef Int)
data FilesArray = PowerNow File File File File |
ChargeNow File File (Maybe File) File File File deriving(Show)
data BatteryState = BatFull | BatLoading | BatDraining
pnowPath :: String -> String
pnowPath e = "/sys/class/power_supply/" ++ e ++ "/power_now"
enowPath :: String -> String
enowPath e = "/sys/class/power_supply/" ++ e ++ "/energy_now"
efullPath :: String -> String
efullPath e = "/sys/class/power_supply/" ++ e ++ "/energy_full"
vnowPath :: String -> String
vnowPath e = "/sys/class/power_supply/" ++ e ++ "/voltage_now"
cnowPath :: String -> String
cnowPath e = "/sys/class/power_supply/" ++ e ++ "/current_now"
cavgPath :: String -> String
cavgPath e = "/sys/class/power_supply/" ++ e ++ "/current_avg"
chnowPath :: String -> String
chnowPath e = "/sys/class/power_supply/" ++ e ++ "/charge_now"
chfullPath :: String -> String
chfullPath e = "/sys/class/power_supply/" ++ e ++ "/charge_full"
adpPath :: String -> String
adpPath e = "/sys/class/power_supply/"++ e ++"/online"
getCurrentStatusInt :: File -> IO Int
getCurrentStatusInt = readValue
getCurrentStatusM :: BatteryHandle -> IO Int
getCurrentStatusM (BatH (PowerNow _ _ _ adp) _) =
getCurrentStatusInt adp
getCurrentStatusM (BatH (ChargeNow _ _ _ _ _ adp) _) =
getCurrentStatusInt adp
getCurrentStatus :: BatteryHandle -> IO BatteryState
getCurrentStatus h = do
val <- getCurrentStatusM h
case val of
1 -> return BatLoading
0 -> return BatDraining
_ -> return BatFull
getCurrentLevelInt :: File -> File -> IO Int
getCurrentLevelInt n f = do
now <- readValue n
full <- readValue f
return $ now * 100 `div` full
getCurrentLevel :: BatteryHandle -> IO Int
getCurrentLevel (BatH (PowerNow _ now full _) _) =
getCurrentLevelInt now full
getCurrentLevel (BatH (ChargeNow _ _ _ now full _) _) =
getCurrentLevelInt now full
getTimeLeftInt :: File -> File -> File -> Int -> File -> IO (Int, Int)
getTimeLeftInt n c f s adp = do
online <- getCurrentStatusInt adp
now <- readValue n
full <- readValue f
let gap = if online == 0 then now else full now
change <- readValue c
let avg = (change * 20 + s * 80) `div` 100
return (sdivUBound gap (avg `div` 3600) 0, avg)
getLoading :: BatteryHandle -> IO Float
getLoading (BatH (PowerNow pnow _ _ _) _) = do
power <- readLine pnow
return $(read power :: Float) / 1000000
getLoading (BatH (ChargeNow vnow cnow _ _ _ _) _) = do
voltage <- readLine vnow
current <- readLine cnow
let pow = ((read voltage :: Float) * (read current :: Float)) / 1000000000000
return pow
getTimeLeft :: BatteryHandle -> IO Int
getTimeLeft (BatH (PowerNow pnow enow efull adp) s)= do
c <- readIORef s
(t, n) <- getTimeLeftInt enow pnow efull c adp
writeIORef s n
return t
getTimeLeft (BatH (ChargeNow _ cnow cavg chnow chfull adp) s)= do
c <- readIORef s
(t, _) <- getTimeLeftInt chnow (fromMaybe cnow cavg) chfull c adp
return $ (floor . sqrt $(fromIntegral t :: Float)) * 60
createPowerNowHandle :: String -> String -> IO BatteryHandle
createPowerNowHandle e b = do
power_now <- fopen $ pnowPath b
energy_now <- fopen $ enowPath b
energy_full <- fopen $ efullPath b
adp_online <- fopen $ adpPath e
ref <- newIORef (0 :: Int)
return $BatH (PowerNow power_now energy_now energy_full adp_online) ref
createChargeNowHandle :: String -> String -> IO BatteryHandle
createChargeNowHandle e b = do
voltage_now <- fopen $ vnowPath b
current_now <- fopen $ cnowPath b
exists <- doesFileExist $ cavgPath b
current_avg <- if exists then Just <$> fopen (cavgPath b) else return Nothing
charge_now <- fopen $ chnowPath b
charge_full <- fopen $ chfullPath b
adp_online <- fopen $ adpPath e
ref <- newIORef (0 :: Int)
return $BatH (ChargeNow voltage_now current_now current_avg charge_now charge_full adp_online) ref
getBatteryHandle :: String
-> String
-> IO BatteryHandle
getBatteryHandle e b = do
exists <- doesFileExist $ pnowPath b
if exists
then createPowerNowHandle e b
else createChargeNowHandle e b
getBatteryHandle' :: String -> IO BatteryHandle
getBatteryHandle' = flip getBatteryHandle "BAT0"