feat: nb add battery max charge option and quick change for it
This commit is contained in:
parent
8f2a1e1357
commit
92a216c920
5 changed files with 136 additions and 73 deletions
|
|
@ -5,9 +5,10 @@
|
||||||
{ config, lib, pkgs, ... }:
|
{ config, lib, pkgs, ... }:
|
||||||
let
|
let
|
||||||
impermanence = builtins.fetchTarball "https://github.com/nix-community/impermanence/archive/master.tar.gz";
|
impermanence = builtins.fetchTarball "https://github.com/nix-community/impermanence/archive/master.tar.gz";
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
nixpkgs.config.allowUnfree = true;
|
nixpkgs.config.allowUnfree = true;
|
||||||
nixpkgs.config.allowBroken = true;
|
nixpkgs.config.allowBroken = true;
|
||||||
|
|
||||||
security.pki.certificates = [ "/home/dominik/.local/share/mkcert/rootCA.pem" ];
|
security.pki.certificates = [ "/home/dominik/.local/share/mkcert/rootCA.pem" ];
|
||||||
|
|
||||||
|
|
@ -30,6 +31,7 @@ in {
|
||||||
./modules/ollama.nix
|
./modules/ollama.nix
|
||||||
./modules/qdrant.nix
|
./modules/qdrant.nix
|
||||||
./modules/battery-brightness.nix
|
./modules/battery-brightness.nix
|
||||||
|
./modules/charge-control.nix
|
||||||
./modules/suspend-fixes.nix
|
./modules/suspend-fixes.nix
|
||||||
|
|
||||||
./cachix.nix
|
./cachix.nix
|
||||||
|
|
@ -71,9 +73,9 @@ in {
|
||||||
programs.zsh = {
|
programs.zsh = {
|
||||||
enable = true;
|
enable = true;
|
||||||
ohMyZsh = {
|
ohMyZsh = {
|
||||||
enable = true; # Enable Oh My Zsh
|
enable = true; # Enable Oh My Zsh
|
||||||
theme = "steeef"; # Set theme
|
theme = "steeef"; # Set theme
|
||||||
plugins = [ "git" ]; # Add plugins
|
plugins = [ "git" ]; # Add plugins
|
||||||
};
|
};
|
||||||
interactiveShellInit = ''
|
interactiveShellInit = ''
|
||||||
# Bind Shift+Return to insert newline (foot terminal sends \e[27;2;13~)
|
# Bind Shift+Return to insert newline (foot terminal sends \e[27;2;13~)
|
||||||
|
|
@ -90,10 +92,10 @@ in {
|
||||||
# Disable irqbalance to save battery (not critical for laptop workloads)
|
# Disable irqbalance to save battery (not critical for laptop workloads)
|
||||||
services.irqbalance.enable = false;
|
services.irqbalance.enable = false;
|
||||||
|
|
||||||
swapDevices = [ {
|
swapDevices = [{
|
||||||
device = "/swap/swapfile";
|
device = "/swap/swapfile";
|
||||||
size = 96 * 1024; # Size is in megabytes (96GB for full hibernation with 92GB RAM)
|
size = 96 * 1024; # Size is in megabytes (96GB for full hibernation with 92GB RAM)
|
||||||
} ];
|
}];
|
||||||
|
|
||||||
# Memory tuning for 92GB RAM
|
# Memory tuning for 92GB RAM
|
||||||
boot.kernel.sysctl = {
|
boot.kernel.sysctl = {
|
||||||
|
|
@ -102,8 +104,8 @@ in {
|
||||||
"vm.dirty_background_ratio" = 5;
|
"vm.dirty_background_ratio" = 5;
|
||||||
"vm.vfs_cache_pressure" = 50;
|
"vm.vfs_cache_pressure" = 50;
|
||||||
# Battery optimization - increase dirty writeback time to batch writes
|
# Battery optimization - increase dirty writeback time to batch writes
|
||||||
"vm.dirty_writeback_centisecs" = 3000; # 30 seconds (default: 500 = 5s)
|
"vm.dirty_writeback_centisecs" = 3000; # 30 seconds (default: 500 = 5s)
|
||||||
"vm.dirty_expire_centisecs" = 3000; # 30 seconds (default: 3000)
|
"vm.dirty_expire_centisecs" = 3000; # 30 seconds (default: 3000)
|
||||||
# Enable laptop mode for disk power management (2 = balanced, less aggressive than 5)
|
# Enable laptop mode for disk power management (2 = balanced, less aggressive than 5)
|
||||||
"vm.laptop_mode" = 2;
|
"vm.laptop_mode" = 2;
|
||||||
};
|
};
|
||||||
|
|
@ -131,7 +133,7 @@ in {
|
||||||
};
|
};
|
||||||
|
|
||||||
hardware.bluetooth.enable = true;
|
hardware.bluetooth.enable = true;
|
||||||
hardware.bluetooth.powerOnBoot = false; # Save battery - enable manually when needed
|
hardware.bluetooth.powerOnBoot = false; # Save battery - enable manually when needed
|
||||||
hardware.bluetooth.settings = {
|
hardware.bluetooth.settings = {
|
||||||
General = { ControllerMode = "bredr"; };
|
General = { ControllerMode = "bredr"; };
|
||||||
};
|
};
|
||||||
|
|
@ -171,12 +173,12 @@ in {
|
||||||
sops.age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ];
|
sops.age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ];
|
||||||
sops.defaultSopsFile = ./secrets.yaml;
|
sops.defaultSopsFile = ./secrets.yaml;
|
||||||
|
|
||||||
sops.secrets.epicenter_vpn_ca = {};
|
sops.secrets.epicenter_vpn_ca = { };
|
||||||
sops.secrets.epicenter_vpn_cert = {};
|
sops.secrets.epicenter_vpn_cert = { };
|
||||||
sops.secrets.epicenter_vpn_key = {};
|
sops.secrets.epicenter_vpn_key = { };
|
||||||
sops.secrets.wg_private_key = {};
|
sops.secrets.wg_private_key = { };
|
||||||
sops.secrets.wg_preshared_key = {};
|
sops.secrets.wg_preshared_key = { };
|
||||||
sops.secrets.wg-cloonar-key = {};
|
sops.secrets.wg-cloonar-key = { };
|
||||||
|
|
||||||
virtualisation.docker.enable = true;
|
virtualisation.docker.enable = true;
|
||||||
services.flatpak.enable = true;
|
services.flatpak.enable = true;
|
||||||
|
|
@ -189,7 +191,7 @@ in {
|
||||||
};
|
};
|
||||||
|
|
||||||
networking.hostName = "nb-01"; # Define your hostname.
|
networking.hostName = "nb-01"; # Define your hostname.
|
||||||
networking.networkmanager.enable = true; # Easiest to use and most distros use this by default.
|
networking.networkmanager.enable = true; # Easiest to use and most distros use this by default.
|
||||||
networking.extraHosts = ''
|
networking.extraHosts = ''
|
||||||
77.119.230.30 vpn.cloonar.com
|
77.119.230.30 vpn.cloonar.com
|
||||||
23.88.38.1 api.ebs.amz.at
|
23.88.38.1 api.ebs.amz.at
|
||||||
|
|
@ -206,7 +208,7 @@ in {
|
||||||
extraGroups = [ "wheel" "disk" "video" "audio" "mysql" "docker" "vboxusers" "networkmanager" "onepassword" "onepassword-cli" "dialout" ]; # Enable ‘sudo’ for the user.
|
extraGroups = [ "wheel" "disk" "video" "audio" "mysql" "docker" "vboxusers" "networkmanager" "onepassword" "onepassword-cli" "dialout" ]; # Enable ‘sudo’ for the user.
|
||||||
};
|
};
|
||||||
|
|
||||||
users.groups.dominik = {};
|
users.groups.dominik = { };
|
||||||
|
|
||||||
environment.systemPackages = with pkgs; [
|
environment.systemPackages = with pkgs; [
|
||||||
alsa-utils
|
alsa-utils
|
||||||
|
|
@ -219,7 +221,7 @@ in {
|
||||||
TERMINAL_COMMAND = "alacritty";
|
TERMINAL_COMMAND = "alacritty";
|
||||||
MOZ_ENABLE_WAYLAND = "1";
|
MOZ_ENABLE_WAYLAND = "1";
|
||||||
};
|
};
|
||||||
|
|
||||||
services.blueman.enable = true;
|
services.blueman.enable = true;
|
||||||
|
|
||||||
security.rtkit.enable = true;
|
security.rtkit.enable = true;
|
||||||
|
|
@ -241,21 +243,21 @@ in {
|
||||||
wants = [ "graphical-session.target" ];
|
wants = [ "graphical-session.target" ];
|
||||||
after = [ "graphical-session.target" ];
|
after = [ "graphical-session.target" ];
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
Type = "simple";
|
Type = "simple";
|
||||||
ExecStart = "${pkgs.polkit_gnome}/libexec/polkit-gnome-authentication-agent-1";
|
ExecStart = "${pkgs.polkit_gnome}/libexec/polkit-gnome-authentication-agent-1";
|
||||||
Restart = "on-failure";
|
Restart = "on-failure";
|
||||||
RestartSec = 1;
|
RestartSec = 1;
|
||||||
TimeoutStopSec = 10;
|
TimeoutStopSec = 10;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
# pgp
|
# pgp
|
||||||
services.pcscd.enable = true;
|
services.pcscd.enable = true;
|
||||||
programs.gnupg.agent = {
|
programs.gnupg.agent = {
|
||||||
enable = true;
|
enable = true;
|
||||||
enableSSHSupport = true;
|
enableSSHSupport = true;
|
||||||
pinentryPackage = pkgs.pinentry-curses;
|
pinentryPackage = pkgs.pinentry-curses;
|
||||||
};
|
};
|
||||||
|
|
||||||
nix = {
|
nix = {
|
||||||
|
|
|
||||||
91
hosts/nb/modules/charge-control.nix
Normal file
91
hosts/nb/modules/charge-control.nix
Normal file
|
|
@ -0,0 +1,91 @@
|
||||||
|
{ pkgs, ... }:
|
||||||
|
let
|
||||||
|
charge-limit-apply = pkgs.writeShellScriptBin "charge-limit-apply" ''
|
||||||
|
if [ "$1" != "80" ] && [ "$1" != "100" ]; then
|
||||||
|
echo "Usage: charge-limit-apply <80|100>" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
${pkgs.fw-ectool}/bin/ectool fwchargelimit "$1"
|
||||||
|
echo "$1" > /run/fw-charge-limit
|
||||||
|
chmod 644 /run/fw-charge-limit
|
||||||
|
'';
|
||||||
|
|
||||||
|
charge-limit-menu = pkgs.writeShellScriptBin "charge-limit-menu" ''
|
||||||
|
choice=$(printf "80%%\n100%%" | ${pkgs.wofi}/bin/wofi --dmenu --prompt "Charge limit")
|
||||||
|
case "$choice" in
|
||||||
|
"80%") /run/wrappers/bin/sudo ${charge-limit-apply}/bin/charge-limit-apply 80 ;;
|
||||||
|
"100%") /run/wrappers/bin/sudo ${charge-limit-apply}/bin/charge-limit-apply 100 ;;
|
||||||
|
esac
|
||||||
|
'';
|
||||||
|
|
||||||
|
waybar-battery = pkgs.writeShellScriptBin "waybar-battery" ''
|
||||||
|
charging_icons=("" "" "" "" "" "" "" "" "" "")
|
||||||
|
default_icons=("" "" "" "" "" "" "" "" "" "")
|
||||||
|
|
||||||
|
bat_path=$(echo /sys/class/power_supply/BAT*)
|
||||||
|
capacity=$(cat "$bat_path/capacity" 2>/dev/null || echo 0)
|
||||||
|
status=$(cat "$bat_path/status" 2>/dev/null || echo "Unknown")
|
||||||
|
limit=$(cat /run/fw-charge-limit 2>/dev/null || echo 80)
|
||||||
|
|
||||||
|
# Select icon based on capacity (10 icons, index 0-9)
|
||||||
|
idx=$(( capacity / 11 ))
|
||||||
|
if [ "$idx" -gt 9 ]; then idx=9; fi
|
||||||
|
|
||||||
|
if [ "$status" = "Charging" ]; then
|
||||||
|
icon="''${charging_icons[$idx]}"
|
||||||
|
else
|
||||||
|
icon="''${default_icons[$idx]}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Determine CSS class
|
||||||
|
class=""
|
||||||
|
if [ "$capacity" -le 15 ]; then
|
||||||
|
class="critical"
|
||||||
|
elif [ "$capacity" -le 30 ]; then
|
||||||
|
class="warning"
|
||||||
|
elif [ "$capacity" -ge 95 ]; then
|
||||||
|
class="good"
|
||||||
|
fi
|
||||||
|
|
||||||
|
tooltip="Battery: ''${capacity}% [''${status}]\nCharge limit: ''${limit}%"
|
||||||
|
|
||||||
|
${pkgs.jq}/bin/jq -cn \
|
||||||
|
--arg text "$icon ''${capacity}% (''${limit}%)" \
|
||||||
|
--arg tooltip "$tooltip" \
|
||||||
|
--arg class "$class" \
|
||||||
|
'{text: $text, tooltip: $tooltip, class: $class}'
|
||||||
|
'';
|
||||||
|
in
|
||||||
|
{
|
||||||
|
environment.systemPackages = [
|
||||||
|
pkgs.fw-ectool
|
||||||
|
charge-limit-apply
|
||||||
|
charge-limit-menu
|
||||||
|
waybar-battery
|
||||||
|
];
|
||||||
|
|
||||||
|
security.sudo.extraRules = [
|
||||||
|
{
|
||||||
|
users = [ "dominik" ];
|
||||||
|
commands = [
|
||||||
|
{
|
||||||
|
command = "${charge-limit-apply}/bin/charge-limit-apply";
|
||||||
|
options = [ "NOPASSWD" ];
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
systemd.services.fw-charge-limit = {
|
||||||
|
description = "Set Framework charge limit on boot";
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
ExecStart = "${pkgs.writeShellScript "fw-charge-limit-init" ''
|
||||||
|
${pkgs.fw-ectool}/bin/ectool fwchargelimit 80
|
||||||
|
echo 80 > /run/fw-charge-limit
|
||||||
|
chmod 644 /run/fw-charge-limit
|
||||||
|
''}";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -13,9 +13,10 @@ let
|
||||||
sessionsFontSize = 24;
|
sessionsFontSize = 24;
|
||||||
usersFontSize = 32;
|
usersFontSize = 32;
|
||||||
};
|
};
|
||||||
variants = ["qt5"];
|
variants = [ "qt5" ];
|
||||||
};
|
};
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
imports = [
|
imports = [
|
||||||
../sway/sway.nix
|
../sway/sway.nix
|
||||||
../sway/launcher-cleanup.nix
|
../sway/launcher-cleanup.nix
|
||||||
|
|
@ -115,7 +116,7 @@ in {
|
||||||
programs.light.enable = true;
|
programs.light.enable = true;
|
||||||
|
|
||||||
hardware.bluetooth.enable = true;
|
hardware.bluetooth.enable = true;
|
||||||
hardware.bluetooth.powerOnBoot = false; # Save battery - enable manually when needed
|
hardware.bluetooth.powerOnBoot = false; # Save battery - enable manually when needed
|
||||||
hardware.bluetooth.settings = {
|
hardware.bluetooth.settings = {
|
||||||
General = { ControllerMode = "bredr"; };
|
General = { ControllerMode = "bredr"; };
|
||||||
};
|
};
|
||||||
|
|
@ -162,7 +163,7 @@ in {
|
||||||
USB_EXCLUDE_PHONE = 0;
|
USB_EXCLUDE_PHONE = 0;
|
||||||
USB_EXCLUDE_PRINTER = 1;
|
USB_EXCLUDE_PRINTER = 1;
|
||||||
USB_EXCLUDE_WWAN = 0;
|
USB_EXCLUDE_WWAN = 0;
|
||||||
USB_EXCLUDE_INPUT = 1; # Exclude keyboard/touchpad to prevent suspend issues
|
USB_EXCLUDE_INPUT = 1; # Exclude keyboard/touchpad to prevent suspend issues
|
||||||
|
|
||||||
# Audio power saving
|
# Audio power saving
|
||||||
SOUND_POWER_SAVE_ON_AC = 0;
|
SOUND_POWER_SAVE_ON_AC = 0;
|
||||||
|
|
@ -173,9 +174,6 @@ in {
|
||||||
DISK_IDLE_SECS_ON_AC = 0;
|
DISK_IDLE_SECS_ON_AC = 0;
|
||||||
DISK_IDLE_SECS_ON_BAT = 2;
|
DISK_IDLE_SECS_ON_BAT = 2;
|
||||||
|
|
||||||
# Battery charge thresholds (Framework 13 recommendation)
|
|
||||||
START_CHARGE_THRESH_BAT0 = 60;
|
|
||||||
STOP_CHARGE_THRESH_BAT0 = 80;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
boot.plymouth = {
|
boot.plymouth = {
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@
|
||||||
"cpu",
|
"cpu",
|
||||||
"custom/left-arrow-light",
|
"custom/left-arrow-light",
|
||||||
"custom/left-arrow-dark",
|
"custom/left-arrow-dark",
|
||||||
"battery",
|
"custom/battery",
|
||||||
"custom/left-arrow-light",
|
"custom/left-arrow-light",
|
||||||
"custom/left-arrow-dark",
|
"custom/left-arrow-dark",
|
||||||
"disk",
|
"disk",
|
||||||
|
|
@ -109,39 +109,11 @@
|
||||||
"interval": 5,
|
"interval": 5,
|
||||||
"format": " {usage:2}%"
|
"format": " {usage:2}%"
|
||||||
},
|
},
|
||||||
"battery": {
|
"custom/battery": {
|
||||||
"states": {
|
"exec": "waybar-battery",
|
||||||
"good": 95,
|
"return-type": "json",
|
||||||
"warning": 30,
|
"interval": 10,
|
||||||
"critical": 15
|
"on-click": "charge-limit-menu"
|
||||||
},
|
|
||||||
"format": "{icon} {capacity}%",
|
|
||||||
"format-icons": {
|
|
||||||
"charging": [
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
""
|
|
||||||
],
|
|
||||||
"default": [
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
""
|
|
||||||
]
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
"disk": {
|
"disk": {
|
||||||
"interval": 5,
|
"interval": 5,
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ window#waybar {
|
||||||
#pulseaudio,
|
#pulseaudio,
|
||||||
#memory,
|
#memory,
|
||||||
#cpu,
|
#cpu,
|
||||||
#battery,
|
#custom-battery,
|
||||||
#disk,
|
#disk,
|
||||||
#tray {
|
#tray {
|
||||||
background: #252525;
|
background: #252525;
|
||||||
|
|
@ -62,7 +62,7 @@ window#waybar {
|
||||||
#cpu {
|
#cpu {
|
||||||
color: #bd93f9;
|
color: #bd93f9;
|
||||||
}
|
}
|
||||||
#battery {
|
#custom-battery {
|
||||||
color: #f1fa8c;
|
color: #f1fa8c;
|
||||||
}
|
}
|
||||||
#disk {
|
#disk {
|
||||||
|
|
@ -77,7 +77,7 @@ window#waybar {
|
||||||
#pulseaudio,
|
#pulseaudio,
|
||||||
#memory,
|
#memory,
|
||||||
#cpu,
|
#cpu,
|
||||||
#battery,
|
#custom-battery,
|
||||||
#disk {
|
#disk {
|
||||||
padding: 0 10px;
|
padding: 0 10px;
|
||||||
padding-left: 5px;
|
padding-left: 5px;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue