Skip to content

Commit

Permalink
fix: use led device for bluetooth sink switch led (#2493)
Browse files Browse the repository at this point in the history
  • Loading branch information
AlvinSchiller authored Feb 8, 2025
1 parent d0447db commit 5b72373
Showing 1 changed file with 22 additions and 37 deletions.
59 changes: 22 additions & 37 deletions components/bluetooth-sink-switch/bt-sink-switch.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,16 @@
cmd = toggle|speakers|headphones : select audio target
debug : enable debug logging
"""

import os
import sys
import re
import subprocess
import logging
import os
import configparser
import time

sys.path.append(os.path.abspath(os.path.dirname(os.path.abspath(__file__)) + "/../gpio_control"))
from GPIODevices import LED # noqa: E402

# Create logger
logger = logging.getLogger('bt-sink-switch.py')
Expand Down Expand Up @@ -79,10 +81,10 @@ def bt_switch(cmd, led_pin=None): # noqa C901
/etc/dbus-1/system.d/bluetooth.conf
Best to check first if the user which later runs this script can execute bluetoothctl and get meaningful results
sudo -u www-data bluetoothctl show
E.g. if you want to do bluetooth manipulation from the web interface, you will most likely need to add www-data
to the group bluetooth
if you want to test this script from the command line, you will most likely need to add user pi
(or whoever you are) to the group bluetooth or run it as superuser
E.g. if you want to do bluetooth manipulation from the web interface, you will most likely need to add www-data
to the group bluetooth.
If you want to test this script from the command line, you will most likely need to add user pi
(or whoever you are) to the group bluetooth or run it as superuser
sudo usermod -G bluetooth -a www-data
Don't forget to reboot for group changes to take effect here
Expand All @@ -93,9 +95,8 @@ def bt_switch(cmd, led_pin=None): # noqa C901
A note for developers: This script is not persistent and only gets called (from various sources)
when the output sink is changed/toggled and exits.
This is done to make is callable from button press (gpio button handler), rfid card number, web interface
The LED state however should be persistent. With GPIOZero, the LED state gets reset at the end of the script.
For that reason GPIO state is manipulated through shell commands
This is done to make is callable from button press (gpio button handler), rfid card number, web interface
The LED state however should be persistent. For that reason no GPIO cleanup is called (ignore warning).
Parameters
----------
Expand All @@ -108,26 +109,14 @@ def bt_switch(cmd, led_pin=None): # noqa C901
logger.error("Invalid command. Doing nothing.")
return

led_device = None
# Rudimentary check if LED pin request is valid GPIO pin number
if led_pin is not None:
if led_pin < 2 or led_pin > 27:
led_pin = None
logger.error("Invalid led_pin. Ignoring led_pin = " + str(led_pin))

if led_pin is not None:
# Set-up GPIO LED pin if not already configured. If it already exists, sanity check direction of pin before use
try:
with open("/sys/class/gpio/gpio" + str(led_pin) + "/direction") as f:
if f.readline(3) != "out":
logger.error("LED pin already in use with direction 'in'. Ignoring led_pin = " + str(led_pin))
led_pin = None
except FileNotFoundError:
# GPIO direction file does not exist -> pin is not configured. Set it up (sleep is necessary!)
proc = subprocess.run("echo " + str(led_pin) + " > /sys/class/gpio/export; \
sleep 0.1; \
echo out > /sys/class/gpio/gpio" + str(led_pin) + "/direction", shell=True, check=False,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
logger.debug(proc.stdout)
else:
led_device = LED(led_pin, name="BluetoothToggleLed", initial_value=False)

# Figure out if output 1 (speakers) is enabled
isSpeakerOn_console = subprocess.run("mpc outputs", shell=True, check=False, stdout=subprocess.PIPE,
Expand Down Expand Up @@ -156,19 +145,19 @@ def bt_switch(cmd, led_pin=None): # noqa C901
logger.debug(proc.stdout)
# Yet, in some cases, a stream error still occurs: check and recover
bt_check_mpc_err()
if led_pin is not None:
proc = subprocess.run("echo 1 > /sys/class/gpio/gpio" + str(led_pin) + "/value", shell=True,
check=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
if led_device is not None:
led_device.on()
logger.debug(b'LED on: ' + proc.stdout)
return
else:
print("No bluetooth device connected. Defaulting to \"Output 1\".")
if led_pin:
if led_device is not None:
sleeptime = 0.25
for i in range(0, 3):
subprocess.run("echo 1 > /sys/class/gpio/gpio" + str(led_pin) + "/value; sleep " + str(
sleeptime) + "; echo 0 > /sys/class/gpio/gpio" + str(led_pin) + "/value; sleep " + str(
sleeptime), shell=True, check=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
led_device.on()
time.sleep(sleeptime)
led_device.off()
time.sleep(sleeptime)

# Default: Switch to Speakers
print("Switched audio sink to \"Output 1\"")
Expand All @@ -178,9 +167,8 @@ def bt_switch(cmd, led_pin=None): # noqa C901
logger.debug(proc.stdout)
# Yet, in some cases, a stream error still occurs: check and recover
bt_check_mpc_err()
if led_pin:
proc = subprocess.run("echo 0 > /sys/class/gpio/gpio" + str(led_pin) + "/value", shell=True, check=False,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
if led_device is not None:
led_device.off()
logger.debug(b'LED off: ' + proc.stdout)


Expand Down Expand Up @@ -217,9 +205,6 @@ def get_led_pin_config(cfg_file):
led_pin = cfg[section_name].getint('led_pin', fallback=None)
if not led_pin:
logger.warning("Could not find 'led_pin' or could not read integer value")
elif not 1 <= led_pin <= 27:
logger.warning(f"Ignoring out of range pin number: {led_pin}.")
led_pin = None
else:
logger.debug(f"No section {section_name} found. Defaulting to led_pin = None")

Expand Down

0 comments on commit 5b72373

Please sign in to comment.