From 7060030e58204d61618281f7f27650e72284a71a Mon Sep 17 00:00:00 2001 From: William Emfinger Date: Sun, 25 Oct 2026 22:24:21 -0500 Subject: [PATCH 1/3] refactor(ble): drop the deprecated NimBLEService::start() calls esp-nimble-cpp 2.x makes NimBLEService::start() a deprecated no-op (services start with the server), so every ble_gatt_server build warned and the wrappers' "failed to start service" paths could never fire. The BatteryService / DeviceInfoService / GenericAccessService / HidService start() wrappers and BleGattServer::start_services() stay as empty [[deprecated]] no-ops for source compatibility; GfpsService::start() keeps setting the nearby advertisement mode and only loses the NimBLE call. Examples and the wdi README no longer call them. Verified: ble_gatt_server, gfps_service, hid_service and wdi/ble examples build for esp32s3 on IDF v6.1 with zero warnings. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01DFjjnq3XCTRAXENSxsCxJU --- .../example/main/ble_gatt_server_example.cpp | 3 --- .../ble_gatt_server/include/battery_service.hpp | 16 +++++----------- .../ble_gatt_server/include/ble_gatt_server.hpp | 9 ++++----- .../include/device_info_service.hpp | 16 +++++----------- .../include/generic_access_service.hpp | 16 +++++----------- .../example/main/gfps_service_example.cpp | 3 --- components/gfps_service/include/gfps_service.hpp | 11 +++-------- .../example/main/hid_service_example.cpp | 6 ------ components/hid_service/include/hid_service.hpp | 10 +++++----- components/wdi/README.md | 1 - .../wdi/ble_example/main/wdi_ble_example.cpp | 1 - 11 files changed, 27 insertions(+), 65 deletions(-) diff --git a/components/ble_gatt_server/example/main/ble_gatt_server_example.cpp b/components/ble_gatt_server/example/main/ble_gatt_server_example.cpp index b6f4b06cc6..033d21af38 100644 --- a/components/ble_gatt_server/example/main/ble_gatt_server_example.cpp +++ b/components/ble_gatt_server/example/main/ble_gatt_server_example.cpp @@ -68,12 +68,9 @@ extern "C" void app_main(void) { // ble_gatt_server.server().addService() // now start the services - ble_gatt_server.start_services(); // starts the device info service and battery service // NOTE: we could also directly start them ourselves if we wanted to // control the order of starting the services // e.g.: - // ble_gatt_server.battery_service().start(); - // ble_gatt_server.device_info_service().start(); // now start the gatt server ble_gatt_server.start(); diff --git a/components/ble_gatt_server/include/battery_service.hpp b/components/ble_gatt_server/include/battery_service.hpp index 72a2c9a3ce..780c453c66 100644 --- a/components/ble_gatt_server/include/battery_service.hpp +++ b/components/ble_gatt_server/include/battery_service.hpp @@ -49,17 +49,11 @@ class BatteryService : public BaseComponent { } /// Start the service - /// \note This must be called after the service has been initialized - void start() { - if (!service_) { - logger_.error("Service not created"); - return; - } - if (!service_->start()) { - logger_.error("Failed to start service"); - return; - } - } + /// \note Kept for API compatibility: NimBLE starts every service when the + /// server starts (esp-nimble-cpp 2.x), so there is nothing to do here. + [[deprecated( + "services are started with the server (BleGattServer::start()); this is a no-op")]] void + start() {} /// Get the service /// \return The Battery Service diff --git a/components/ble_gatt_server/include/ble_gatt_server.hpp b/components/ble_gatt_server/include/ble_gatt_server.hpp index 44462f1423..1726709f64 100644 --- a/components/ble_gatt_server/include/ble_gatt_server.hpp +++ b/components/ble_gatt_server/include/ble_gatt_server.hpp @@ -294,11 +294,10 @@ class BleGattServer : public BaseComponent { } /// Start the services - /// This method starts the device info and battery services. - void start_services() { - device_info_service_.start(); - battery_service_.start(); - } + /// \note Kept for API compatibility: NimBLE starts every service when the + /// server starts (start()), so there is nothing to do here. + [[deprecated("services are started with the server (start()); this is a no-op")]] void + start_services() {} /// Start the server /// This method starts the GATT server. diff --git a/components/ble_gatt_server/include/device_info_service.hpp b/components/ble_gatt_server/include/device_info_service.hpp index 3d3dfb87ed..a9175673bb 100644 --- a/components/ble_gatt_server/include/device_info_service.hpp +++ b/components/ble_gatt_server/include/device_info_service.hpp @@ -86,17 +86,11 @@ class DeviceInfoService : public BaseComponent { } /// Start the service - /// \note This must be called after the service has been initialized - void start() { - if (!service_) { - logger_.error("Service not created"); - return; - } - if (!service_->start()) { - logger_.error("Failed to start service"); - return; - } - } + /// \note Kept for API compatibility: NimBLE starts every service when the + /// server starts (esp-nimble-cpp 2.x), so there is nothing to do here. + [[deprecated( + "services are started with the server (BleGattServer::start()); this is a no-op")]] void + start() {} /// Get the service object /// \return The service object diff --git a/components/ble_gatt_server/include/generic_access_service.hpp b/components/ble_gatt_server/include/generic_access_service.hpp index 3a552a80f1..75ee23ccb6 100644 --- a/components/ble_gatt_server/include/generic_access_service.hpp +++ b/components/ble_gatt_server/include/generic_access_service.hpp @@ -72,17 +72,11 @@ class GenericAccessService : public BaseComponent { } /// Start the service - /// \note This must be called after the service has been initialized - void start() { - if (!service_) { - logger_.error("Service not created"); - return; - } - if (!service_->start()) { - logger_.error("Failed to start service"); - return; - } - } + /// \note Kept for API compatibility: NimBLE starts every service when the + /// server starts (esp-nimble-cpp 2.x), so there is nothing to do here. + [[deprecated( + "services are started with the server (BleGattServer::start()); this is a no-op")]] void + start() {} /// Get the service object /// \return The service object diff --git a/components/gfps_service/example/main/gfps_service_example.cpp b/components/gfps_service/example/main/gfps_service_example.cpp index b44b9714b8..bcc712c94b 100644 --- a/components/gfps_service/example/main/gfps_service_example.cpp +++ b/components/gfps_service/example/main/gfps_service_example.cpp @@ -53,12 +53,9 @@ extern "C" void app_main(void) { // now that we've made the input characteristic, we can start the service gfps_service.start(); - ble_gatt_server.start_services(); // starts the device info service and battery service // NOTE: we could also directly start them ourselves if we wanted to // control the order of starting the services // e.g.: - // ble_gatt_server.battery_service().start(); - // ble_gatt_server.device_info_service().start(); // now start the gatt server ble_gatt_server.start(); diff --git a/components/gfps_service/include/gfps_service.hpp b/components/gfps_service/include/gfps_service.hpp index f5de444980..30b6bfb5c0 100644 --- a/components/gfps_service/include/gfps_service.hpp +++ b/components/gfps_service/include/gfps_service.hpp @@ -190,19 +190,14 @@ class GfpsService : public espp::BaseComponent { } /// Start the service - /// \note This function will start the service - /// \note This function will also set the advertisement mode for the nearby - /// framework + /// \note The GATT service itself is started with the server + /// (BleGattServer::start()); this sets the advertisement mode for the + /// nearby framework, which must still be called. void start() { if (!service_) { logger_.error("Service not created"); return; } - if (service_->start()) { - logger_.info("Service started"); - } else { - logger_.error("Failed to start service"); - } int advertisement_mode = NEARBY_FP_ADVERTISEMENT_DISCOVERABLE | NEARBY_FP_ADVERTISEMENT_PAIRING_UI_INDICATOR; logger_.info("Setting advertisement mode to {}", advertisement_mode); diff --git a/components/hid_service/example/main/hid_service_example.cpp b/components/hid_service/example/main/hid_service_example.cpp index 6b1b6f29b5..d4a392f9c9 100644 --- a/components/hid_service/example/main/hid_service_example.cpp +++ b/components/hid_service/example/main/hid_service_example.cpp @@ -488,12 +488,6 @@ extern "C" void app_main(void) { ps4_feature_f2->setValue(feature_f2_data); #endif // CONFIG_EXAMPLE_AS_XBOX - // now that we've made the input characteristic, we can start the service - hid_service.start(); - // starts the device info service and battery service, see - // hid_service_example for more info - ble_gatt_server.start_services(); - // now start the gatt server ble_gatt_server.start(); diff --git a/components/hid_service/include/hid_service.hpp b/components/hid_service/include/hid_service.hpp index 3e7dd10726..4c06a2c769 100644 --- a/components/hid_service/include/hid_service.hpp +++ b/components/hid_service/include/hid_service.hpp @@ -80,11 +80,11 @@ class HidService : public espp::BaseComponent { } /// @brief Start the HID service. - void start() { - if (service_) { - service_->start(); - } - } + /// @note Kept for API compatibility: NimBLE starts every service when the + /// server starts (BleGattServer::start()), so there is nothing to do. + [[deprecated( + "services are started with the server (BleGattServer::start()); this is a no-op")]] void + start() {} /// @brief Get the HID service. /// @return The HID service. diff --git a/components/wdi/README.md b/components/wdi/README.md index 5f1b9e7507..489be6a9dd 100644 --- a/components/wdi/README.md +++ b/components/wdi/README.md @@ -125,7 +125,6 @@ espp::WdiBlePeripheral wdi({.on_feedback = [](const espp::wdi::FeedbackReport &f espp::BleGattServer ble; ble.init("espp WDI"); wdi.make_service(ble.server()); -ble.start_services(); wdi.start(); ble.start(); espp::BleGattServer::AdvertisedData adv; diff --git a/components/wdi/ble_example/main/wdi_ble_example.cpp b/components/wdi/ble_example/main/wdi_ble_example.cpp index 17b73d0f5e..a041279f27 100644 --- a/components/wdi/ble_example/main/wdi_ble_example.cpp +++ b/components/wdi/ble_example/main/wdi_ble_example.cpp @@ -43,7 +43,6 @@ extern "C" void app_main(void) { const std::string device_name = "espp WDI"; ble.init(device_name); wdi.make_service(ble.server()); - ble.start_services(); wdi.start(); ble.start(); From 73d716c0b2dbd7a7b65308452b26f906999f074f Mon Sep 17 00:00:00 2001 From: William Emfinger Date: Sun, 25 Oct 2026 22:35:23 -0500 Subject: [PATCH 2/3] refactor(wdi): deprecate the no-op WdiBlePeripheral::start() like the other service wrappers Same treatment as the ble_gatt_server / hid_service wrappers: the method stays for source compatibility, marked [[deprecated]] pointing at BleGattServer::start(); the README and BLE example stop calling it. Deprecation messages shortened so clang-format keeps each attribute on one line. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01DFjjnq3XCTRAXENSxsCxJU --- components/ble_gatt_server/include/battery_service.hpp | 4 +--- components/ble_gatt_server/include/ble_gatt_server.hpp | 3 +-- components/ble_gatt_server/include/device_info_service.hpp | 4 +--- .../ble_gatt_server/include/generic_access_service.hpp | 4 +--- components/hid_service/include/hid_service.hpp | 4 +--- components/wdi/README.md | 3 +-- components/wdi/ble_example/main/wdi_ble_example.cpp | 1 - components/wdi/include/wdi_ble.hpp | 7 +++---- 8 files changed, 9 insertions(+), 21 deletions(-) diff --git a/components/ble_gatt_server/include/battery_service.hpp b/components/ble_gatt_server/include/battery_service.hpp index 780c453c66..2e5cd19418 100644 --- a/components/ble_gatt_server/include/battery_service.hpp +++ b/components/ble_gatt_server/include/battery_service.hpp @@ -51,9 +51,7 @@ class BatteryService : public BaseComponent { /// Start the service /// \note Kept for API compatibility: NimBLE starts every service when the /// server starts (esp-nimble-cpp 2.x), so there is nothing to do here. - [[deprecated( - "services are started with the server (BleGattServer::start()); this is a no-op")]] void - start() {} + [[deprecated("no-op: services start with BleGattServer::start()")]] void start() {} /// Get the service /// \return The Battery Service diff --git a/components/ble_gatt_server/include/ble_gatt_server.hpp b/components/ble_gatt_server/include/ble_gatt_server.hpp index 1726709f64..e991c67842 100644 --- a/components/ble_gatt_server/include/ble_gatt_server.hpp +++ b/components/ble_gatt_server/include/ble_gatt_server.hpp @@ -296,8 +296,7 @@ class BleGattServer : public BaseComponent { /// Start the services /// \note Kept for API compatibility: NimBLE starts every service when the /// server starts (start()), so there is nothing to do here. - [[deprecated("services are started with the server (start()); this is a no-op")]] void - start_services() {} + [[deprecated("no-op: services start with start()")]] void start_services() {} /// Start the server /// This method starts the GATT server. diff --git a/components/ble_gatt_server/include/device_info_service.hpp b/components/ble_gatt_server/include/device_info_service.hpp index a9175673bb..335d905544 100644 --- a/components/ble_gatt_server/include/device_info_service.hpp +++ b/components/ble_gatt_server/include/device_info_service.hpp @@ -88,9 +88,7 @@ class DeviceInfoService : public BaseComponent { /// Start the service /// \note Kept for API compatibility: NimBLE starts every service when the /// server starts (esp-nimble-cpp 2.x), so there is nothing to do here. - [[deprecated( - "services are started with the server (BleGattServer::start()); this is a no-op")]] void - start() {} + [[deprecated("no-op: services start with BleGattServer::start()")]] void start() {} /// Get the service object /// \return The service object diff --git a/components/ble_gatt_server/include/generic_access_service.hpp b/components/ble_gatt_server/include/generic_access_service.hpp index 75ee23ccb6..a3b9db4a4b 100644 --- a/components/ble_gatt_server/include/generic_access_service.hpp +++ b/components/ble_gatt_server/include/generic_access_service.hpp @@ -74,9 +74,7 @@ class GenericAccessService : public BaseComponent { /// Start the service /// \note Kept for API compatibility: NimBLE starts every service when the /// server starts (esp-nimble-cpp 2.x), so there is nothing to do here. - [[deprecated( - "services are started with the server (BleGattServer::start()); this is a no-op")]] void - start() {} + [[deprecated("no-op: services start with BleGattServer::start()")]] void start() {} /// Get the service object /// \return The service object diff --git a/components/hid_service/include/hid_service.hpp b/components/hid_service/include/hid_service.hpp index 4c06a2c769..1a98813f41 100644 --- a/components/hid_service/include/hid_service.hpp +++ b/components/hid_service/include/hid_service.hpp @@ -82,9 +82,7 @@ class HidService : public espp::BaseComponent { /// @brief Start the HID service. /// @note Kept for API compatibility: NimBLE starts every service when the /// server starts (BleGattServer::start()), so there is nothing to do. - [[deprecated( - "services are started with the server (BleGattServer::start()); this is a no-op")]] void - start() {} + [[deprecated("no-op: services start with BleGattServer::start()")]] void start() {} /// @brief Get the HID service. /// @return The HID service. diff --git a/components/wdi/README.md b/components/wdi/README.md index 489be6a9dd..9e668d7b7f 100644 --- a/components/wdi/README.md +++ b/components/wdi/README.md @@ -118,14 +118,13 @@ dev.poll(); // keepalive if due `wdi_ble.hpp` wraps `WdiDevice` with the WDI GATT service (service `10A50001-…`, characteristics `10A5000{6..A}`) on `espp::BleGattServer` (esp-nimble-cpp). After -`BleGattServer::init()`, create the service, start it, advertise, and poll: +`BleGattServer::init()`, create the service, start the server, advertise, and poll: ```cpp espp::WdiBlePeripheral wdi({.on_feedback = [](const espp::wdi::FeedbackReport &f){ /*...*/ }}); espp::BleGattServer ble; ble.init("espp WDI"); wdi.make_service(ble.server()); -wdi.start(); ble.start(); espp::BleGattServer::AdvertisedData adv; adv.setName("espp WDI"); diff --git a/components/wdi/ble_example/main/wdi_ble_example.cpp b/components/wdi/ble_example/main/wdi_ble_example.cpp index a041279f27..7a9145d1a1 100644 --- a/components/wdi/ble_example/main/wdi_ble_example.cpp +++ b/components/wdi/ble_example/main/wdi_ble_example.cpp @@ -43,7 +43,6 @@ extern "C" void app_main(void) { const std::string device_name = "espp WDI"; ble.init(device_name); wdi.make_service(ble.server()); - wdi.start(); ble.start(); espp::BleGattServer::AdvertisedData adv; diff --git a/components/wdi/include/wdi_ble.hpp b/components/wdi/include/wdi_ble.hpp index 2648aa6a73..072869ef74 100644 --- a/components/wdi/include/wdi_ble.hpp +++ b/components/wdi/include/wdi_ble.hpp @@ -115,10 +115,9 @@ class WdiBlePeripheral : public BaseComponent { keepalive_resp_->setCallbacks(&keepalive_resp_cb_); } - /// @brief Kept for API symmetry with make_service(); NimBLE starts every - /// service when the server starts (NimBLEService::start() is a - /// deprecated no-op), so there is nothing to do here. - void start() {} + /// @brief Kept for API compatibility: NimBLE starts every service when the + /// server starts (BleGattServer::start()), so there is nothing to do. + [[deprecated("no-op: services start with BleGattServer::start()")]] void start() {} NimBLEService *get_service() { return service_; } From 7f2a2c13104144f1fa589112ccaa60b91d5cd721 Mon Sep 17 00:00:00 2001 From: William Emfinger Date: Sun, 25 Oct 2026 22:48:16 -0500 Subject: [PATCH 3/3] docs(ble): drop the stale "start the services" comments from the examples Review follow-up: the comment blocks that described starting services by hand (left behind when the start_services() calls went) are removed; the examples now say the server start also starts every added service, and the gfps example's comment says what gfps_service.start() still does (sets the nearby advertisement mode). Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01DFjjnq3XCTRAXENSxsCxJU --- .../example/main/ble_gatt_server_example.cpp | 8 ++------ .../gfps_service/example/main/gfps_service_example.cpp | 8 +++----- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/components/ble_gatt_server/example/main/ble_gatt_server_example.cpp b/components/ble_gatt_server/example/main/ble_gatt_server_example.cpp index 033d21af38..c0e94da181 100644 --- a/components/ble_gatt_server/example/main/ble_gatt_server_example.cpp +++ b/components/ble_gatt_server/example/main/ble_gatt_server_example.cpp @@ -67,12 +67,8 @@ extern "C" void app_main(void) { // you can create a service and add it to the server using // ble_gatt_server.server().addService() - // now start the services - // NOTE: we could also directly start them ourselves if we wanted to - // control the order of starting the services - // e.g.: - - // now start the gatt server + // now start the gatt server; this also starts every service that has + // been added to it (the built-in device info / battery services included) ble_gatt_server.start(); // let's set some of the service data diff --git a/components/gfps_service/example/main/gfps_service_example.cpp b/components/gfps_service/example/main/gfps_service_example.cpp index bcc712c94b..39f808cd00 100644 --- a/components/gfps_service/example/main/gfps_service_example.cpp +++ b/components/gfps_service/example/main/gfps_service_example.cpp @@ -51,13 +51,11 @@ extern "C" void app_main(void) { gfps_service.set_log_level(espp::Logger::Verbosity::DEBUG); gfps_service.init(ble_gatt_server.server()); - // now that we've made the input characteristic, we can start the service + // set the nearby-framework advertisement mode (the GATT service itself is + // started with the server below) gfps_service.start(); - // NOTE: we could also directly start them ourselves if we wanted to - // control the order of starting the services - // e.g.: - // now start the gatt server + // now start the gatt server; this also starts every service added to it ble_gatt_server.start(); // let's set some of the service data