1
0
Fork 0

Change battery watcher to Haskell

This commit is contained in:
Malte Brandy 2020-01-08 01:14:05 +01:00
parent 0c0fb335b8
commit 5a8cd6624c
No known key found for this signature in database
GPG key ID: 226A2D41EF5378C9
2 changed files with 57 additions and 18 deletions

View file

@ -1,32 +1,70 @@
{ lib, pkgs, config, ... }:
let
battery-watch = pkgs.writeScript "battery-watch" ''
#!${pkgs.stdenv.shell}
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"
];
} ''
criticalLevel = 20 -- percent
minutes = 60 * 1000 * 1000 -- threadDelay takes microseconds
critical_level=20 #percent
main = do
client <- connectSession
let loop = \handleMay -> 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
let NextAction { note = noteMay , delay = delay } = chooseAction chargerOnline batteryLevel
handle <- if | Just note <- noteMay -> Just <$> maybe (notify client note) (flip (replace client) note) handleMay
| otherwise -> pure handleMay
echo ([i|Waiting for #{delay} minutes until next message.|] :: String)
threadDelay $ delay * minutes
loop handle
loop Nothing
export PATH=$PATH:${pkgs.coreutils}/bin:${pkgs.gnugrep}/bin:${pkgs.gnused}/bin
data NextAction = NextAction { note :: Maybe Note, delay :: Int }
while true
do
if [ "$(${pkgs.acpi}/bin/acpi -a | grep -o off)" == "off" ]; then
battery_level=`${pkgs.acpi}/bin/acpi -b | sed 's/.*[dg], //g;s/\%,.*//g'`
if [ $battery_level -le $critical_level ]; then
${pkgs.libnotify}/bin/notify-send 'Battery level is low!' "Only $battery_level% of the charge remains."
else
${pkgs.libnotify}/bin/notify-send 'Battery level is discharging!' "Only $battery_level% of the charge remains."
sleep 18m
fi
fi
sleep 2m
done
type Parser = Parsec Text LT.Text
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 <* "%")
chooseAction :: Bool -> Int -> NextAction
chooseAction chargerOnline batteryLevel
| chargerOnline = NextAction Nothing 1
| batteryLevel <= criticalLevel = mkMsg $ myNote {summary = "Battery is low!"}
| otherwise = mkMsg $ myNote {summary = "Battery is discharging!"}
where
mkMsg = flip NextAction (max 1 (batteryLevel `div` 5)) . Just
myNote = blankNote { body = Just $ Text [i|Only #{batteryLevel}% remaining.|]}
'';
in {
systemd.user = {
services.battery = {
Unit = { Description = "Watch battery state and warn user"; };
Service = { ExecStart = toString battery-watch; };
Service = {
ExecStart = "${battery-watch}/bin/battery-watch";
Restart = "always";
};
Install = { WantedBy = [ "graphical-session.target" ]; };
};
};

View file

@ -55,6 +55,7 @@ rec {
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ExtendedDefaultRules #-}
{-# LANGUAGE MultiWayIf #-}
import Shh
import qualified Prelude