1
0
Fork 0
nixos-config/home-manager/roles/battery.nix

79 lines
2.9 KiB
Nix
Raw Normal View History

2022-03-08 01:42:46 +00:00
{
lib,
pkgs,
config,
...
}: let
2021-05-18 14:33:28 +00:00
battery-watch = pkgs.writeHaskellScript
2022-03-08 01:42:46 +00:00
{
name = "battery-watch";
bins = [pkgs.acpi];
imports = [
"DBus.Notify"
"Control.Concurrent"
"Text.Megaparsec"
"Text.Megaparsec.Char"
"Text.Megaparsec.Char.Lexer"
"Replace.Megaparsec"
"Data.Maybe"
];
} ''
2020-01-13 20:12:38 +00:00
moderateLevel = 50 -- percent
lowLevel = 20 -- percent
criticalLevel = 8 -- percent
minute = 60 * 1000 * 1000 -- threadDelay takes microseconds
2020-01-08 00:14:05 +00:00
main = do
client <- connectSession
2020-01-13 20:12:38 +00:00
let loop = \lastState handleMay -> do
newState <- getState
let noteMay = chooseAction lastState newState
2020-01-08 00:14:05 +00:00
handle <- if | Just note <- noteMay -> Just <$> maybe (notify client note) (flip (replace client) note) handleMay
| otherwise -> pure handleMay
2020-01-13 20:12:38 +00:00
threadDelay $ minute `div` 4
loop newState handle
loop (BatState True 100) Nothing
2020-01-08 00:14:05 +00:00
2020-01-13 20:12:38 +00:00
data BatState = BatState { charging :: Bool, level :: Int }
getState = do
batteryStateText <- decodeUtf8 <$> (acpi "-a" |> captureTrim)
batteryLevelText <- decodeUtf8 <$> (acpi "-b" |> captureTrim)
chargerOnline <- maybe (fail "Couldnt get charging state") pure $ parseMaybe onlineParser batteryStateText
batteryLevel <- maybe (fail "Couldnt get battery level") pure $ parseMaybe levelParser batteryLevelText
pure $ BatState chargerOnline batteryLevel
2020-01-08 00:14:05 +00:00
2020-01-19 16:40:02 +00:00
type Parser = Parsec Text LText
2020-01-08 00:14:05 +00:00
onlineParser :: Parser Bool
onlineParser = not . null . rights <$> sepCap (string "on-line")
levelParser :: Parser Int
levelParser = (maybe (fail "No Number found") pure . listToMaybe . rights) =<< sepCap (decimal <* "%")
2020-01-13 20:12:38 +00:00
chooseAction :: BatState -> BatState -> Maybe Note
chooseAction (BatState wasCharging lastLevel) (BatState isCharging currentLevel)
| wasCharging && isCharging = Nothing
| wasCharging && not isCharging = Just $ myNote{summary = "Charger disconnected." }
| not wasCharging && isCharging = Just $ myNote{summary = "Charger connected.", expiry = Milliseconds 5000 }
| currentLevel <= criticalLevel = Just $ myNote{summary = "Battery is very low!" }
| currentLevel <= lowLevel && currentLevel < lastLevel = Just $ myNote{summary = "Battery is low!"}
| ((currentLevel `mod` 5 == 0 && currentLevel <= moderateLevel) || (currentLevel `mod` 10 == 0)) && currentLevel < lastLevel = Just $ myNote{summary = "Battery is discharging."}
| otherwise = Nothing
2020-01-08 00:14:05 +00:00
where
2020-01-13 20:12:38 +00:00
myNote = blankNote { body = Just $ Text [i|#{currentLevel}% remaining.|]}
2019-07-31 21:56:52 +00:00
'';
2022-03-08 01:42:46 +00:00
in {
2018-05-26 20:48:33 +00:00
systemd.user = {
services.battery = {
2020-12-17 01:26:47 +00:00
Unit.Description = "Watch battery state and warn user";
2020-01-08 00:14:05 +00:00
Service = {
ExecStart = "${battery-watch}/bin/battery-watch";
Restart = "always";
RestartSec = 60;
2020-01-08 00:14:05 +00:00
};
2022-03-08 01:42:46 +00:00
Install.WantedBy = ["default.target"];
2018-05-26 20:48:33 +00:00
};
};
}