{ config, pkgs, ... }: { systemd.user.services.bt-notify = { Unit = { Description = "Bluetooth Connection & Battery Notifications"; After = [ "graphical-session.target" ]; ConditionPathExists = "${config.home.homeDirectory}/.local/bin/bt-notify.sh"; }; Install = { WantedBy = [ "graphical-session.target" ]; }; Service = { Type = "simple"; ExecStart = "${config.home.homeDirectory}/.local/bin/bt-notify.sh"; Restart = "always"; RestartSec = 5; }; }; home.file."/.local/bin/bt-notify.sh" = { source = pkgs.writeShellScript "bt-notify" '' set -euo pipefail # Temporary file to remember which devices were connected last loop STATE_FILE="/tmp/bt-connected-state" # Ensure the file exists touch "$STATE_FILE" # Listen to BlueZ D-Bus signals AND poll for battery (some devices only report on poll) ( # D-Bus listener (connection events) ${pkgs.dbus}/bin/dbus-monitor "interface=org.bluez.Device1,member=PropertiesChanged" --system & # Polling loop for battery (runs in background) while true; do ${pkgs.bluez}/bin/bluetoothctl devices | cut -f2 -d' ' | while read -r mac; do info=$(${pkgs.bluez}/bin/bluetoothctl info "$mac") name=$(echo "$info" | grep -i "Alias" | cut -d' ' -f2-) connected=$(echo "$info" | grep -i "Connected" | awk '{print $2}') battery_line=$(echo "$info" | grep -i "Battery Percentage" || true) battery=$(echo "$battery_line" | awk '{print $3}' | tr -d '()') # --- Connection change detection --- if [[ "$connected" == "yes" ]] && ! grep -q "^$mac$" "$STATE_FILE"; then ${pkgs.libnotify}/bin/notify-send -a "Bluetooth" "Connected" "$name" echo "$mac" >> "$STATE_FILE" elif [[ "$connected" == "no" ]] && grep -q "^$mac$" "$STATE_FILE"; then ${pkgs.libnotify}/bin/notify-send -a "Bluetooth" "Disconnected" "$name" sed -i "/^$mac$/d" "$STATE_FILE" fi # --- Low battery warning --- if [[ -n "$battery" && "$battery" -lt 20 ]]; then ${pkgs.libnotify}/bin/notify-send -u critical -a "Bluetooth" "Low Battery" "$name: ''${battery}%" fi done sleep 10 done & ) | while read -r line; do # Parse D-Bus PropertiesChanged for Connected if echo "$line" | grep -q '"Connected"'; then path=$(echo "$line" | grep -oP 'path="\K[^"]+') mac=$(basename "$path") info=$(${pkgs.bluez}/bin/bluetoothctl info "$mac") name=$(echo "$info" | grep -i "Alias" | cut -d' ' -f2-) connected=$(echo "$info" | grep -i "Connected" | awk '{print $2}') if [[ "$connected" == "yes" ]] && ! grep -q "^$mac$" "$STATE_FILE"; then ${pkgs.libnotify}/bin/notify-send -a "Bluetooth" "Connected" "$name" echo "$mac" >> "$STATE_FILE" elif [[ "$connected" == "no" ]] && grep -q "^$mac$" "$STATE_FILE"; then ${pkgs.libnotify}/bin/notify-send -a "Bluetooth" "Disconnected" "$name" sed -i "/^$mac$/d" "$STATE_FILE" fi fi done ''; }; }