aboutsummaryrefslogtreecommitdiffstats
path: root/home/bt.nix
blob: b41950a8a48c95096cc8a4ccfde0d0e1086254e7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
{ 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
    '';
  };
}