Bluetooth Power On after Sleep

Do you also always have to enable your Bluetooth on your Linux device when login after wakeup from suspend?

Then prepare your system with this systemd system-sleep hook script!
The just updated version also restores the state from before suspend, when ENABLE_STATUS is yes.

# cat >/usr/lib/systemd/system-sleep/bluetooth-resume.sh <<'EOF'
#!/bin/sh

CONFIG_FILE="/etc/systemd/bluetooth-resume.conf"

PATH="/usr/bin:/usr/sbin:/bin:/sbin"

DEVICE=hci0
ENABLED=yes
ENABLE_STATUS=yes
STATUS=on

[ -f "$CONFIG_FILE" ] && . "$CONFIG_FILE"

[ "X$ENABLED" = "Xyes" ] || {
    echo "bluetooth-resume: not enabled" | logger
    exit 0
}

rc=0

[ "$1" = "pre" ] && [ "X$ENABLE_STATUS" = "Xyes" ] && {
    busctl get-property org.bluez /org/bluez/$DEVICE org.bluez.Adapter1 Powered | grep -q true && {
        sed -i 's/^STATUS=.*$/STATUS=on  # this is set by bluetooth-resume/' "$CONFIG_FILE"
        echo "bluetooth-resume: updated status to <on>" | logger
    } || {
        sed -i 's/^STATUS=.*$/STATUS=off # this is set by bluetooth-resume/' "$CONFIG_FILE"
        echo "bluetooth-resume: updated status to <off>" | logger
    }
}

[ "$1" = "post" ] && {
    status=$(echo "$STATUS" | tr 'A-Z' 'a-z')
    [ "X$ENABLE_STATUS" = "Xyes" ] && [ "X$STATUS" != "Xon" ] && status=off

    i=0
    while [ $i -lt 10 ]; do
        controller=$(bluetoothctl list 2>/dev/null | head -n 1)
        [ -n "$controller" ] && {
            echo "bluetooth-resume: controller ready" | logger
            break
        } || {
            echo "bluetooth-resume: controller not ready" | logger
            i=$((i + 1))
            sleep 1
        }
    done

    busctl get-property org.bluez /org/bluez/$DEVICE org.bluez.Adapter1 Powered | grep -q true && {
        echo "bluetooth-resume: status <on>" | logger
        [ "X$status" = "Xon" ] && exit 0
    } || {
        echo "bluetooth-resume: status <off>" | logger
        [ "X$status" != "Xon" ] && exit 0
    }

    rfkill list | grep -A2 "$DEVICE" | cut -d':' -f2 | grep -q yes && {
        devnr=$(rfkill list | grep "$DEVICE" | cut -d':' -f1)
        [ -n "$devnr" ] && rfkill unblock "$devnr" && {
            i=0
            while rfkill list | grep -A2 "$DEVICE" | cut -d':' -f2 | grep -q yes ; do
                i=$((i + 1))
                [ $i -lt 10 ] || break
                sleep 1
            done
            echo "bluetooth-resume: $DEVICE unblocked" | logger
        } || {
            echo "bluetooth-resume: rfkill unblock fail" | logger
        }
    }

    i=0    
    while [ $i -lt 3 ] ; do
        sleep 1
        busctl get-property org.bluez /org/bluez/$DEVICE org.bluez.Adapter1 Powered | grep -q true && {
            echo "bluetooth-resume: status <on>" | logger
            [ "X$status" = "Xon" ] && exit 0
        } || {
            echo "bluetooth-resume: status <off>" | logger
            [ "X$status" != "Xon" ] && exit 0
        }
        i=$((i + 1))
    done

    bluetoothctl power $status
    rc=$?
    [ $rc -eq 0 ] && {
        echo "bluetooth-resume: bluetoothctl power $status" | logger
    } || {
        echo "bluetooth-resume: bluetoothctl fail (rc $rc)" | logger
    } 
}

exit $rc
EOF

chmod +x /usr/lib/systemd/system-sleep/bluetooth-resume.sh

And the optional configuration file to have a place to disable the hook temporarly:

# cat >/etc/systemd/bluetooth-resume.conf <<'EOF'
# config file for /usr/lib/systemd/system-sleep/bluetooth-resume.sh

DEVICE=hci0
ENABLED=yes
ENABLED_STATUS=yes
STATUS=on  # this is set by bluetooth-resume
EOF