diff --git a/components/bluetooth-sink-switch/bt-sink-switch.py b/components/bluetooth-sink-switch/bt-sink-switch.py index 7fe2d918f..6492717cf 100755 --- a/components/bluetooth-sink-switch/bt-sink-switch.py +++ b/components/bluetooth-sink-switch/bt-sink-switch.py @@ -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') @@ -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 @@ -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 ---------- @@ -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, @@ -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\"") @@ -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) @@ -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")