generated from Grigo/AndroidTemplate
Daily checkup
This commit is contained in:
+76
-2
@@ -12,6 +12,8 @@ import json
|
||||
import os
|
||||
import queue
|
||||
import random
|
||||
import re
|
||||
import subprocess
|
||||
import threading
|
||||
import struct
|
||||
import sys
|
||||
@@ -1340,7 +1342,9 @@ class DataCharacteristic(Characteristic):
|
||||
|
||||
class StatusCharacteristic(Characteristic):
|
||||
def __init__(self, bus, index, service: Service, bridge: AisHubBridge):
|
||||
Characteristic.__init__(self, bus, index, AIS_HUB_STATUS_UUID, ["read", "notify"], service)
|
||||
# Только read: notify не используется клиентом; лишний notify увеличивает
|
||||
# поверхность ATT без пользы. Шифрование не требуется (без encrypt-*).
|
||||
Characteristic.__init__(self, bus, index, AIS_HUB_STATUS_UUID, ["read"], service)
|
||||
self.bridge = bridge
|
||||
self.notifying = False
|
||||
|
||||
@@ -1417,6 +1421,74 @@ def find_adapter(bus):
|
||||
return None
|
||||
|
||||
|
||||
def _hci_index_from_adapter_path(adapter_path: str) -> str | None:
|
||||
m = re.search(r'hci(\d+)$', adapter_path)
|
||||
return m.group(1) if m else None
|
||||
|
||||
|
||||
def configure_adapter_for_open_le(bus, adapter_path: str) -> None:
|
||||
"""
|
||||
Снижает вероятность системного диалога pairing на Android.
|
||||
|
||||
Наши характеристики без encrypt-* флагов, но bluetoothd по умолчанию:
|
||||
- шлёт SMP Security Request (bonding) при LE connect;
|
||||
- делает reverse GATT discovery к central (читает Battery и т.п. на
|
||||
телефоне) -> Insufficient Authentication -> Android показывает pairing.
|
||||
|
||||
См. bluez/bluez#851, ukBaz/python-bluezero#390.
|
||||
"""
|
||||
props = dbus.Interface(
|
||||
bus.get_object(BLUEZ_SERVICE_NAME, adapter_path),
|
||||
DBUS_PROP_IFACE,
|
||||
)
|
||||
try:
|
||||
props.Set('org.bluez.Adapter1', 'Pairable', dbus.Boolean(False))
|
||||
log_info('[Adapter] Pairable=false (no incoming pairing UI from adapter)')
|
||||
except Exception as e:
|
||||
log_warn(f'[Adapter] Pairable=false failed: {e}')
|
||||
|
||||
# btmgmt: bondable off + NoInputNoOutput — peripheral не инициирует bonding.
|
||||
hci = _hci_index_from_adapter_path(adapter_path)
|
||||
if hci is None:
|
||||
log_warn('[Adapter] cannot parse hci index from ' + adapter_path)
|
||||
return
|
||||
for args in (
|
||||
['bondable', 'off'],
|
||||
['io-cap', '3'], # NoInputNoOutput
|
||||
):
|
||||
cmd = ['btmgmt', '-i', hci] + args
|
||||
try:
|
||||
r = subprocess.run(cmd, capture_output=True, text=True, timeout=5)
|
||||
if r.returncode == 0:
|
||||
log_info(f'[Adapter] btmgmt {" ".join(args)}: ok')
|
||||
else:
|
||||
err = (r.stderr or r.stdout or '').strip()
|
||||
log_warn(f'[Adapter] btmgmt {" ".join(args)} failed ({r.returncode}): {err}')
|
||||
except FileNotFoundError:
|
||||
log_warn('[Adapter] btmgmt not found; set ReverseServiceDiscovery=false in /etc/bluetooth/main.conf')
|
||||
break
|
||||
except Exception as e:
|
||||
log_warn(f'[Adapter] btmgmt {" ".join(args)}: {e}')
|
||||
|
||||
log_info(
|
||||
'[Adapter] Рекомендуется в /etc/bluetooth/main.conf: '
|
||||
'ReverseServiceDiscovery=false и [GATT] Client=false (перезапуск bluetoothd)'
|
||||
)
|
||||
|
||||
|
||||
def trust_connected_device(bus, device_path: str) -> None:
|
||||
"""Помечает central как Trusted — на части стеков убирает повторный pairing prompt."""
|
||||
if not device_path or device_path == 'unknown':
|
||||
return
|
||||
try:
|
||||
dev = bus.get_object(BLUEZ_SERVICE_NAME, device_path)
|
||||
props = dbus.Interface(dev, DBUS_PROP_IFACE)
|
||||
props.Set('org.bluez.Device1', 'Trusted', dbus.Boolean(True))
|
||||
log_debug(f'[BlueZ] Device Trusted=true: {device_path}')
|
||||
except Exception as e:
|
||||
log_debug(f'[BlueZ] Trusted=true failed for {device_path}: {e}')
|
||||
|
||||
|
||||
# ============ main() ============
|
||||
|
||||
def main():
|
||||
@@ -1432,6 +1504,7 @@ def main():
|
||||
return 1
|
||||
|
||||
log_info(f'Используем адаптер: {adapter_path}')
|
||||
configure_adapter_for_open_le(bus, adapter_path)
|
||||
|
||||
service_manager = dbus.Interface(
|
||||
bus.get_object(BLUEZ_SERVICE_NAME, adapter_path),
|
||||
@@ -1455,11 +1528,12 @@ def main():
|
||||
if "Connected" not in changed:
|
||||
return
|
||||
connected = bool(changed.get("Connected"))
|
||||
dev_path = str(path or "")
|
||||
dev_path = "" if path is None else str(path)
|
||||
if not dev_path:
|
||||
return
|
||||
if connected:
|
||||
log_info(f"[BlueZ] Device connected: {dev_path} sessions={bridge.session_count()}")
|
||||
trust_connected_device(bus, dev_path)
|
||||
bridge.get_or_create_session(dev_path)
|
||||
else:
|
||||
log_info(f"[BlueZ] Device disconnected: {dev_path} -> removing session")
|
||||
|
||||
Reference in New Issue
Block a user