From 0e00fbf2d6130bf8761742a7a656f62690cb1246 Mon Sep 17 00:00:00 2001 From: torlando-tech Date: Tue, 28 Oct 2025 23:25:52 -0400 Subject: [PATCH] feat: enable BlueZ experimental mode by default to fix BLE connection issues MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #3 BlueZ experimental mode is required for proper BLE connectivity. Without it, BlueZ attempts Classic Bluetooth (BR/EDR) connections instead of BLE (LE) connections, causing connection errors like "br-connection-profile-unavailable" and immediate disconnections after pairing. Changes: - install.sh: Automatically enables BlueZ experimental mode during installation - Detects BlueZ version (requires >= 5.49) - Creates systemd override to add -E flag to bluetoothd - Checks if already enabled to avoid duplicate configuration - Shows strong warning if user skips with --skip-experimental flag - Added --skip-experimental flag to opt-out (not recommended) - Updated help text to document new flag - tests/test_installer.sh: Added tests for experimental mode configuration - README.md: Documented BlueZ experimental mode in installation sections - Added to automated installation description - Added as required step in manual installation - Added troubleshooting section for BR/EDR connection errors - examples/config_example.toml: Added troubleshooting entry for BR/EDR errors The installer now: 1. Detects BlueZ version >= 5.49 (required for experimental mode) 2. Checks if already enabled (graceful skip) 3. Enables experimental mode by default unless --skip-experimental is used 4. Shows prominent warning if skipped (may cause BLE to break) 5. Handles edge cases (no systemd, old BlueZ, container environments) This addresses the root cause reported in issue #3 where devices were connecting then immediately disconnecting with BR/EDR profile errors. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- README.md | 54 ++++++++++++- examples/config_example.toml | 13 +++ install.sh | 148 ++++++++++++++++++++++++++++++++++- tests/test_installer.sh | 44 +++++++++++ 4 files changed, 252 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index a94ac7f..51ca23a 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,15 @@ The script will: 2. ✓ Install system dependencies (BlueZ, dbus) 3. ✓ Install Python packages in the correct environment 4. ✓ Copy BLE interface files to `~/.reticulum/interfaces/` (or custom config directory if specified) -5. ✓ Optionally set up Bluetooth permissions +5. ✓ Enable BlueZ experimental mode (required for proper BLE connectivity) +6. ✓ Optionally set up Bluetooth permissions + +**BlueZ Experimental Mode**: The installer automatically enables BlueZ experimental mode, which is required for proper BLE connectivity. This allows the BLE interface to use LE-specific connection methods instead of defaulting to Classic Bluetooth (BR/EDR), preventing connection errors like "br-connection-profile-unavailable". + +To skip this configuration (not recommended): +```bash +./install.sh --skip-experimental +``` ### Option B: Manual Installation @@ -100,7 +108,35 @@ mkdir -p ~/.reticulum/interfaces cp src/RNS/Interfaces/BLE*.py ~/.reticulum/interfaces/ ``` -#### 4. Grant Bluetooth Permissions +#### 4. Enable BlueZ Experimental Mode (Required) + +BlueZ experimental mode is required for proper BLE connectivity. Without it, BlueZ may attempt Classic Bluetooth (BR/EDR) connections instead of BLE (LE) connections, causing connection failures. + +Enable experimental mode (BlueZ >= 5.49): +```bash +sudo systemctl edit bluetooth +``` + +Add these lines: +``` +[Service] +ExecStart= +ExecStart=/usr/lib/bluetooth/bluetoothd -E +``` + +Save and restart Bluetooth: +```bash +sudo systemctl daemon-reload +sudo systemctl restart bluetooth +``` + +Verify it's enabled: +```bash +ps aux | grep bluetoothd +# Should show: /usr/lib/bluetooth/bluetoothd -E +``` + +#### 5. Grant Bluetooth Permissions For non-root operation: ```bash @@ -199,9 +235,21 @@ python ble_minimal_test.py test - Set `enable_peripheral = no` to disable peripheral mode ### Permission denied errors -- Grant capabilities to Python (see Installation → Manual Installation → step 4) +- Grant capabilities to Python (see Installation → Manual Installation → step 5) - Or run with sudo: `sudo rnsd` (not recommended) +### BR/EDR connection errors (br-connection-profile-unavailable, ProfileUnavailable) +These errors occur when BlueZ attempts Classic Bluetooth (BR/EDR) connections instead of BLE (LE) connections. This is the most common BLE connection issue. + +**Symptoms:** +- Devices connect then immediately disconnect +- Errors: "br-connection-profile-unavailable", "ProfileUnavailable" +- "ConnectDevice() unavailable" in logs +- Devices get blacklisted after multiple failures + +**Solution:** +Enable BlueZ experimental mode (see Installation → Manual Installation → step 4). If you used the automated installer, re-run it without `--skip-experimental`. + ## Architecture The BLE interface consists of four main components: diff --git a/examples/config_example.toml b/examples/config_example.toml index f8482b9..823fd75 100644 --- a/examples/config_example.toml +++ b/examples/config_example.toml @@ -253,6 +253,19 @@ power_mode = balanced # - Restart Bluetooth service (Linux: sudo systemctl restart bluetooth) # - Check device_name is not too long (max ~20 characters) # +# 6. BR/EDR connection errors (br-connection-profile-unavailable, ProfileUnavailable): +# IMPORTANT: This is the most common BLE connection issue! +# - Symptoms: Devices connect then immediately disconnect, "ConnectDevice() unavailable" in logs +# - Cause: BlueZ attempting Classic Bluetooth (BR/EDR) instead of BLE (LE) connections +# - Solution: Enable BlueZ experimental mode (required for proper BLE connectivity) +# Linux: sudo systemctl edit bluetooth +# Add: [Service] +# ExecStart= +# ExecStart=/usr/lib/bluetooth/bluetoothd -E +# Then: sudo systemctl daemon-reload && sudo systemctl restart bluetooth +# - If you used install.sh, it should have enabled this automatically +# - Verify: ps aux | grep bluetoothd (should show -E flag) +# # For more troubleshooting, see README.md # ============================================================================ diff --git a/install.sh b/install.sh index 0db1189..aa6f9a6 100755 --- a/install.sh +++ b/install.sh @@ -51,19 +51,26 @@ pip_install() { # Parse command line arguments CUSTOM_CONFIG_DIR="" +SKIP_BLUEZ_EXPERIMENTAL=false while [[ $# -gt 0 ]]; do case $1 in --config) CUSTOM_CONFIG_DIR="$2" shift 2 ;; + --skip-experimental) + SKIP_BLUEZ_EXPERIMENTAL=true + shift + ;; -h|--help) - echo "Usage: $0 [--config CONFIG_DIR]" + echo "Usage: $0 [OPTIONS]" echo "" echo "Options:" - echo " --config CONFIG_DIR Install to custom Reticulum config directory" - echo " (default: ~/.reticulum)" - echo " -h, --help Show this help message" + echo " --config CONFIG_DIR Install to custom Reticulum config directory" + echo " (default: ~/.reticulum)" + echo " --skip-experimental Skip enabling BlueZ experimental mode" + echo " WARNING: May cause BLE connection failures" + echo " -h, --help Show this help message" exit 0 ;; *) @@ -351,6 +358,139 @@ fi echo +# Step 5A: BlueZ Experimental Mode +print_header "BlueZ Experimental Mode" + +# Check if bluetoothctl is available +if ! command -v bluetoothctl &> /dev/null; then + print_warning "bluetoothctl not found - BlueZ may not be installed" + print_info "BLE interface requires BlueZ for Bluetooth functionality" + echo +elif ! command -v systemctl &> /dev/null; then + print_warning "systemctl not found - cannot configure BlueZ experimental mode" + print_info "This system may not use systemd, or this may be a container environment" + echo +else + # Detect BlueZ version + BLUEZ_VERSION=$(bluetoothctl --version 2>/dev/null | grep -oP '\d+\.\d+' | head -1) + + if [ -z "$BLUEZ_VERSION" ]; then + print_warning "Could not detect BlueZ version" + echo + else + print_info "Detected BlueZ version: $BLUEZ_VERSION" + + # Parse version to check if >= 5.49 + VERSION_MAJOR=$(echo "$BLUEZ_VERSION" | cut -d. -f1) + VERSION_MINOR=$(echo "$BLUEZ_VERSION" | cut -d. -f2) + + if [ "$VERSION_MAJOR" -lt 5 ] || ([ "$VERSION_MAJOR" -eq 5 ] && [ "$VERSION_MINOR" -lt 49 ]); then + print_warning "BlueZ version $BLUEZ_VERSION does not support experimental mode (requires >= 5.49)" + print_info "BLE interface will work with standard connection methods" + print_info "Consider upgrading BlueZ for full BLE compatibility" + echo + else + # Check if experimental mode is already enabled + if systemctl status bluetooth 2>/dev/null | grep -q -- "-E\|--experimental"; then + print_success "BlueZ experimental mode already enabled" + echo + elif [ "$SKIP_BLUEZ_EXPERIMENTAL" = true ]; then + # User explicitly skipped experimental mode - show strong warning + echo + print_error "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + print_error "WARNING: Skipping BlueZ experimental mode" + print_error "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + echo + echo -e "${RED}BLE connections may fail with errors like:${NC}" + echo " • br-connection-profile-unavailable" + echo " • ProfileUnavailable" + echo " • Immediate disconnections after pairing" + echo + echo -e "${RED}Your BLE interface may attempt Classic Bluetooth (BR/EDR)${NC}" + echo -e "${RED}connections instead of BLE (LE) connections.${NC}" + echo + echo -e "${YELLOW}This is NOT RECOMMENDED unless you have a specific reason.${NC}" + echo + echo "To enable experimental mode later:" + echo " 1. sudo systemctl edit bluetooth" + echo " 2. Add these lines:" + echo " [Service]" + echo " ExecStart=" + echo " ExecStart=/usr/lib/bluetooth/bluetoothd -E" + echo " 3. sudo systemctl daemon-reload" + echo " 4. sudo systemctl restart bluetooth" + echo + print_error "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + echo + else + # Enable experimental mode by default + print_info "Enabling BlueZ experimental mode (required for proper BLE connectivity)" + print_info "This enables LE-specific connection methods (ConnectDevice API)" + echo + + # Find bluetoothd path + BLUETOOTHD_PATH="" + for path in /usr/lib/bluetooth/bluetoothd /usr/libexec/bluetooth/bluetoothd; do + if [ -f "$path" ]; then + BLUETOOTHD_PATH="$path" + break + fi + done + + if [ -z "$BLUETOOTHD_PATH" ]; then + print_error "Could not find bluetoothd binary" + print_warning "Tried: /usr/lib/bluetooth/bluetoothd, /usr/libexec/bluetooth/bluetoothd" + echo + else + print_info "Using bluetoothd at: $BLUETOOTHD_PATH" + + # Create systemd override + print_info "Creating systemd override for bluetooth service..." + + # Use sudo only if not running as root + if [ "$EUID" -eq 0 ]; then + # Running as root - no sudo needed + mkdir -p /etc/systemd/system/bluetooth.service.d + cat > /etc/systemd/system/bluetooth.service.d/override.conf < /dev/null < /dev/null && command -v bluetoothctl &> /dev/null; then + # systemctl is available - check if experimental mode was configured + if [ -f /etc/systemd/system/bluetooth.service.d/override.conf ]; then + echo " ✓ Systemd override file created" + if grep -q -- "-E" /etc/systemd/system/bluetooth.service.d/override.conf; then + echo " ✓ Experimental mode flag (-E) configured" + else + echo " ⚠ WARNING: Override file exists but -E flag not found" + fi + else + # No override file - may have been already enabled or not supported + if systemctl status bluetooth 2>/dev/null | grep -q -- "-E\|--experimental"; then + echo " ✓ Experimental mode already enabled (not via installer)" + else + echo " ⚠ WARNING: Experimental mode not configured" + fi + fi +else + # systemctl or bluetoothctl not available (container environment) + echo " ℹ Systemd/BlueZ not available (container environment - OK)" +fi + +echo "" + +# Test --skip-experimental flag +echo "Testing --skip-experimental flag..." +cd "$(dirname "$0")/.." +# Run with --skip-experimental to verify it doesn't fail +./install.sh --config /tmp/test-config-skip --skip-experimental > /tmp/skip-test.log 2>&1 <