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

81 lines
3.1 KiB
Nix
Raw Normal View History

2018-05-31 12:03:03 +00:00
{ lib, pkgs, config, ... }:
2018-05-26 20:48:33 +00:00
let
2020-01-08 00:14:05 +00:00
inherit (import ../lib/default.nix) writeHaskellScript;
battery-watch = writeHaskellScript {
name = "battery-watch";
libraries = [
pkgs.haskellPackages.fdo-notify
pkgs.haskellPackages.megaparsec
pkgs.haskellPackages.replace-megaparsec
];
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
'';
2018-05-26 20:48:33 +00:00
in {
2018-05-31 10:34:48 +00:00
2018-05-26 20:48:33 +00:00
systemd.user = {
services.battery = {
2019-07-31 21:56:52 +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";
};
2020-01-29 21:29:42 +00:00
Install = { WantedBy = [ "default.target" ]; };
2018-05-26 20:48:33 +00:00
};
};
2018-05-31 10:34:48 +00:00
2018-05-26 20:48:33 +00:00
}