refresh when pair

This commit is contained in:
cheykrym 2026-03-31 23:54:39 +03:00
parent 6456b6c23d
commit e963628158
2 changed files with 56 additions and 3 deletions

View File

@ -49,16 +49,18 @@ class BluetoothScreen(QWidget):
actions.setContentsMargins(0, 0, 0, 0) actions.setContentsMargins(0, 0, 0, 0)
actions.setSpacing(12) actions.setSpacing(12)
# Кнопка скрыта, видимость включается автоматически при входе в меню
self.btn_visible = QPushButton("Сделать видимым") self.btn_visible = QPushButton("Сделать видимым")
self.btn_visible.setObjectName("BluetoothActionBtn") self.btn_visible.setObjectName("BluetoothActionBtn")
self.btn_visible.setMinimumHeight(56) self.btn_visible.setMinimumHeight(56)
self.btn_visible.clicked.connect(self._make_visible) self.btn_visible.clicked.connect(self._make_visible)
self.btn_visible.setVisible(False) # временная кнопка, скрыта self.btn_visible.setVisible(False)
self.btn_refresh = QPushButton("Обновить список") self.btn_refresh = QPushButton("Обновить список")
self.btn_refresh.setObjectName("BluetoothActionBtn") self.btn_refresh.setObjectName("BluetoothActionBtn")
self.btn_refresh.setMinimumHeight(56) self.btn_refresh.setMinimumHeight(56)
self.btn_refresh.clicked.connect(self.refresh_list) self.btn_refresh.clicked.connect(self.refresh_list)
self.btn_refresh.setVisible(False) # скрываем, обновляемся автоматически
self.btn_connect = QPushButton("Подключить") self.btn_connect = QPushButton("Подключить")
self.btn_connect.setObjectName("BluetoothActionBtnPrimary") self.btn_connect.setObjectName("BluetoothActionBtnPrimary")
@ -81,6 +83,9 @@ class BluetoothScreen(QWidget):
root.addWidget(self.list, 1) root.addWidget(self.list, 1)
root.addLayout(actions) root.addLayout(actions)
# Подписка на событие успешного сопряжения
self._bt_service.pairing_completed.connect(self.refresh_list)
self.refresh_list() self.refresh_list()
QTimer.singleShot(200, self._auto_connect_last) QTimer.singleShot(200, self._auto_connect_last)
@ -174,11 +179,13 @@ class BluetoothScreen(QWidget):
self.status.setText(self._bt_service.get_status_text(mac)) self.status.setText(self._bt_service.get_status_text(mac))
def showEvent(self, event): def showEvent(self, event):
"""Экран показан — запускаем режим сопряжения.""" """Экран показан — запускаем режим сопряжения и мониторинг."""
super().showEvent(event) super().showEvent(event)
self._refresh_discoverable() self._refresh_discoverable()
self._bt_service.start_pairing_monitor()
def hideEvent(self, event): def hideEvent(self, event):
"""Экран скрыт — останавливаем таймер.""" """Экран скрыт — останавливаем таймер и мониторинг."""
super().hideEvent(event) super().hideEvent(event)
self._discoverable_timer.stop() self._discoverable_timer.stop()
self._bt_service.stop_pairing_monitor()

View File

@ -24,11 +24,13 @@ class BluetoothService(QObject):
status_changed = Signal(str) status_changed = Signal(str)
devices_changed = Signal(list) devices_changed = Signal(list)
connected_changed = Signal(str, bool) # mac, connected connected_changed = Signal(str, bool) # mac, connected
pairing_completed = Signal() # новое устройство сопряжено
def __init__(self, parent=None): def __init__(self, parent=None):
super().__init__(parent) super().__init__(parent)
self._log_path = Path("~/.cache/car_ui/bluetooth.log").expanduser() self._log_path = Path("~/.cache/car_ui/bluetooth.log").expanduser()
self._last_error = "" self._last_error = ""
self._monitor_process: subprocess.Popen | None = None
# === Public API === # === Public API ===
@ -182,6 +184,50 @@ class BluetoothService(QObject):
"""Предыдущий трек.""" """Предыдущий трек."""
self._run_btctl(["menu player", "previous"]) self._run_btctl(["menu player", "previous"])
def start_pairing_monitor(self) -> None:
"""Запустить мониторинг событий сопряжения."""
if self._monitor_process is not None:
return
try:
self._monitor_process = subprocess.Popen(
["bluetoothctl", "events"],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
bufsize=1,
)
# Запускаем поток для чтения событий
import threading
threading.Thread(target=self._read_events, daemon=True).start()
except (subprocess.SubprocessError, OSError):
self._monitor_process = None
def stop_pairing_monitor(self) -> None:
"""Остановить мониторинг событий."""
if self._monitor_process is not None:
self._monitor_process.terminate()
self._monitor_process = None
def _read_events(self) -> None:
"""Чтение событий из bluetoothctl events."""
if self._monitor_process is None:
return
try:
for line in iter(self._monitor_process.stdout.readline, ''):
if line:
self._process_event(line.strip())
except (ValueError, OSError):
pass
def _process_event(self, line: str) -> None:
"""Обработка события bluetoothctl."""
# Событие успешного сопряжения
if "Pairing successful" in line or "Pairing complete" in line:
self.pairing_completed.emit()
# Событие нового устройства
elif "Device" in line and "connected" in line.lower():
pass # можно обработать подключение
# === Private methods === # === Private methods ===
def _run_cmd(self, args: list[str]) -> str: def _run_cmd(self, args: list[str]) -> str: