Skip to content

Garmin pairing#732

Merged
doudar merged 38 commits into
developfrom
garmin-pairing
May 4, 2026
Merged

Garmin pairing#732
doudar merged 38 commits into
developfrom
garmin-pairing

Conversation

@doudar
Copy link
Copy Markdown
Owner

@doudar doudar commented May 2, 2026

This pull request improves BLE advertising and setup to enhance compatibility with Garmin devices, particularly for discovery and pairing as a cycling power sensor. The changes focus on advertising only the Cycling Power Service (CPS) in the primary advertisement, using a public device address, and making the device appear as a standard cycling power sensor. Other minor configuration and characteristic adjustments are also included.

BLE Advertising and Device Discovery Improvements:

  • Modified BLE advertising in startBLEServer to advertise only the Cycling Power Service (CPS) UUID and cycling power sensor appearance in the primary advertisement, improving Garmin device discovery and pairing. Other services remain discoverable via GATT after connection.
  • Updated BLE setup in setupBLE to use a public device address (BLE_ADDR_PUBLIC), as required by Garmin for sensor discovery.

BLE Characteristic Adjustments:

  • Changed cyclingPowerMeasurementCharacteristic in BLE_Cycling_Power_Service to use only the NOTIFY property (removed READ), aligning with standard BLE cycling power meter behavior.

Documentation and Configuration:

  • Updated CHANGELOG.md to document the BLE advertising and public address changes for improved Garmin compatibility.
  • Minor configuration update: Disabled CONFIG_LITTLEFS_WDT_RESET in sdkconfig.release.

doudar and others added 28 commits February 28, 2026 22:50
Move FTMS control point write logic from DirConManager.cpp into
BLE_Fitness_Machine_Service::handleDirConWrite().

Move Zwift sync_rx write logic (including auto-subscription UUIDs)
from DirConManager.cpp into BLE_Zwift_Service::handleDirConWrite().

DirConManager now calls each service's handleDirConWrite() generically
without referencing any service-specific UUIDs or protocol details.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ncy; adjust spacing and update service UUID references
…in compatibility

- Restructured BLE advertising to prioritize the Cycling Power Service (CPS) UUID (0x1818) in the primary packet, mimicking commercial power meters to bypass strict Garmin discovery filters.
- Added BLE Appearance (0x0484) to explicitly identify the device as a Cycling Power Sensor.
- Moved the SmartSpin2k custom service UUID to the scan response to prevent advertising packet overflow and reduce noise for central scanners.
- Updated the Cycling Power Measurement characteristic to NOTIFY only to comply with the Bluetooth CPP v1.1 specification.
- Forced a public MAC address type to ensure stable pairing with Garmin watches that reject random resolvable addresses.
…in compatibility

- Restructured BLE advertising to prioritize the Cycling Power Service (CPS) UUID (0x1818) in the primary packet, mimicking commercial power meters to bypass strict Garmin discovery filters.
- Added BLE Appearance (0x0484) to explicitly identify the device as a Cycling Power Sensor.
- Moved the SmartSpin2k custom service UUID to the scan response to prevent advertising packet overflow and reduce noise for central scanners.
- Updated the Cycling Power Measurement characteristic to NOTIFY only to comply with the Bluetooth CPP v1.1 specification.
- Forced a public MAC address type to ensure stable pairing with Garmin watches that reject random resolvable addresses.
Copilot AI review requested due to automatic review settings May 2, 2026 02:22
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the BLE initialization and advertising payload to improve Garmin discovery/pairing by making SmartSpin2k appear more like a standard Cycling Power Sensor (CPS), with a few related configuration updates.

Changes:

  • Adjust BLE advertising to primarily advertise only the Cycling Power Service (CPS) UUID + Cycling Power Sensor appearance, with SS2K custom service moved to scan response.
  • Configure NimBLE to use a public device address type for Garmin compatibility.
  • Align CPS Cycling Power Measurement characteristic properties closer to typical power meter behavior (NOTIFY-only).

Reviewed changes

Copilot reviewed 6 out of 7 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/BLE_Setup.cpp Sets BLE own address type to public before starting client/server.
src/BLE_Server.cpp Reworks advertising payload (CPS-only primary adv + appearance + name; SS2K UUID in scan response).
src/BLE_Cycling_Power_Service.cpp Removes READ property from Cycling Power Measurement characteristic.
sdkconfig.release Explicitly disables CONFIG_LITTLEFS_WDT_RESET.
sdkconfig.debug Adds a full auto-generated debug sdkconfig snapshot.
dependencies.lock Updates managed component versions/hashes (esp_modem, mdns, littlefs).
CHANGELOG.md Documents Garmin-related BLE advertising/address changes under Unreleased.

Comment thread src/BLE_Server.cpp Outdated
Comment on lines +63 to +67
oAdvertisementData.setName(userConfig->getDeviceName()); // Include name in primary packet
pAdvertising->setAdvertisementData(oAdvertisementData);

// Scan response: custom service UUID for SS2K app discovery
oScanResponseData.setCompleteServices(SMARTSPIN2K_SERVICE_UUID);
Comment thread sdkconfig.debug
Comment on lines +1 to +4
#
# Automatically generated file. DO NOT EDIT.
# Espressif IoT Development Framework (ESP-IDF) 5.4.2 Project Configuration
#
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 7 changed files in this pull request and generated 3 comments.

Comment thread src/BLE_Server.cpp Outdated
Comment on lines +60 to +66
oAdvertisementData.setFlags(0x06); // General Discoverable, BR/EDR Not Supported
oAdvertisementData.setAppearance(0x0484); // Cycling: Power Sensor
oAdvertisementData.setCompleteServices16(primaryServiceUUIDs);
oAdvertisementData.setName(userConfig->getDeviceName()); // Include name in primary packet
pAdvertising->setAdvertisementData(oAdvertisementData);

// Scan response: custom service UUID for SS2K app discovery
// Power Meter service setup
pPowerMonitor = spinBLEServer.pServer->createService(CYCLINGPOWERSERVICE_UUID);
cyclingPowerMeasurementCharacteristic = pPowerMonitor->createCharacteristic(CYCLINGPOWERMEASUREMENT_UUID, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::NOTIFY);
cyclingPowerMeasurementCharacteristic = pPowerMonitor->createCharacteristic(CYCLINGPOWERMEASUREMENT_UUID, NIMBLE_PROPERTY::NOTIFY);
Comment thread sdkconfig.debug Outdated
doudar and others added 10 commits May 2, 2026 08:41
Co-authored-by: Copilot <copilot@github.com>
… to handle service UUIDs

Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <copilot@github.com>
Garmin compatible advertising. ZP (Currently disabled)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@doudar doudar merged commit c1495df into develop May 4, 2026
2 checks passed
@doudar doudar deleted the garmin-pairing branch May 4, 2026 02:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants