From c7cafeba6bc3c1e2f5bbf8444904269869e8d0e3 Mon Sep 17 00:00:00 2001 From: Alexander Bantyev Date: Sun, 26 Sep 2021 15:27:02 +0300 Subject: [PATCH] Use experimental bluetoothd and use upower for battery querying --- profiles/hardware.nix | 8 +- profiles/workspace/i3blocks/default.nix | 2 +- .../workspace/i3blocks/scripts/battery.nix | 103 ++++++++++-------- .../workspace/i3blocks/scripts/bluetooth.nix | 18 --- .../i3blocks/scripts/bluetooth_battery.py | 100 ----------------- 5 files changed, 65 insertions(+), 166 deletions(-) delete mode 100755 profiles/workspace/i3blocks/scripts/bluetooth_battery.py diff --git a/profiles/hardware.nix b/profiles/hardware.nix index e1a1db1..c7cb68b 100644 --- a/profiles/hardware.nix +++ b/profiles/hardware.nix @@ -9,8 +9,12 @@ with deviceSpecific; { hardware.opengl.driSupport32Bit = true; # For steam hardware.opengl.package = pkgs.mesa_drivers; - hardware.bluetooth.enable = true; - hardware.bluetooth.package = pkgs.bluezFull; + hardware.bluetooth = { + enable = true; + package = pkgs.bluezFull; + }; + + systemd.services.bluetooth.serviceConfig.ExecStart = lib.mkForce [ "" "${pkgs.bluezFull}/libexec/bluetooth/bluetoothd -f /etc/bluetooth/main.conf -E" ]; persist.state.directories = [ "/var/lib/bluetooth" ]; diff --git a/profiles/workspace/i3blocks/default.nix b/profiles/workspace/i3blocks/default.nix index 0fa76c2..892a10f 100644 --- a/profiles/workspace/i3blocks/default.nix +++ b/profiles/workspace/i3blocks/default.nix @@ -61,8 +61,8 @@ in { (scrint "freq" 10) (scr "temperature") (scrint "free" 10) - ] ++ optionals config.deviceSpecific.isLaptop [ (scr "battery") + ] ++ optionals config.deviceSpecific.isLaptop [ (scrint "brightness" 5) ] ++ optional (config.deviceSpecific.devInfo ? bigScreen) (scrint "network" 1) ++ [ diff --git a/profiles/workspace/i3blocks/scripts/battery.nix b/profiles/workspace/i3blocks/scripts/battery.nix index 576a1b4..b827b85 100644 --- a/profiles/workspace/i3blocks/scripts/battery.nix +++ b/profiles/workspace/i3blocks/scripts/battery.nix @@ -1,48 +1,61 @@ -{ acpi, bash, iconfont, low_threshold ? 10, ... }: '' +{ upower, bash, iconfont, low_threshold ? 10, ... }: '' #!${bash}/bin/bash - BATTERY="`${acpi}/bin/acpi -b | grep --invert-match unavailable | head -1`" - STATUS=`awk -F'[,:] ' '{print $2}' <<< "$BATTERY"` - CHARGE=`awk -F'[,%] ' '{print $2}' <<< "$BATTERY" | tr -d "%"` - TIME=`awk -F', ' '{print $3}' <<< "$BATTERY" | cut -d " " -f 1 | cut -d: -f1-2` - case "$STATUS" in - Full) ;& "Not charging") icon=; TEXT="FULL"; status=0 - ;; - Charging) - TEXT="$CHARGE% ($TIME)" - status=0 - case $CHARGE in - [2-3]*) icon=;; - [4-5]*) icon=;; - [6-7]*) icon=;; - [8-9]*) icon=;; - 100) icon=;; - *) icon=;; - esac - ;; - Discharging) - if [[ $CHARGE -gt ${toString low_threshold} ]] - then - status=0 - else - status=33 + readarray -t DEVICES <<< "$(${upower}/bin/upower -e | grep -v "DisplayDevice$")" + + DELIM="" + STATUS=0 + + for dev in "''${DEVICES[@]}"; do + INFO="$(${upower}/bin/upower -i "$dev")" + PERCENTAGE="$(echo "$INFO" | grep 'percentage:' | grep -o '[[:digit:]]*')" + if [ -n "$PERCENTAGE" ]; then + STATE="$(echo "$INFO" | grep 'state:' | tr -s ' ' | cut -d' ' -f3)" + if [[ "x$STATE" == "xfully-charged" ]] || [[ "x$STATE" == "xcharging" ]]; then + TIME="$(echo "$INFO" | grep 'time to empty:' | tr -s ' ' | cut -d' ' -f5-6)" + case $PERCENTAGE in + [2-3]*) icon=;; + [4-5]*) icon=;; + [6-7]*) icon=;; + [8-9]*) icon=;; + 100) icon=;; + *) icon=;; + esac + else + if [[ "$PERCENTAGE" -lt ${toString low_threshold} ]]; then + STATUS=33 + fi + TIME="$(echo "$INFO" | grep 'time to full:' | tr -s ' ' | cut -d' ' -f5-6)" + case $PERCENTAGE in + 1?) icon=;; + 2?) icon=;; + 3?) icon=;; + 4?) icon=;; + 5?) icon=;; + 6?) icon=;; + 7?) icon=;; + 8?) icon=;; + 9?) icon=;; + 100) icon=;; + *) icon=;; + esac + fi + if [ -n "$DELIM" ]; then + echo -n "| " + else + DELIM="yes" + fi + echo -n "" + if echo "$INFO" | grep 'native-path:' | grep bluez > /dev/null; then + echo -n "" + fi + echo -n "$icon" + if [ -n "$BLOCK_BUTTON" ]; then + echo -n " $PERCENTAGE% " + if [ -n "$TIME" ]; then echo -n "($TIME) "; fi + fi fi - TEXT="$CHARGE% ($TIME)"; - case $CHARGE in - 1?) icon=;; - 2?) icon=;; - 3?) icon=;; - 4?) icon=;; - 5?) icon=;; - 6?) icon=;; - 7?) icon=;; - 8?) icon=;; - 9?) icon=;; - 100) icon=;; - *) ;; - esac - ;; - esac - [[ -n $BLOCK_BUTTON ]] && text=" $TEXT" - echo "$icon$text" - exit $status + done + + echo + exit "$STATUS" '' diff --git a/profiles/workspace/i3blocks/scripts/bluetooth.nix b/profiles/workspace/i3blocks/scripts/bluetooth.nix index 6071c39..b2738a1 100644 --- a/profiles/workspace/i3blocks/scripts/bluetooth.nix +++ b/profiles/workspace/i3blocks/scripts/bluetooth.nix @@ -16,22 +16,4 @@ echo -n "" fi fi - DEVICE=$(${bluez}/bin/bluetoothctl info | grep -o "[0-9A-F][0-9A-F]:[0-9A-F][0-9A-F]:[0-9A-F][0-9A-F]:[0-9A-F][0-9A-F]:[0-9A-F][0-9A-F]:[0-9A-F][0-9A-F]" | head -1) - CHARGE=$(${python3.withPackages (ps: [ ps.pybluez ])}/bin/python3 ${./bluetooth_battery.py} $DEVICE) - code=0 - case $CHARGE in - 1?) icon=; code=33;; - 2?) icon=; code=33;; - 3?) icon=;; - 4?) icon=;; - 5?) icon=;; - 6?) icon=;; - 7?) icon=;; - 8?) icon=;; - 9?) icon=;; - 100) icon=;; - *) ; code=33;; - esac - echo "$icon" - exit $code '' diff --git a/profiles/workspace/i3blocks/scripts/bluetooth_battery.py b/profiles/workspace/i3blocks/scripts/bluetooth_battery.py deleted file mode 100755 index 2fba0dc..0000000 --- a/profiles/workspace/i3blocks/scripts/bluetooth_battery.py +++ /dev/null @@ -1,100 +0,0 @@ -#!/usr/bin/env python3 - -""" -A python script to get battery level from Bluetooth headsets -""" - -# License: GPL-3.0 -# Author: @TheWeirdDev -# 29 Sept 2019 - -import errno -import bluetooth -import sys - - -def send(sock, message): - sock.send(b"\r\n" + message + b"\r\n") - - -def getATCommand(sock, line, device): - blevel = -1 - - if b"BRSF" in line: - send(sock, b"+BRSF: 1024") - send(sock, b"OK") - elif b"CIND=" in line: - send(sock, b"+CIND: (\"battchg\",(0-5))") - send(sock, b"OK") - elif b"CIND?" in line: - send(sock, b"+CIND: 5") - send(sock, b"OK") - elif b"BIND=?" in line: - # Announce that we support the battery level HF indicator - # https://www.bluetooth.com/specifications/assigned-numbers/hands-free-profile/ - send(sock, b"+BIND: (2)") - send(sock, b"OK") - elif b"BIND?" in line: - # Enable battery level HF indicator - send(sock, b"+BIND: 2,1") - send(sock, b"OK") - elif b"XAPL=" in line: - send(sock, b"+XAPL: iPhone,7") - send(sock, b"OK") - elif b"IPHONEACCEV" in line: - parts = line.strip().split(b',')[1:] - if len(parts) > 1 and (len(parts) % 2) == 0: - parts = iter(parts) - params = dict(zip(parts, parts)) - if b'1' in params: - blevel = (int(params[b'1']) + 1) * 10 - elif b"BIEV=" in line: - params = line.strip().split(b"=")[1].split(b",") - if params[0] == b"2": - blevel = int(params[1]) - else: - send(sock, b"OK") - - if blevel != -1: - print(blevel) - return False - - return True - -def find_rfcomm_port(device): - uuid="0000111e-0000-1000-8000-00805f9b34fb" - proto = bluetooth.find_service(address=device, uuid=uuid) - if len(proto) == 0: - print("Couldn't find the RFCOMM port number") - return 4 - else: - for j in range(len(proto)): - if 'protocol' in proto[j] and proto[j]['protocol'] == 'RFCOMM': - port = proto[j]['port'] - return port - -def main(): - if (len(sys.argv) < 2): - print("Usage: bl_battery.py [.PORT] ...") - print(" Port number is optional") - exit() - else: - for device in sys.argv[1:]: - i = device.find('.') - if i == -1: - port = find_rfcomm_port(device) - else: - port = int(device[i+1:]) - device = device[:i] - try: - s = bluetooth.BluetoothSocket(bluetooth.RFCOMM) - s.connect((device, port)) - while getATCommand(s, s.recv(128), device): - pass - s.close() - except OSError as e: - print(f"{device} is offline", e) - - -if __name__ == "__main__": - main()