Bluetooth Speaker Verbinden

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
taake
User
Beiträge: 125
Registriert: Donnerstag 14. Oktober 2010, 08:49

Hallo zusammen,

ich wollte mal schauen ob man hier ggf. etwas Hilfe finden kann.
Folgendes "Problem" Ich habe mir via Flask einen kleinen player gebaut der hörspiele und co über mein bluetooth Lautsprecher wiedergeben kann.

Leider scheint der Bluetooth support in python eher unterirdisch zu sein.

Letzendlich bin ich bei einer Lösung gelandet die alles andere als schön ist, es gibt pybluez (https://github.com/pybluez/pybluez) welches aber nicht mehr aktiv weitereinwickelt wird, und zwar zum scannen geeignet ist, aber laut der sehr überschaubaren doku keine Verbindung aufbauen kann.
Nun übernimmt pybluez das scannen und sofern es eine der von mir definierten bluetoothspeaker findet versucht es sich via pydbus zu verbinden.

Code: Alles auswählen

from app import app                                                                                                     
import pydbus                                                                                                           
import bluetooth                                                                                                        
                                                                                                                        
                                                                                                                        
class BluetoothConnect:                                                                                                 
    def __init__(self):                                                                                                 
        self.speaker = None                                                                                             
        self.bus = pydbus.SystemBus()                                                                                   
                                                                                                                        
    def scan(self):                                                                                                     
        self.devices = bluetooth.discover_devices()                                                                     
        app.logger.debug(f'Device Scan found following devices {self.devices}')                                         
                                                                                                                        
    def find_my_device(self):                                                                                           
        for dev in self.devices:                                                                                        
            if dev in app.config['SPEAKER_MAC_LIST']:                                                                   
                app.logger.debug(f'Found device match for: {dev}')                                                      
                self.speaker = dev                                                                                      
                break                                                                                                   
                                                                                                                        
    def bt_con(self):                                                                                                   
        self.adapter_path = '/org/bluez/hci0'                                                                           
        self.device_path = f'{self.adapter_path}/dev_{self.speaker.replace(":", "_")}'                                  
        self.bluez_service = 'org.bluez'                                                                                
        adapter = self.bus.get(self.bluez_service, self.adapter_path)                                                   
        device = self.bus.get(self.bluez_service, self.device_path)                                                     
        device.Connect()                                                                                                
                                                                                                                        
    def connect(self):                                                                                                  
        self.scan()                                                                                                     
        if not len(self.devices) > 0:                                                                                   
            return 'No devices found'                                                                                   
        self.find_my_device()                                                                                           
        if self.speaker != None:                                                                                        
            self.bt_con()                                                                                               
            return f'found device {self.speaker} an tryed to connect'                                                   
        else:                                                                                                           
            return f'Not found any matching device in avalible bluetooth devices: {self.devices}' 
Jedenfalls bin ich mir der aktuellen Lösung recht unglücklich pydbus möchte nicht wirklich verwenden, pybluez wird nicht mehr aktiv entwickelt.
Die ganze Situation ist also eher so mäh - leider sehe ich keine wirklichen alternativen, bluetoothctl (unter linux) via os.subprocess zu steuern schließe ich kategorisch aus, weil das reines gefrickel wäre.

Jetzt zur eigentlichen Frage, hat jemand ne Idee wie man das nicht ganz so suboptimal lösen kann?
Benutzeravatar
__blackjack__
User
Beiträge: 13080
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Anmerkungen zum Quelltext: Die Klasse ist komisch. Da werden in Methoden plötzlich neue Attribute eingeführt, das sollte nicht sein.

`scan()` könnte die Geräteliste beispielsweise einfach als Rückgabewert liefern. Dann wäre das einfach eine Funktion.

``if not len(devices) > 0:`` ist eine recht umständliche verwirrende Art ``if not devices:`` zu schreiben.

Und `find_my_device()` könnte `speaker` einfach als Rückgabewert liefern. Dann wäre das auch einfach nur eine Funktion. Und `BluetoothConnect` hätte nur noch den DBus als Zustand.

Die Attribute die in `bt_con()` gesetzt werden sind eigentlich Konstanten, oder halt auch einfach nur lokale Namen.

`adapter` wird dort definiert, aber nirgends verwendet.

Wenn man die Klasse raus wirft, bleibt das hier:

Code: Alles auswählen

#!/usr/bin/env python3
import bluetooth
import pydbus
from app import app


def scan():
    devices = bluetooth.discover_devices()
    app.logger.debug(f"Device Scan found following devices {devices}")
    return devices


def find_my_device(devices):
    for device in devices:
        if device in app.config["SPEAKER_MAC_LIST"]:
            app.logger.debug(f"Found device match for: {device}")
            return device
    return None


def bt_con(speaker):
    pydbus.SystemBus().get(
        "org.bluez", f"/org/bluez/hci0/dev_{speaker.replace(':', '_')}"
    ).Connect()


def connect():
    devices = scan()
    if not devices:
        return (None, "No devices found")

    speaker = find_my_device(devices)
    if speaker:
        bt_con(speaker)
        return (speaker, f"found device {speaker} an tryed to connect")

    return (
        None,
        f"Not found any matching device in avalible bluetooth devices:"
        f" {devices}",
    )
Wobei der Rückgabewert von `connect()` IMHO nicht so schön ist, da würde ich wahrscheinlich eher mit Ausnahmen arbeiten.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Antworten