From eebeb6b62c6d20526e915321ea78e4b1d8928289 Mon Sep 17 00:00:00 2001 From: yuanhonghui Date: Fri, 10 Jul 2026 11:24:20 +0800 Subject: [PATCH] feat(example): add pytest for nimble examples --- examples/bluetooth/.build-test-rules.yml | 388 +++- examples/bluetooth/PYTEST_DUAL_DUT_CI_IDS.md | 19 +- .../main/Kconfig.projbuild | 12 + .../ble_periodic_adv_with_cte/main/main.c | 17 +- .../sdkconfig.ci.name | 2 + .../main/Kconfig.projbuild | 12 + .../ble_periodic_sync_with_cte/main/main.c | 29 +- .../sdkconfig.ci.name | 3 + .../common_components/cte_config/cte_config.c | 17 +- .../common_components/cte_config/cte_config.h | 4 + .../ble_cts/cts_cent/main/Kconfig.projbuild | 12 + .../nimble/ble_cts/cts_cent/main/main.c | 78 +- .../cts_cent/sdkconfig.ci.esp32c2_xtal26m | 6 + .../nimble/ble_cts/cts_cent/sdkconfig.ci.name | 4 + .../ble_cts/cts_prph/main/Kconfig.projbuild | 12 + .../nimble/ble_cts/cts_prph/main/main.c | 61 +- .../cts_prph/sdkconfig.ci.esp32c2_xtal26m | 5 + .../nimble/ble_cts/cts_prph/sdkconfig.ci.name | 3 + .../ble_htp/htp_cent/main/Kconfig.projbuild | 12 + .../nimble/ble_htp/htp_cent/main/main.c | 78 +- .../htp_cent/sdkconfig.ci.esp32c2_xtal26m | 6 + .../nimble/ble_htp/htp_cent/sdkconfig.ci.name | 4 + .../ble_htp/htp_prph/main/Kconfig.projbuild | 13 + .../nimble/ble_htp/htp_prph/main/main.c | 61 +- .../htp_prph/sdkconfig.ci.esp32c2_xtal26m | 5 + .../nimble/ble_htp/htp_prph/sdkconfig.ci.name | 3 + .../coc_blecent/main/Kconfig.projbuild | 12 + .../ble_l2cap_coc/coc_blecent/main/main.c | 81 +- .../coc_blecent/sdkconfig.ci.esp32c2_xtal26m | 4 + .../coc_blecent/sdkconfig.ci.name | 2 + .../coc_bleprph/main/Kconfig.projbuild | 12 + .../ble_l2cap_coc/coc_bleprph/main/main.c | 70 +- .../coc_bleprph/sdkconfig.ci.esp32c2_xtal26m | 4 + .../coc_bleprph/sdkconfig.ci.name | 2 + .../sdkconfig.ci.esp32c2_xtal26m | 2 + .../nimble/ble_multi_adv/sdkconfig.ci.name | 1 + .../main/Kconfig.projbuild | 11 + .../ble_multi_conn_cent/main/main.c | 52 +- .../ble_multi_conn_cent/sdkconfig.ci.name | 4 + .../main/Kconfig.projbuild | 12 + .../ble_multi_conn_prph/main/main.c | 56 +- .../ble_multi_conn_prph/sdkconfig.ci.name | 3 + .../ble_pawr_adv/main/Kconfig.projbuild | 12 + .../ble_pawr_adv/ble_pawr_adv/main/main.c | 28 +- .../ble_pawr_adv/sdkconfig.ci.name | 2 + .../ble_pawr_sync/main/Kconfig.projbuild | 12 + .../ble_pawr_adv/ble_pawr_sync/main/main.c | 40 +- .../ble_pawr_sync/sdkconfig.ci.name | 2 + .../ble_pawr_adv_conn/main/Kconfig.projbuild | 12 + .../ble_pawr_adv_conn/main/main.c | 28 +- .../ble_pawr_adv_conn/sdkconfig.ci.name | 2 + .../ble_pawr_sync_conn/main/Kconfig.projbuild | 12 + .../ble_pawr_sync_conn/main/main.c | 39 +- .../ble_pawr_sync_conn/sdkconfig.ci.name | 2 + .../ble_periodic_adv/main/Kconfig.projbuild | 12 + .../nimble/ble_periodic_adv/main/main.c | 29 +- .../sdkconfig.ci.esp32c2_xtal26m | 4 + .../nimble/ble_periodic_adv/sdkconfig.ci.name | 2 + .../ble_periodic_sync/main/Kconfig.projbuild | 12 + .../nimble/ble_periodic_sync/main/main.c | 73 +- .../sdkconfig.ci.esp32c2_xtal26m | 4 + .../ble_periodic_sync/sdkconfig.ci.name | 2 + .../ble_phy/phy_cent/main/Kconfig.projbuild | 12 + .../nimble/ble_phy/phy_cent/main/main.c | 55 + .../phy_cent/sdkconfig.ci.esp32c2_xtal26m | 4 + .../nimble/ble_phy/phy_cent/sdkconfig.ci.name | 2 + .../ble_phy/phy_prph/main/Kconfig.projbuild | 12 + .../nimble/ble_phy/phy_prph/main/main.c | 57 +- .../phy_prph/sdkconfig.ci.esp32c2_xtal26m | 4 + .../nimble/ble_phy/phy_prph/sdkconfig.ci.name | 2 + .../main/Kconfig.projbuild | 12 + .../proximity_sensor_cent/main/main.c | 139 +- .../sdkconfig.ci.conn_with_scan | 3 + .../sdkconfig.ci.conn_with_scan_v4 | 4 + .../sdkconfig.ci.esp32_name_v4 | 3 + .../sdkconfig.ci.esp32c2_xtal26m | 5 + ...dkconfig.ci.esp32c2_xtal26m_conn_with_scan | 5 + ...onfig.ci.esp32c2_xtal26m_conn_with_scan_v4 | 6 + .../sdkconfig.ci.esp32c2_xtal26m_name_v4 | 6 + .../proximity_sensor_cent/sdkconfig.ci.name | 3 + .../sdkconfig.ci.name_v4 | 4 + .../main/Kconfig.projbuild | 12 + .../proximity_sensor_prph/main/main.c | 43 +- .../sdkconfig.ci.conn_with_scan | 3 + .../sdkconfig.ci.conn_with_scan_v4 | 4 + .../sdkconfig.ci.esp32_name_v4 | 3 + .../sdkconfig.ci.esp32c2_xtal26m | 5 + ...dkconfig.ci.esp32c2_xtal26m_conn_with_scan | 5 + ...onfig.ci.esp32c2_xtal26m_conn_with_scan_v4 | 6 + .../sdkconfig.ci.esp32c2_xtal26m_name_v4 | 6 + .../proximity_sensor_prph/sdkconfig.ci.name | 3 + .../sdkconfig.ci.name_v4 | 4 + .../ble_spp/spp_client/main/Kconfig.projbuild | 15 + .../nimble/ble_spp/spp_client/main/main.c | 51 +- .../spp_client/sdkconfig.ci.esp32c2_xtal26m | 4 + .../ble_spp/spp_client/sdkconfig.ci.name | 2 + .../ble_spp/spp_server/main/Kconfig.projbuild | 12 + .../nimble/ble_spp/spp_server/main/main.c | 47 +- .../spp_server/sdkconfig.ci.esp32c2_xtal26m | 4 + .../ble_spp/spp_server/sdkconfig.ci.name | 2 + .../nimble/blecent/main/Kconfig.projbuild | 8 + examples/bluetooth/nimble/blecent/main/main.c | 74 +- .../sdkconfig.ci.bleprph_esp32c2_xtal26m | 7 + .../nimble/blecent/sdkconfig.ci.name | 5 + .../nimble/bleprph/main/Kconfig.projbuild | 8 + examples/bluetooth/nimble/bleprph/main/main.c | 63 +- .../sdkconfig.ci.bleprph_esp32c2_xtal26m | 7 + .../nimble/bleprph/sdkconfig.ci.name | 5 + .../bluetooth/nimble/pytest_nimble_test.py | 1802 ++++++++++++++++- .../blecent_throughput/main/Kconfig.projbuild | 8 + .../gatt/blecent_throughput/main/main.c | 83 + .../sdkconfig.ci.esp32c2_xtal26m | 4 + .../gatt/blecent_throughput/sdkconfig.ci.name | 2 + .../bleprph_throughput/main/Kconfig.projbuild | 8 + .../gatt/bleprph_throughput/main/main.c | 53 +- .../sdkconfig.ci.esp32c2_xtal26m | 4 + .../gatt/bleprph_throughput/sdkconfig.ci.name | 2 + .../l2cap_coc_cent/main/Kconfig.projbuild | 12 + .../l2cap_coc/l2cap_coc_cent/main/main.c | 66 + .../sdkconfig.ci.esp32c2_xtal26m | 6 + .../l2cap_coc_cent/sdkconfig.ci.name | 4 + .../l2cap_coc_prph/main/Kconfig.projbuild | 12 + .../l2cap_coc/l2cap_coc_prph/main/main.c | 70 +- .../sdkconfig.ci.esp32c2_xtal26m | 4 + .../l2cap_coc_prph/sdkconfig.ci.name | 2 + 125 files changed, 4249 insertions(+), 162 deletions(-) create mode 100644 examples/bluetooth/nimble/ble_cte/ble_periodic_adv_with_cte/sdkconfig.ci.name create mode 100644 examples/bluetooth/nimble/ble_cte/ble_periodic_sync_with_cte/sdkconfig.ci.name create mode 100644 examples/bluetooth/nimble/ble_cts/cts_cent/sdkconfig.ci.esp32c2_xtal26m create mode 100644 examples/bluetooth/nimble/ble_cts/cts_cent/sdkconfig.ci.name create mode 100644 examples/bluetooth/nimble/ble_cts/cts_prph/sdkconfig.ci.esp32c2_xtal26m create mode 100644 examples/bluetooth/nimble/ble_cts/cts_prph/sdkconfig.ci.name create mode 100644 examples/bluetooth/nimble/ble_htp/htp_cent/sdkconfig.ci.esp32c2_xtal26m create mode 100644 examples/bluetooth/nimble/ble_htp/htp_cent/sdkconfig.ci.name create mode 100644 examples/bluetooth/nimble/ble_htp/htp_prph/sdkconfig.ci.esp32c2_xtal26m create mode 100644 examples/bluetooth/nimble/ble_htp/htp_prph/sdkconfig.ci.name create mode 100644 examples/bluetooth/nimble/ble_l2cap_coc/coc_blecent/sdkconfig.ci.esp32c2_xtal26m create mode 100644 examples/bluetooth/nimble/ble_l2cap_coc/coc_blecent/sdkconfig.ci.name create mode 100644 examples/bluetooth/nimble/ble_l2cap_coc/coc_bleprph/sdkconfig.ci.esp32c2_xtal26m create mode 100644 examples/bluetooth/nimble/ble_l2cap_coc/coc_bleprph/sdkconfig.ci.name create mode 100644 examples/bluetooth/nimble/ble_multi_adv/sdkconfig.ci.esp32c2_xtal26m create mode 100644 examples/bluetooth/nimble/ble_multi_adv/sdkconfig.ci.name create mode 100644 examples/bluetooth/nimble/ble_multi_conn/ble_multi_conn_cent/sdkconfig.ci.name create mode 100644 examples/bluetooth/nimble/ble_multi_conn/ble_multi_conn_prph/sdkconfig.ci.name create mode 100644 examples/bluetooth/nimble/ble_pawr_adv/ble_pawr_adv/sdkconfig.ci.name create mode 100644 examples/bluetooth/nimble/ble_pawr_adv/ble_pawr_sync/sdkconfig.ci.name create mode 100644 examples/bluetooth/nimble/ble_pawr_adv_conn/ble_pawr_adv_conn/sdkconfig.ci.name create mode 100644 examples/bluetooth/nimble/ble_pawr_adv_conn/ble_pawr_sync_conn/sdkconfig.ci.name create mode 100644 examples/bluetooth/nimble/ble_periodic_adv/sdkconfig.ci.esp32c2_xtal26m create mode 100644 examples/bluetooth/nimble/ble_periodic_adv/sdkconfig.ci.name create mode 100644 examples/bluetooth/nimble/ble_periodic_sync/sdkconfig.ci.esp32c2_xtal26m create mode 100644 examples/bluetooth/nimble/ble_periodic_sync/sdkconfig.ci.name create mode 100644 examples/bluetooth/nimble/ble_phy/phy_cent/sdkconfig.ci.esp32c2_xtal26m create mode 100644 examples/bluetooth/nimble/ble_phy/phy_cent/sdkconfig.ci.name create mode 100644 examples/bluetooth/nimble/ble_phy/phy_prph/sdkconfig.ci.esp32c2_xtal26m create mode 100644 examples/bluetooth/nimble/ble_phy/phy_prph/sdkconfig.ci.name create mode 100644 examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_cent/sdkconfig.ci.conn_with_scan create mode 100644 examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_cent/sdkconfig.ci.conn_with_scan_v4 create mode 100644 examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_cent/sdkconfig.ci.esp32_name_v4 create mode 100644 examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_cent/sdkconfig.ci.esp32c2_xtal26m create mode 100644 examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_cent/sdkconfig.ci.esp32c2_xtal26m_conn_with_scan create mode 100644 examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_cent/sdkconfig.ci.esp32c2_xtal26m_conn_with_scan_v4 create mode 100644 examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_cent/sdkconfig.ci.esp32c2_xtal26m_name_v4 create mode 100644 examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_cent/sdkconfig.ci.name create mode 100644 examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_cent/sdkconfig.ci.name_v4 create mode 100644 examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_prph/sdkconfig.ci.conn_with_scan create mode 100644 examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_prph/sdkconfig.ci.conn_with_scan_v4 create mode 100644 examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_prph/sdkconfig.ci.esp32_name_v4 create mode 100644 examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_prph/sdkconfig.ci.esp32c2_xtal26m create mode 100644 examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_prph/sdkconfig.ci.esp32c2_xtal26m_conn_with_scan create mode 100644 examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_prph/sdkconfig.ci.esp32c2_xtal26m_conn_with_scan_v4 create mode 100644 examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_prph/sdkconfig.ci.esp32c2_xtal26m_name_v4 create mode 100644 examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_prph/sdkconfig.ci.name create mode 100644 examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_prph/sdkconfig.ci.name_v4 create mode 100644 examples/bluetooth/nimble/ble_spp/spp_client/main/Kconfig.projbuild create mode 100644 examples/bluetooth/nimble/ble_spp/spp_client/sdkconfig.ci.esp32c2_xtal26m create mode 100644 examples/bluetooth/nimble/ble_spp/spp_client/sdkconfig.ci.name create mode 100644 examples/bluetooth/nimble/ble_spp/spp_server/sdkconfig.ci.esp32c2_xtal26m create mode 100644 examples/bluetooth/nimble/ble_spp/spp_server/sdkconfig.ci.name create mode 100644 examples/bluetooth/nimble/blecent/sdkconfig.ci.bleprph_esp32c2_xtal26m create mode 100644 examples/bluetooth/nimble/blecent/sdkconfig.ci.name create mode 100644 examples/bluetooth/nimble/bleprph/sdkconfig.ci.bleprph_esp32c2_xtal26m create mode 100644 examples/bluetooth/nimble/bleprph/sdkconfig.ci.name create mode 100644 examples/bluetooth/nimble/throughput_app/gatt/blecent_throughput/sdkconfig.ci.esp32c2_xtal26m create mode 100644 examples/bluetooth/nimble/throughput_app/gatt/blecent_throughput/sdkconfig.ci.name create mode 100644 examples/bluetooth/nimble/throughput_app/gatt/bleprph_throughput/sdkconfig.ci.esp32c2_xtal26m create mode 100644 examples/bluetooth/nimble/throughput_app/gatt/bleprph_throughput/sdkconfig.ci.name create mode 100644 examples/bluetooth/nimble/throughput_app/l2cap_coc/l2cap_coc_cent/sdkconfig.ci.esp32c2_xtal26m create mode 100644 examples/bluetooth/nimble/throughput_app/l2cap_coc/l2cap_coc_cent/sdkconfig.ci.name create mode 100644 examples/bluetooth/nimble/throughput_app/l2cap_coc/l2cap_coc_prph/sdkconfig.ci.esp32c2_xtal26m create mode 100644 examples/bluetooth/nimble/throughput_app/l2cap_coc/l2cap_coc_prph/sdkconfig.ci.name diff --git a/examples/bluetooth/.build-test-rules.yml b/examples/bluetooth/.build-test-rules.yml index 8827b56cf24..6ac9bec1622 100644 --- a/examples/bluetooth/.build-test-rules.yml +++ b/examples/bluetooth/.build-test-rules.yml @@ -414,12 +414,54 @@ examples/bluetooth/nimble/ble_chan_sound_reflector: depends_filepatterns: - examples/bluetooth/nimble/ble_chan_sound_reflector/**/* - examples/bluetooth/nimble/common/**/* -examples/bluetooth/nimble/ble_cte: + +examples/bluetooth/nimble/ble_cte/ble_periodic_adv_with_cte: <<: *bt_default_depends enable: - if: SOC_BLE_CTE_SUPPORTED == 1 + disable_test: + - if: IDF_TARGET == "esp32h4" + temporary: true + reason: lack of runner depends_filepatterns: - examples/bluetooth/nimble/ble_cte/common_components/* + - examples/bluetooth/nimble/pytest_nimble_test.py + +examples/bluetooth/nimble/ble_cte/ble_periodic_sync_with_cte: + <<: *bt_default_depends + enable: + - if: SOC_BLE_CTE_SUPPORTED == 1 + disable_test: + - if: IDF_TARGET == "esp32h4" + temporary: true + reason: lack of runner + depends_filepatterns: + - examples/bluetooth/nimble/ble_cte/common_components/* + - examples/bluetooth/nimble/pytest_nimble_test.py + +examples/bluetooth/nimble/ble_cts/cts_cent: + <<: *bt_default_depends + disable: + - if: SOC_BLE_SUPPORTED != 1 + disable_test: + - if: IDF_TARGET == "esp32h4" # TODO: IDFCI-11112 + temporary: true + reason: lack of runner + depends_filepatterns: + - examples/bluetooth/nimble/common/**/* + - examples/bluetooth/nimble/pytest_nimble_test.py + +examples/bluetooth/nimble/ble_cts/cts_prph: + <<: *bt_default_depends + disable: + - if: SOC_BLE_SUPPORTED != 1 + disable_test: + - if: IDF_TARGET == "esp32h4" # TODO: IDFCI-11112 + temporary: true + reason: lack of runner + depends_filepatterns: + - examples/bluetooth/nimble/common/**/* + - examples/bluetooth/nimble/pytest_nimble_test.py examples/bluetooth/nimble/ble_enc_adv_data: <<: *bt_default_depends @@ -430,14 +472,70 @@ examples/bluetooth/nimble/ble_enc_adv_data: depends_filepatterns: - examples/bluetooth/nimble/common/**/* +examples/bluetooth/nimble/ble_htp/htp_cent: + <<: *bt_default_depends + disable: + - if: SOC_BLE_SUPPORTED != 1 + disable_test: + - if: IDF_TARGET == "esp32h4" # TODO: IDFCI-11112 + temporary: true + reason: lack of runner + depends_filepatterns: + - examples/bluetooth/nimble/common/**/* + - examples/bluetooth/nimble/pytest_nimble_test.py + +examples/bluetooth/nimble/ble_htp/htp_prph: + <<: *bt_default_depends + disable: + - if: SOC_BLE_SUPPORTED != 1 + disable_test: + - if: IDF_TARGET == "esp32h4" # TODO: IDFCI-11112 + temporary: true + reason: lack of runner + depends_filepatterns: + - examples/bluetooth/nimble/common/**/* + - examples/bluetooth/nimble/pytest_nimble_test.py + +examples/bluetooth/nimble/ble_l2cap_coc/coc_blecent: + <<: *bt_default_depends + disable: + - if: SOC_BLE_SUPPORTED != 1 + disable_test: + - if: IDF_TARGET == "esp32h4" # TODO: IDFCI-11112 + temporary: true + reason: lack of runner + depends_filepatterns: + - examples/bluetooth/nimble/common/**/* + - examples/bluetooth/nimble/pytest_nimble_test.py + +examples/bluetooth/nimble/ble_l2cap_coc/coc_bleprph: + <<: *bt_default_depends + disable: + - if: SOC_BLE_SUPPORTED != 1 + disable_test: + - if: IDF_TARGET == "esp32h4" # TODO: IDFCI-11112 + temporary: true + reason: lack of runner + depends_filepatterns: + - examples/bluetooth/nimble/common/**/* + - examples/bluetooth/nimble/pytest_nimble_test.py + examples/bluetooth/nimble/ble_multi_adv: <<: *bt_default_depends enable: - if: SOC_BLE_SUPPORTED == 1 and IDF_TARGET != "esp32" temporary: true reason: the other targets are not tested yet + disable_test: + - if: IDF_TARGET == "esp32h4" # TODO: IDFCI-11112 + temporary: true + reason: lack of runner + - if: IDF_TARGET == "esp32h21" + temporary: true + reason: lack of runner depends_filepatterns: - examples/bluetooth/nimble/common/**/* + - examples/bluetooth/nimble/pytest_nimble_test.py examples/bluetooth/nimble/ble_multi_conn: <<: *bt_default_depends @@ -448,33 +546,135 @@ examples/bluetooth/nimble/ble_multi_conn: depends_filepatterns: - examples/bluetooth/nimble/common/**/* -examples/bluetooth/nimble/ble_pawr_adv: +examples/bluetooth/nimble/ble_multi_conn/ble_multi_conn_cent: <<: *bt_default_depends enable: - if: SOC_ESP_NIMBLE_CONTROLLER == 1 and IDF_TARGET != "esp32c2" + disable_test: + - if: IDF_TARGET == "esp32h4" # TODO: IDFCI-11112 + temporary: true + reason: lack of runner + - if: IDF_TARGET == "esp32h21" + temporary: true + reason: lack of runner + depends_filepatterns: + - examples/bluetooth/nimble/common/**/* + - examples/bluetooth/nimble/pytest_nimble_test.py + +examples/bluetooth/nimble/ble_multi_conn/ble_multi_conn_prph: + <<: *bt_default_depends + enable: + - if: SOC_ESP_NIMBLE_CONTROLLER == 1 and IDF_TARGET != "esp32c2" + disable_test: + - if: IDF_TARGET == "esp32h4" # TODO: IDFCI-11112 + temporary: true + reason: lack of runner + - if: IDF_TARGET == "esp32h21" + temporary: true + reason: lack of runner + depends_filepatterns: + - examples/bluetooth/nimble/common/**/* + - examples/bluetooth/nimble/pytest_nimble_test.py + +examples/bluetooth/nimble/ble_pawr_adv: + <<: *bt_default_depends + enable: + - if: SOC_ESP_NIMBLE_CONTROLLER == 1 and SOC_BLE_PERIODIC_ADV_WITH_RESPONSE == 1 + +examples/bluetooth/nimble/ble_pawr_adv/ble_pawr_adv: + <<: *bt_default_depends + enable: + - if: SOC_ESP_NIMBLE_CONTROLLER == 1 and SOC_BLE_PERIODIC_ADV_WITH_RESPONSE == 1 + disable_test: + - if: IDF_TARGET == "esp32h4" # TODO: IDFCI-11112 + temporary: true + reason: lack of runner + - if: IDF_TARGET == "esp32h21" + temporary: true + reason: lack of runner + depends_filepatterns: + - examples/bluetooth/nimble/common/**/* + - examples/bluetooth/nimble/pytest_nimble_test.py + +examples/bluetooth/nimble/ble_pawr_adv/ble_pawr_sync: + <<: *bt_default_depends + enable: + - if: SOC_ESP_NIMBLE_CONTROLLER == 1 and SOC_BLE_PERIODIC_ADV_WITH_RESPONSE == 1 + disable_test: + - if: IDF_TARGET == "esp32h4" # TODO: IDFCI-11112 + temporary: true + reason: lack of runner + - if: IDF_TARGET == "esp32h21" + temporary: true + reason: lack of runner + depends_filepatterns: + - examples/bluetooth/nimble/common/**/* + - examples/bluetooth/nimble/pytest_nimble_test.py examples/bluetooth/nimble/ble_pawr_adv_conn: <<: *bt_default_depends enable: - - if: SOC_ESP_NIMBLE_CONTROLLER == 1 and IDF_TARGET != "esp32c2" + - if: SOC_ESP_NIMBLE_CONTROLLER == 1 and SOC_BLE_PERIODIC_ADV_WITH_RESPONSE == 1 + +examples/bluetooth/nimble/ble_pawr_adv_conn/ble_pawr_adv_conn: + <<: *bt_default_depends + enable: + - if: SOC_ESP_NIMBLE_CONTROLLER == 1 and SOC_BLE_PERIODIC_ADV_WITH_RESPONSE == 1 + disable_test: + - if: IDF_TARGET == "esp32h4" # TODO: IDFCI-11112 + temporary: true + reason: lack of runner + - if: IDF_TARGET == "esp32h21" + temporary: true + reason: lack of runner + depends_filepatterns: + - examples/bluetooth/nimble/common/**/* + - examples/bluetooth/nimble/pytest_nimble_test.py + +examples/bluetooth/nimble/ble_pawr_adv_conn/ble_pawr_sync_conn: + <<: *bt_default_depends + enable: + - if: SOC_ESP_NIMBLE_CONTROLLER == 1 and SOC_BLE_PERIODIC_ADV_WITH_RESPONSE == 1 + disable_test: + - if: IDF_TARGET == "esp32h4" # TODO: IDFCI-11112 + temporary: true + reason: lack of runner + - if: IDF_TARGET == "esp32h21" + temporary: true + reason: lack of runner + depends_filepatterns: + - examples/bluetooth/nimble/common/**/* + - examples/bluetooth/nimble/pytest_nimble_test.py examples/bluetooth/nimble/ble_periodic_adv: <<: *bt_default_depends enable: - - if: SOC_BLE_SUPPORTED == 1 and IDF_TARGET != "esp32" + - if: SOC_BLE_SUPPORTED == 1 and SOC_BLE_50_SUPPORTED == 1 + disable_test: + - if: IDF_TARGET == "esp32h4" # TODO: IDFCI-11112 temporary: true - reason: the other targets are not tested yet + reason: lack of runner + - if: IDF_TARGET == "esp32h21" + temporary: true + reason: lack of runner depends_filepatterns: - examples/bluetooth/nimble/common/**/* + - examples/bluetooth/nimble/pytest_nimble_test.py examples/bluetooth/nimble/ble_periodic_sync: <<: *bt_default_depends enable: - - if: SOC_BLE_SUPPORTED == 1 and IDF_TARGET != "esp32" + - if: SOC_BLE_SUPPORTED == 1 and SOC_BLE_50_SUPPORTED == 1 + disable_test: + - if: IDF_TARGET == "esp32h4" # TODO: IDFCI-11112 temporary: true - reason: the other targets are not tested yet + reason: lack of runner + - if: IDF_TARGET == "esp32h21" + temporary: true + reason: lack of runner depends_filepatterns: - examples/bluetooth/nimble/common/**/* + - examples/bluetooth/nimble/pytest_nimble_test.py examples/bluetooth/nimble/ble_phy: <<: *bt_default_depends @@ -485,14 +685,107 @@ examples/bluetooth/nimble/ble_phy: depends_filepatterns: - examples/bluetooth/nimble/common/**/* +examples/bluetooth/nimble/ble_phy/phy_cent: + <<: *bt_default_depends + enable: + - if: SOC_BLE_SUPPORTED == 1 and IDF_TARGET != "esp32" + disable_test: + - if: IDF_TARGET == "esp32h4" # TODO: IDFCI-11112 + temporary: true + reason: lack of runner + depends_filepatterns: + - examples/bluetooth/nimble/common/**/* + - examples/bluetooth/nimble/pytest_nimble_test.py + +examples/bluetooth/nimble/ble_phy/phy_prph: + <<: *bt_default_depends + enable: + - if: SOC_BLE_SUPPORTED == 1 and IDF_TARGET != "esp32" + disable_test: + - if: IDF_TARGET == "esp32h4" # TODO: IDFCI-11112 + temporary: true + reason: lack of runner + depends_filepatterns: + - examples/bluetooth/nimble/common/**/* + - examples/bluetooth/nimble/pytest_nimble_test.py + +examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_cent: + <<: *bt_default_depends + disable: + - if: SOC_BLE_SUPPORTED != 1 + - if: IDF_TARGET == "esp32" and CONFIG_NAME in ["name", "conn_with_scan", "conn_with_scan_v4", "name_v4"] + reason: esp32 does not support extended adv / connect-with-scan used by these CI variants + - if: IDF_TARGET != "esp32" and CONFIG_NAME == "esp32_name_v4" + reason: esp32_name_v4 is for ESP32 only + - if: IDF_TARGET != "esp32c2" and CONFIG_NAME in ["esp32c2_xtal26m", "esp32c2_xtal26m_conn_with_scan", "esp32c2_xtal26m_name_v4", "esp32c2_xtal26m_conn_with_scan_v4"] + reason: esp32c2_xtal26m* configs are for ESP32-C2 26MHz only + disable_test: + - if: IDF_TARGET == "esp32h4" # TODO: IDFCI-11112 + temporary: true + reason: lack of runner + - if: IDF_TARGET == "esp32h21" + temporary: true + reason: lack of runner + - if: IDF_TARGET == "esp32s31" # TODO: BLEQABR25-2508 + temporary: true + reason: ble bugs + depends_filepatterns: + - examples/bluetooth/nimble/common/**/* + - examples/bluetooth/nimble/pytest_nimble_test.py + +examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_prph: + <<: *bt_default_depends + disable: + - if: SOC_BLE_SUPPORTED != 1 + - if: IDF_TARGET == "esp32" and CONFIG_NAME in ["name", "conn_with_scan", "conn_with_scan_v4", "name_v4"] + reason: esp32 does not support extended adv / connect-with-scan used by these CI variants + - if: IDF_TARGET != "esp32" and CONFIG_NAME == "esp32_name_v4" + reason: esp32_name_v4 is for ESP32 only + - if: IDF_TARGET != "esp32c2" and CONFIG_NAME in ["esp32c2_xtal26m", "esp32c2_xtal26m_conn_with_scan", "esp32c2_xtal26m_name_v4", "esp32c2_xtal26m_conn_with_scan_v4"] + reason: esp32c2_xtal26m* configs are for ESP32-C2 26MHz only + disable_test: + - if: IDF_TARGET == "esp32h4" # TODO: IDFCI-11112 + temporary: true + reason: lack of runner + - if: IDF_TARGET == "esp32h21" + temporary: true + reason: lack of runner + - if: IDF_TARGET == "esp32s31" # TODO: BLEQABR25-2508 + temporary: true + reason: ble bugs + depends_filepatterns: + - examples/bluetooth/nimble/common/**/* + - examples/bluetooth/nimble/pytest_nimble_test.py + +examples/bluetooth/nimble/ble_spp/spp_client: + <<: *bt_default_depends + disable: + - if: SOC_BLE_SUPPORTED != 1 + disable_test: + - if: IDF_TARGET == "esp32h4" # TODO: IDFCI-11112 + temporary: true + reason: lack of runner + depends_filepatterns: + - examples/bluetooth/nimble/common/**/* + - examples/bluetooth/nimble/pytest_nimble_test.py + +examples/bluetooth/nimble/ble_spp/spp_server: + <<: *bt_default_depends + disable: + - if: SOC_BLE_SUPPORTED != 1 + disable_test: + - if: IDF_TARGET == "esp32h4" # TODO: IDFCI-11112 + temporary: true + reason: lack of runner + depends_filepatterns: + - examples/bluetooth/nimble/common/**/* + - examples/bluetooth/nimble/pytest_nimble_test.py + examples/bluetooth/nimble/blecent: <<: *bt_default_depends disable: - if: SOC_BLE_SUPPORTED != 1 disable_test: - - if: IDF_TARGET == "esp32s31" - temporary: true - reason: lack of runners - if: IDF_TARGET == "esp32h4" # TODO: IDFCI-11112 temporary: true reason: lack of runner @@ -502,6 +795,7 @@ examples/bluetooth/nimble/blecent: depends_filepatterns: - examples/bluetooth/nimble/common/**/* - examples/bluetooth/nimble/blecent/**/* + - examples/bluetooth/nimble/bleprph/**/* - examples/bluetooth/nimble/power_save/**/* - examples/bluetooth/nimble/pytest_nimble_test.py @@ -514,6 +808,20 @@ examples/bluetooth/nimble/blemesh: depends_filepatterns: - examples/bluetooth/nimble/common/**/* +examples/bluetooth/nimble/bleprph: + <<: *bt_default_depends + disable: + - if: SOC_BLE_SUPPORTED != 1 + disable_test: + - if: IDF_TARGET == "esp32h4" # TODO: IDFCI-11112 + temporary: true + reason: lack of runner + depends_filepatterns: + - examples/bluetooth/nimble/common/**/* + - examples/bluetooth/nimble/blecent/**/* + - examples/bluetooth/nimble/bleprph/**/* + - examples/bluetooth/nimble/pytest_nimble_test.py + examples/bluetooth/nimble/bleprph_wifi_coex: <<: *bt_default_depends disable: @@ -541,7 +849,7 @@ examples/bluetooth/nimble/power_save: disable_test: - if: IDF_TARGET == "esp32s31" temporary: true - reason: lack of runners, and light sleep not supported yet + reason: light sleep not supported yet - if: IDF_TARGET == "esp32h4" # TODO: IDFCI-11112 temporary: true reason: lack of runner @@ -560,30 +868,84 @@ examples/bluetooth/nimble/throughput_app: - if: SOC_BLE_SUPPORTED != 1 depends_filepatterns: - examples/bluetooth/nimble/common/**/* + - examples/bluetooth/nimble/pytest_nimble_test.py examples/bluetooth/nimble/throughput_app/gatt/blecent_throughput: <<: *bt_default_depends disable: - if: SOC_BLE_SUPPORTED != 1 + disable_test: + - if: IDF_TARGET == "esp32h21" + temporary: true + reason: lack of runner + - if: IDF_TARGET == "esp32h4" # TODO: IDFCI-11112 + temporary: true + reason: lack of runner + - if: IDF_TARGET == "esp32s31" # TODO: BLEQABR25-2509 + temporary: true + reason: ble bugs depends_components+: - esp_driver_gpio - esp_driver_uart depends_filepatterns: - examples/bluetooth/nimble/common/**/* - examples/bluetooth/nimble/throughput_app/gatt/blecent_throughput/components/**/* + - examples/bluetooth/nimble/throughput_app/gatt/bleprph_throughput/**/* + - examples/bluetooth/nimble/pytest_nimble_test.py + +examples/bluetooth/nimble/throughput_app/gatt/bleprph_throughput: + <<: *bt_default_depends + disable: + - if: SOC_BLE_SUPPORTED != 1 + disable_test: + - if: IDF_TARGET == "esp32h21" + temporary: true + reason: lack of runner + - if: IDF_TARGET == "esp32h4" # TODO: IDFCI-11112 + temporary: true + reason: lack of runner + - if: IDF_TARGET == "esp32s31" # TODO: BLEQABR25-2509 + temporary: true + reason: ble bugs + depends_filepatterns: + - examples/bluetooth/nimble/common/**/* + - examples/bluetooth/nimble/throughput_app/gatt/blecent_throughput/**/* + - examples/bluetooth/nimble/pytest_nimble_test.py examples/bluetooth/nimble/throughput_app/l2cap_coc/l2cap_coc_cent: <<: *bt_default_depends disable: - if: SOC_BLE_SUPPORTED != 1 + disable_test: + - if: IDF_TARGET == "esp32h21" + temporary: true + reason: lack of runner + - if: IDF_TARGET == "esp32h4" # TODO: IDFCI-11112 + temporary: true + reason: lack of runner + - if: IDF_TARGET == "esp32c2" # TODO: BLEQABR25-2507 + temporary: true + reason: ble bugs depends_filepatterns: - examples/bluetooth/nimble/common/**/* - - examples/bluetooth/nimble/throughput_app/l2cap_coc/l2cap_coc_cent/**/* + - examples/bluetooth/nimble/throughput_app/l2cap_coc/l2cap_coc_prph/**/* + - examples/bluetooth/nimble/pytest_nimble_test.py examples/bluetooth/nimble/throughput_app/l2cap_coc/l2cap_coc_prph: <<: *bt_default_depends disable: - if: SOC_BLE_SUPPORTED != 1 + disable_test: + - if: IDF_TARGET == "esp32h21" + temporary: true + reason: lack of runner + - if: IDF_TARGET == "esp32h4" # TODO: IDFCI-11112 + temporary: true + reason: lack of runner + - if: IDF_TARGET == "esp32c2" # TODO: BLEQABR25-2507 + temporary: true + reason: ble bugs depends_filepatterns: - examples/bluetooth/nimble/common/**/* - - examples/bluetooth/nimble/throughput_app/l2cap_coc/l2cap_coc_prph/**/* + - examples/bluetooth/nimble/throughput_app/l2cap_coc/l2cap_coc_cent/**/* + - examples/bluetooth/nimble/pytest_nimble_test.py diff --git a/examples/bluetooth/PYTEST_DUAL_DUT_CI_IDS.md b/examples/bluetooth/PYTEST_DUAL_DUT_CI_IDS.md index 2a360ddc224..fb7a2499219 100644 --- a/examples/bluetooth/PYTEST_DUAL_DUT_CI_IDS.md +++ b/examples/bluetooth/PYTEST_DUAL_DUT_CI_IDS.md @@ -60,8 +60,25 @@ Paths are relative to `examples/bluetooth/`. Bluedroid uses `esp_bluedroid_get_e | 23 | `bluedroid/ble_50/ble50_throughput/throughput_server` / `throughput_client` (`notify`) | `bluedroid/ble_50/ble50_throughput/pytest_ble50_throughput_test.py` | | 24 | same pair (`write`) | same | | 25 | `nimble/ble_cte/ble_periodic_adv_with_cte` / `ble_periodic_sync_with_cte` | `nimble/pytest_nimble_test.py` | +| 26 | `nimble/ble_cts/cts_prph` / `cts_cent` | `nimble/pytest_nimble_test.py` | +| 27 | `nimble/ble_htp/htp_prph` / `htp_cent` | `nimble/pytest_nimble_test.py` | +| 28 | `nimble/ble_spp/spp_server` / `spp_client` | `nimble/pytest_nimble_test.py` | +| 29 | `nimble/ble_multi_conn/ble_multi_conn_prph` / `ble_multi_conn_cent` | `nimble/pytest_nimble_test.py` | +| 30 | `nimble/ble_phy/phy_prph` / `phy_cent` | `nimble/pytest_nimble_test.py` | +| 31 | `nimble/ble_pawr_adv_conn/ble_pawr_adv_conn` / `ble_pawr_sync_conn` | `nimble/pytest_nimble_test.py` | +| 32 | `nimble/ble_pawr_adv/ble_pawr_adv` / `ble_pawr_sync` | `nimble/pytest_nimble_test.py` | +| 33 | `nimble/ble_proximity_sensor` (`name` / `esp32c2_xtal26m`) | `nimble/pytest_nimble_test.py` | +| 34 | `nimble/ble_proximity_sensor` (`conn_with_scan` / `esp32c2_xtal26m_conn_with_scan`) | same | +| 35 | `nimble/ble_proximity_sensor` (`name_v4` / `esp32c2_xtal26m_name_v4`) | same | +| 36 | `nimble/ble_proximity_sensor` (`conn_with_scan_v4` / `esp32c2_xtal26m_conn_with_scan_v4`) | same | +| 37 | `nimble/ble_proximity_sensor` (`esp32_name_v4`) | same | +| 38 | `nimble/ble_periodic_adv` / `ble_periodic_sync` | `nimble/pytest_nimble_test.py` | +| 39 | `nimble/bleprph` / `blecent` | `nimble/pytest_nimble_test.py` | +| 40 | `nimble/throughput_app/gatt/bleprph_throughput` / `blecent_throughput` | `nimble/pytest_nimble_test.py` | +| 41 | `nimble/ble_l2cap_coc/coc_bleprph` / `coc_blecent` | `nimble/pytest_nimble_test.py` | +| 42 | `nimble/throughput_app/l2cap_coc/l2cap_coc_prph` / `l2cap_coc_cent` | `nimble/pytest_nimble_test.py` | -**Next available Example ID: 26** +**Next available Example ID: 43** --- diff --git a/examples/bluetooth/nimble/ble_cte/ble_periodic_adv_with_cte/main/Kconfig.projbuild b/examples/bluetooth/nimble/ble_cte/ble_periodic_adv_with_cte/main/Kconfig.projbuild index be0efca6de7..22badcd062b 100644 --- a/examples/bluetooth/nimble/ble_cte/ble_periodic_adv_with_cte/main/Kconfig.projbuild +++ b/examples/bluetooth/nimble/ble_cte/ble_periodic_adv_with_cte/main/Kconfig.projbuild @@ -77,4 +77,16 @@ menu "Example Configuration" help Use this option to advertise a random address instead of public address + config EXAMPLE_CI_ID + int "example id for CI test" + default 0 + help + This config the example id for CI test. Only for internal used. + + config EXAMPLE_CI_PIPELINE_ID + int "The pipeline id for CI test" + default 0 + help + This config the pipeline id for CI test. Only for internal used. + endmenu diff --git a/examples/bluetooth/nimble/ble_cte/ble_periodic_adv_with_cte/main/main.c b/examples/bluetooth/nimble/ble_cte/ble_periodic_adv_with_cte/main/main.c index 85c02629467..7b96548d7ad 100644 --- a/examples/bluetooth/nimble/ble_cte/ble_periodic_adv_with_cte/main/main.c +++ b/examples/bluetooth/nimble/ble_cte/ble_periodic_adv_with_cte/main/main.c @@ -6,6 +6,7 @@ #include "esp_log.h" #include "nvs_flash.h" +#include #include "nimble/nimble_port.h" #include "nimble/nimble_port_freertos.h" #include "host/ble_hs.h" @@ -17,6 +18,7 @@ /* Global constants */ static const char *TAG = "CTE_ADV_EXAMPLE"; +static char adv_device_name[32] = "CTE_Periodic_Adv"; static uint8_t s_periodic_adv_raw_data[] = {0x0D, BLE_HS_ADV_TYPE_COMP_NAME, 'C','T','E',' ','P','e','r','i','o','d','i','c'}; #if !(MYNEWT_VAL(BLE_EXT_ADV) && MYNEWT_VAL(BLE_PERIODIC_ADV) && MYNEWT_VAL(BLE_AOA_AOD)) @@ -38,8 +40,8 @@ static void start_periodic_adv_cte(uint8_t own_addr_type) assert(rc == 0); ESP_LOGI(TAG, "Device Address: "); - ESP_LOGI(TAG, "%02x:%02x:%02x:%02x:%02x:%02x", - addr.val[5], addr.val[4], addr.val[3], addr.val[2], addr.val[1], addr.val[0]); + ESP_LOGI(TAG, "Bluetooth MAC: %02x:%02x:%02x:%02x:%02x:%02x", + addr.val[5], addr.val[4], addr.val[3], addr.val[2], addr.val[1], addr.val[0]); /* Configure extended advertising parameters */ struct ble_gap_ext_adv_params ext_adv_params = { @@ -54,9 +56,16 @@ static void start_periodic_adv_cte(uint8_t own_addr_type) assert(rc == 0); /* Configure advertising data */ +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + strncpy(adv_device_name, esp_ble_cte_get_example_name(), sizeof(adv_device_name) - 1); + adv_device_name[sizeof(adv_device_name) - 1] = '\0'; + ESP_LOGI(TAG, "DeviceName:%s, CIID:%02X, PipelineID:%05X, ChipID:%02X", + adv_device_name, CONFIG_EXAMPLE_CI_ID, CONFIG_EXAMPLE_CI_PIPELINE_ID, CONFIG_IDF_FIRMWARE_CHIP_ID); +#endif + struct ble_hs_adv_fields adv_fields = {0}; - adv_fields.name = (const uint8_t *)"CTE_Periodic_Adv"; - adv_fields.name_len = strlen("CTE_Periodic_Adv"); + adv_fields.name = (const uint8_t *)adv_device_name; + adv_fields.name_len = strlen(adv_device_name); struct os_mbuf *data = os_msys_get_pkthdr(BLE_HS_ADV_MAX_FIELD_SZ, 0); assert(data); diff --git a/examples/bluetooth/nimble/ble_cte/ble_periodic_adv_with_cte/sdkconfig.ci.name b/examples/bluetooth/nimble/ble_cte/ble_periodic_adv_with_cte/sdkconfig.ci.name new file mode 100644 index 00000000000..a372d836917 --- /dev/null +++ b/examples/bluetooth/nimble/ble_cte/ble_periodic_adv_with_cte/sdkconfig.ci.name @@ -0,0 +1,2 @@ +CONFIG_EXAMPLE_CI_ID=25 +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} diff --git a/examples/bluetooth/nimble/ble_cte/ble_periodic_sync_with_cte/main/Kconfig.projbuild b/examples/bluetooth/nimble/ble_cte/ble_periodic_sync_with_cte/main/Kconfig.projbuild index bb9e6f38afe..81ca450292a 100644 --- a/examples/bluetooth/nimble/ble_cte/ble_periodic_sync_with_cte/main/Kconfig.projbuild +++ b/examples/bluetooth/nimble/ble_cte/ble_periodic_sync_with_cte/main/Kconfig.projbuild @@ -67,4 +67,16 @@ menu "Example Configuration" help GPIO pin number for the most significant bit (MSB) of antenna encoding. + config EXAMPLE_CI_ID + int "example id for CI test" + default 0 + help + This config the example id for CI test. Only for internal used. + + config EXAMPLE_CI_PIPELINE_ID + int "The pipeline id for CI test" + default 0 + help + This config the pipeline id for CI test. Only for internal used. + endmenu diff --git a/examples/bluetooth/nimble/ble_cte/ble_periodic_sync_with_cte/main/main.c b/examples/bluetooth/nimble/ble_cte/ble_periodic_sync_with_cte/main/main.c index 7a9f008d91b..e6b9eeb633b 100644 --- a/examples/bluetooth/nimble/ble_cte/ble_periodic_sync_with_cte/main/main.c +++ b/examples/bluetooth/nimble/ble_cte/ble_periodic_sync_with_cte/main/main.c @@ -7,6 +7,7 @@ #include "esp_log.h" #include "nvs_flash.h" #include "esp_check.h" +#include #include "nimble/nimble_port.h" #include "nimble/nimble_port_freertos.h" @@ -17,6 +18,7 @@ static const char *TAG = "CTE_SYNC_EXAMPLE"; static int is_synced = 0; +static char sync_target_name[32] = "CTE_Periodic_Adv"; static int periodic_sync_gap_event(struct ble_gap_event *event, void *arg); @@ -173,7 +175,7 @@ static int periodic_sync_gap_event(struct ble_gap_event *event, void *arg) memcpy(dev_name, &adv_data[index + 2], name_len); dev_name[name_len] = '\0'; - if (strcmp(dev_name, CONFIG_EXAMPLE_SYNC_TARGET_DEVNAME) == 0) { + if (strcmp(dev_name, sync_target_name) == 0) { should_sync = true; break; } @@ -255,10 +257,27 @@ static void periodic_sync_on_reset(int reason) static void periodic_sync_on_sync(void) { int rc; + uint8_t own_addr_type; + ble_addr_t addr; + /* Make sure we have proper identity address set (public preferred) */ rc = ble_hs_util_ensure_addr(0); assert(rc == 0); + rc = ble_hs_id_infer_auto(0, &own_addr_type); + assert(rc == 0); + + rc = ble_hs_id_copy_addr(own_addr_type, addr.val, NULL); + assert(rc == 0); + + ESP_LOGI(TAG, "Bluetooth MAC: %02x:%02x:%02x:%02x:%02x:%02x", + addr.val[5], addr.val[4], addr.val[3], addr.val[2], addr.val[1], addr.val[0]); + +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + ESP_LOGI(TAG, "DeviceName:%s, CIID:%02X, PipelineID:%05X, ChipID:%02X", + sync_target_name, CONFIG_EXAMPLE_CI_ID, CONFIG_EXAMPLE_CI_PIPELINE_ID, CONFIG_IDF_FIRMWARE_CHIP_ID); +#endif + /* Begin scanning for a periodic advertiser to sync with. */ periodic_sync_scan(); } @@ -300,6 +319,14 @@ void app_main(void) assert(rc == 0); #endif +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + strncpy(sync_target_name, esp_ble_cte_get_example_name(), sizeof(sync_target_name) - 1); + sync_target_name[sizeof(sync_target_name) - 1] = '\0'; +#elif CONFIG_EXAMPLE_SYNC_BY_NAME + strncpy(sync_target_name, CONFIG_EXAMPLE_SYNC_TARGET_DEVNAME, sizeof(sync_target_name) - 1); + sync_target_name[sizeof(sync_target_name) - 1] = '\0'; +#endif + #if MYNEWT_VAL(BLE_AOA_AOD) ESP_LOGI(TAG, "\n%s", direction_finding_logo); diff --git a/examples/bluetooth/nimble/ble_cte/ble_periodic_sync_with_cte/sdkconfig.ci.name b/examples/bluetooth/nimble/ble_cte/ble_periodic_sync_with_cte/sdkconfig.ci.name new file mode 100644 index 00000000000..421897bb7df --- /dev/null +++ b/examples/bluetooth/nimble/ble_cte/ble_periodic_sync_with_cte/sdkconfig.ci.name @@ -0,0 +1,3 @@ +CONFIG_EXAMPLE_CI_ID=25 +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} +CONFIG_EXAMPLE_SYNC_BY_NAME=y diff --git a/examples/bluetooth/nimble/ble_cte/common_components/cte_config/cte_config.c b/examples/bluetooth/nimble/ble_cte/common_components/cte_config/cte_config.c index 8aed7f5a751..9cf7773df1d 100644 --- a/examples/bluetooth/nimble/ble_cte/common_components/cte_config/cte_config.c +++ b/examples/bluetooth/nimble/ble_cte/common_components/cte_config/cte_config.c @@ -1,10 +1,11 @@ /* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: CC0-1.0 */ #include +#include #include "sdkconfig.h" #include "cte_config.h" #include "esp_log.h" @@ -78,6 +79,20 @@ uint8_t antenna_use_gpio[CONFIG_EXAMPLE_ANT_GPIO_BIT_COUNT] = { uint8_t antenna_signal_index[4] = {CTE_ANT0_IDX, CTE_ANT1_IDX, CTE_ANT2_IDX, CTE_ANT3_IDX}; +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID +char *esp_ble_cte_get_example_name(void) +{ + static char example_name[32]; + + memset(example_name, 0, sizeof(example_name)); + snprintf(example_name, sizeof(example_name), "BE%02X_%05X_%02X", + CONFIG_EXAMPLE_CI_ID & 0xFF, + CONFIG_EXAMPLE_CI_PIPELINE_ID & 0xFFFFF, + CONFIG_IDF_FIRMWARE_CHIP_ID & 0xFF); + return example_name; +} +#endif + int ble_direction_finding_antenna_init(uint8_t* gpio_array,uint8_t gpio_array_len){ int rc; // GPIO configuration diff --git a/examples/bluetooth/nimble/ble_cte/common_components/cte_config/cte_config.h b/examples/bluetooth/nimble/ble_cte/common_components/cte_config/cte_config.h index 754bfd11e72..3a655acad25 100644 --- a/examples/bluetooth/nimble/ble_cte/common_components/cte_config/cte_config.h +++ b/examples/bluetooth/nimble/ble_cte/common_components/cte_config/cte_config.h @@ -16,3 +16,7 @@ extern uint8_t antenna_use_gpio[]; extern const char direction_finding_logo[]; int ble_direction_finding_antenna_init(uint8_t* gpio_array,uint8_t gpio_array_len); + +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID +char *esp_ble_cte_get_example_name(void); +#endif diff --git a/examples/bluetooth/nimble/ble_cts/cts_cent/main/Kconfig.projbuild b/examples/bluetooth/nimble/ble_cts/cts_cent/main/Kconfig.projbuild index 12750f2701d..6bebd916996 100644 --- a/examples/bluetooth/nimble/ble_cts/cts_cent/main/Kconfig.projbuild +++ b/examples/bluetooth/nimble/ble_cts/cts_cent/main/Kconfig.projbuild @@ -24,4 +24,16 @@ menu "Example Configuration" If this option is disabled, ensure config BT_NIMBLE_EXT_ADV is also disabled from Nimble stack menuconfig + config EXAMPLE_CI_ID + int "example id for CI test" + default 0 + help + This config the example id for CI test. Only for internal used. + + config EXAMPLE_CI_PIPELINE_ID + int "The pipeline id for CI test" + default 0 + help + This config the pipeline id for CI test. Only for internal used. + endmenu diff --git a/examples/bluetooth/nimble/ble_cts/cts_cent/main/main.c b/examples/bluetooth/nimble/ble_cts/cts_cent/main/main.c index f2856d6f47d..c10e660b092 100644 --- a/examples/bluetooth/nimble/ble_cts/cts_cent/main/main.c +++ b/examples/bluetooth/nimble/ble_cts/cts_cent/main/main.c @@ -4,6 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include +#include #include "esp_log.h" #include "nvs_flash.h" /* BLE */ @@ -20,8 +22,23 @@ #endif static const char *tag = "NimBLE_CTS_CENT"; +static char remote_device_name[32]; static int ble_cts_cent_gap_event(struct ble_gap_event *event, void *arg); +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID +static char *esp_ble_cts_get_example_name(void) +{ + static char example_name[32]; + + memset(example_name, 0, sizeof(example_name)); + snprintf(example_name, sizeof(example_name), "BE%02X_%05X_%02X", + CONFIG_EXAMPLE_CI_ID & 0xFF, + CONFIG_EXAMPLE_CI_PIPELINE_ID & 0xFFFFF, + CONFIG_IDF_FIRMWARE_CHIP_ID & 0xFF); + return example_name; +} +#endif + static char *day_of_week[8] = { "Unknown", "Monday", @@ -186,6 +203,12 @@ ble_cts_cent_scan(void) disc_params.filter_policy = 0; disc_params.limited = 0; +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + /* Full scan improves discovery reliability in multi-board CI environments. */ + disc_params.itvl = BLE_GAP_SCAN_ITVL_MS(50); + disc_params.window = BLE_GAP_SCAN_ITVL_MS(50); +#endif + rc = ble_gap_disc(own_addr_type, BLE_HS_FOREVER, &disc_params, ble_cts_cent_gap_event, NULL); if (rc != 0) { @@ -222,6 +245,24 @@ ext_ble_cts_cent_should_connect(const struct ble_gap_ext_disc_desc *disc) } } +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + while (offset < disc->length_data) { + ad_struct_len = disc->data[offset]; + if (ad_struct_len == 0 || offset + ad_struct_len + 1 > disc->length_data) { + break; + } + if (disc->data[offset + 1] == BLE_HS_ADV_TYPE_COMP_NAME || + disc->data[offset + 1] == BLE_HS_ADV_TYPE_INCOMP_NAME) { + int name_len = ad_struct_len - 1; + if (name_len == (int)strlen(remote_device_name) && + memcmp(&disc->data[offset + 2], remote_device_name, name_len) == 0) { + return 1; + } + } + offset += ad_struct_len + 1; + } + return 0; +#else /* The device has to advertise support for the CTS * service (0x1805). */ @@ -254,6 +295,7 @@ ext_ble_cts_cent_should_connect(const struct ble_gap_ext_disc_desc *disc) } return 0; +#endif } #else @@ -262,7 +304,6 @@ ble_cts_cent_should_connect(const struct ble_gap_disc_desc *disc) { struct ble_hs_adv_fields fields; int rc; - int i; uint8_t test_addr[6] = {0}; /* The device has to be advertising connectability. */ if (disc->event_type != BLE_HCI_ADV_RPT_EVTYPE_ADV_IND && @@ -287,16 +328,25 @@ ble_cts_cent_should_connect(const struct ble_gap_disc_desc *disc) } } +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + if (fields.name != NULL && + fields.name_len == strlen(remote_device_name) && + memcmp(fields.name, remote_device_name, fields.name_len) == 0) { + return 1; + } + return 0; +#else /* The device has to advertise support for the Current Time * service (0x1805). */ - for (i = 0; i < fields.num_uuids16; i++) { + for (int i = 0; i < fields.num_uuids16; i++) { if (ble_uuid_u16(&fields.uuids16[i].u) == BLE_SVC_CTS_UUID16) { return 1; } } return 0; +#endif } #endif @@ -323,6 +373,16 @@ ble_cts_cent_connect_if_interesting(void *disc) } #endif +#if CONFIG_EXAMPLE_EXTENDED_ADV + addr = &((struct ble_gap_ext_disc_desc *)disc)->addr; +#else + addr = &((struct ble_gap_disc_desc *)disc)->addr; +#endif + +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + ESP_LOGI(tag, "Found device: %s, name: %s", addr_str(addr->val), remote_device_name); +#endif + #if !(MYNEWT_VAL(BLE_HOST_ALLOW_CONNECT_WITH_SCAN)) /* Scanning must be stopped before a connection can be initiated. */ rc = ble_gap_disc_cancel(); @@ -345,11 +405,6 @@ ble_cts_cent_connect_if_interesting(void *disc) /* Try to connect the the advertiser. Allow 30 seconds (30000 ms) for * timeout. */ -#if CONFIG_EXAMPLE_EXTENDED_ADV - addr = &((struct ble_gap_ext_disc_desc *)disc)->addr; -#else - addr = &((struct ble_gap_disc_desc *)disc)->addr; -#endif rc = ble_gap_connect(own_addr_type, addr, 30000, NULL, ble_cts_cent_gap_event, NULL); if (rc != 0) { @@ -413,6 +468,8 @@ ble_cts_cent_gap_event(struct ble_gap_event *event, void *arg) assert(rc == 0); print_conn_desc(&desc); MODLOG_DFLT(INFO, "\n"); + ESP_LOGI(tag, "Connected, conn_handle %d, remote %s", + event->connect.conn_handle, addr_str(desc.peer_ota_addr.val)); /* Remember peer. */ rc = peer_add(event->connect.conn_handle); @@ -609,6 +666,13 @@ app_main(void) return; } +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + strncpy(remote_device_name, esp_ble_cts_get_example_name(), sizeof(remote_device_name) - 1); + remote_device_name[sizeof(remote_device_name) - 1] = '\0'; + ESP_LOGI(tag, "DeviceName:%s, CIID:%02X, PipelineID:%05X, ChipID:%02X", + remote_device_name, CONFIG_EXAMPLE_CI_ID, CONFIG_EXAMPLE_CI_PIPELINE_ID, CONFIG_IDF_FIRMWARE_CHIP_ID); +#endif + /* Configure the host. */ ble_hs_cfg.reset_cb = ble_cts_cent_on_reset; ble_hs_cfg.sync_cb = ble_cts_cent_on_sync; diff --git a/examples/bluetooth/nimble/ble_cts/cts_cent/sdkconfig.ci.esp32c2_xtal26m b/examples/bluetooth/nimble/ble_cts/cts_cent/sdkconfig.ci.esp32c2_xtal26m new file mode 100644 index 00000000000..8430fb6f9a3 --- /dev/null +++ b/examples/bluetooth/nimble/ble_cts/cts_cent/sdkconfig.ci.esp32c2_xtal26m @@ -0,0 +1,6 @@ +CONFIG_EXAMPLE_CI_ID=26 +CONFIG_IDF_TARGET="esp32c2" +CONFIG_XTAL_FREQ_26=y +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} +CONFIG_EXAMPLE_ENCRYPTION=n +CONFIG_EXAMPLE_EXTENDED_ADV=n diff --git a/examples/bluetooth/nimble/ble_cts/cts_cent/sdkconfig.ci.name b/examples/bluetooth/nimble/ble_cts/cts_cent/sdkconfig.ci.name new file mode 100644 index 00000000000..355f8f8302b --- /dev/null +++ b/examples/bluetooth/nimble/ble_cts/cts_cent/sdkconfig.ci.name @@ -0,0 +1,4 @@ +CONFIG_EXAMPLE_CI_ID=26 +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} +CONFIG_EXAMPLE_ENCRYPTION=n +CONFIG_EXAMPLE_EXTENDED_ADV=n diff --git a/examples/bluetooth/nimble/ble_cts/cts_prph/main/Kconfig.projbuild b/examples/bluetooth/nimble/ble_cts/cts_prph/main/Kconfig.projbuild index 8e5ab9f250a..4cf399a365c 100644 --- a/examples/bluetooth/nimble/ble_cts/cts_prph/main/Kconfig.projbuild +++ b/examples/bluetooth/nimble/ble_cts/cts_prph/main/Kconfig.projbuild @@ -11,4 +11,16 @@ menu "Example Configuration" If this option is disabled, ensure config BT_NIMBLE_EXT_ADV is also disabled from Nimble stack menuconfig + config EXAMPLE_CI_ID + int "example id for CI test" + default 0 + help + This config the example id for CI test. Only for internal used. + + config EXAMPLE_CI_PIPELINE_ID + int "The pipeline id for CI test" + default 0 + help + This config the pipeline id for CI test. Only for internal used. + endmenu diff --git a/examples/bluetooth/nimble/ble_cts/cts_prph/main/main.c b/examples/bluetooth/nimble/ble_cts/cts_prph/main/main.c index 2658a45df18..e84eb307833 100644 --- a/examples/bluetooth/nimble/ble_cts/cts_prph/main/main.c +++ b/examples/bluetooth/nimble/ble_cts/cts_prph/main/main.c @@ -4,6 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include +#include #include "esp_log.h" #include "nvs_flash.h" #include "freertos/FreeRTOSConfig.h" @@ -27,11 +29,25 @@ static uint8_t ext_adv_pattern_1[] = { #endif static const char *tag = "NimBLE_CTS_PRPH"; -static const char *device_name = "ble_cts_prph"; +static char device_name[32] = "ble_cts_prph"; static int ble_cts_prph_gap_event(struct ble_gap_event *event, void *arg); static uint8_t ble_cts_prph_addr_type; +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID +static char *esp_ble_cts_get_example_name(void) +{ + static char example_name[32]; + + memset(example_name, 0, sizeof(example_name)); + snprintf(example_name, sizeof(example_name), "BE%02X_%05X_%02X", + CONFIG_EXAMPLE_CI_ID & 0xFF, + CONFIG_EXAMPLE_CI_PIPELINE_ID & 0xFFFFF, + CONFIG_IDF_FIRMWARE_CHIP_ID & 0xFF); + return example_name; +} +#endif + /** * Utility function to log an array of bytes. */ @@ -67,6 +83,11 @@ ext_ble_cts_prph_advertise(void) struct os_mbuf *data; uint8_t instance = 0; int rc; +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + uint8_t ci_adv_data[32]; + uint8_t ci_adv_len; + uint8_t name_len; +#endif /* First check if any instance is already active */ if (ble_gap_ext_adv_active(instance)) { @@ -96,6 +117,20 @@ ext_ble_cts_prph_advertise(void) /* in this case only scan response is allowed */ +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + name_len = strlen(device_name); + memset(ci_adv_data, 0, sizeof(ci_adv_data)); + ci_adv_data[0] = name_len + 1; + ci_adv_data[1] = BLE_HS_ADV_TYPE_COMP_NAME; + memcpy(&ci_adv_data[2], device_name, name_len); + ci_adv_len = 2 + name_len; + + data = os_msys_get_pkthdr(ci_adv_len, 0); + assert(data); + + rc = os_mbuf_append(data, ci_adv_data, ci_adv_len); + assert(rc == 0); +#else /* get mbuf for scan rsp data */ data = os_msys_get_pkthdr(sizeof(ext_adv_pattern_1), 0); assert(data); @@ -103,6 +138,7 @@ ext_ble_cts_prph_advertise(void) /* fill mbuf with scan rsp data */ rc = os_mbuf_append(data, ext_adv_pattern_1, sizeof(ext_adv_pattern_1)); assert(rc == 0); +#endif rc = ble_gap_ext_adv_set_data(instance, data); assert (rc == 0); @@ -148,12 +184,14 @@ ble_cts_prph_advertise(void) fields.name_len = strlen(device_name); fields.name_is_complete = 1; +#if !(CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID) static const ble_uuid16_t adv_uuids16[] = { BLE_UUID16_INIT(BLE_SVC_CTS_UUID16) }; fields.uuids16 = adv_uuids16; fields.num_uuids16 = 1; fields.uuids16_is_complete = 1; +#endif rc = ble_gap_adv_set_fields(&fields); if (rc != 0) { @@ -177,6 +215,9 @@ ble_cts_prph_advertise(void) static int ble_cts_prph_gap_event(struct ble_gap_event *event, void *arg) { + struct ble_gap_conn_desc desc; + int rc; + switch (event->type) { case BLE_GAP_EVENT_CONNECT: /* A new connection was established or a connection attempt failed */ @@ -184,7 +225,16 @@ ble_cts_prph_gap_event(struct ble_gap_event *event, void *arg) event->connect.status == 0 ? "established" : "failed", event->connect.status); - if (event->connect.status != 0) { + if (event->connect.status == 0) { + rc = ble_gap_conn_find(event->connect.conn_handle, &desc); + if (rc == 0) { + ESP_LOGI(tag, "Connected, conn_handle %d, remote %02x:%02x:%02x:%02x:%02x:%02x", + event->connect.conn_handle, + desc.peer_ota_addr.val[5], desc.peer_ota_addr.val[4], + desc.peer_ota_addr.val[3], desc.peer_ota_addr.val[2], + desc.peer_ota_addr.val[1], desc.peer_ota_addr.val[0]); + } + } else { /* Connection failed; resume advertising */ #if CONFIG_EXAMPLE_EXTENDED_ADV ext_ble_cts_prph_advertise(); @@ -305,6 +355,13 @@ void app_main(void) rc = gatt_svr_init(); assert(rc == 0); +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + strncpy(device_name, esp_ble_cts_get_example_name(), sizeof(device_name) - 1); + device_name[sizeof(device_name) - 1] = '\0'; + ESP_LOGI(tag, "DeviceName:%s, CIID:%02X, PipelineID:%05X, ChipID:%02X", + device_name, CONFIG_EXAMPLE_CI_ID, CONFIG_EXAMPLE_CI_PIPELINE_ID, CONFIG_IDF_FIRMWARE_CHIP_ID); +#endif + #if CONFIG_BT_NIMBLE_GAP_SERVICE /* Set the default device name */ rc = ble_svc_gap_device_name_set(device_name); diff --git a/examples/bluetooth/nimble/ble_cts/cts_prph/sdkconfig.ci.esp32c2_xtal26m b/examples/bluetooth/nimble/ble_cts/cts_prph/sdkconfig.ci.esp32c2_xtal26m new file mode 100644 index 00000000000..665f112660d --- /dev/null +++ b/examples/bluetooth/nimble/ble_cts/cts_prph/sdkconfig.ci.esp32c2_xtal26m @@ -0,0 +1,5 @@ +CONFIG_EXAMPLE_CI_ID=26 +CONFIG_IDF_TARGET="esp32c2" +CONFIG_XTAL_FREQ_26=y +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} +CONFIG_EXAMPLE_EXTENDED_ADV=n diff --git a/examples/bluetooth/nimble/ble_cts/cts_prph/sdkconfig.ci.name b/examples/bluetooth/nimble/ble_cts/cts_prph/sdkconfig.ci.name new file mode 100644 index 00000000000..c506283f578 --- /dev/null +++ b/examples/bluetooth/nimble/ble_cts/cts_prph/sdkconfig.ci.name @@ -0,0 +1,3 @@ +CONFIG_EXAMPLE_CI_ID=26 +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} +CONFIG_EXAMPLE_EXTENDED_ADV=n diff --git a/examples/bluetooth/nimble/ble_htp/htp_cent/main/Kconfig.projbuild b/examples/bluetooth/nimble/ble_htp/htp_cent/main/Kconfig.projbuild index 12750f2701d..6bebd916996 100644 --- a/examples/bluetooth/nimble/ble_htp/htp_cent/main/Kconfig.projbuild +++ b/examples/bluetooth/nimble/ble_htp/htp_cent/main/Kconfig.projbuild @@ -24,4 +24,16 @@ menu "Example Configuration" If this option is disabled, ensure config BT_NIMBLE_EXT_ADV is also disabled from Nimble stack menuconfig + config EXAMPLE_CI_ID + int "example id for CI test" + default 0 + help + This config the example id for CI test. Only for internal used. + + config EXAMPLE_CI_PIPELINE_ID + int "The pipeline id for CI test" + default 0 + help + This config the pipeline id for CI test. Only for internal used. + endmenu diff --git a/examples/bluetooth/nimble/ble_htp/htp_cent/main/main.c b/examples/bluetooth/nimble/ble_htp/htp_cent/main/main.c index 472643e5df1..32701fb7bcb 100644 --- a/examples/bluetooth/nimble/ble_htp/htp_cent/main/main.c +++ b/examples/bluetooth/nimble/ble_htp/htp_cent/main/main.c @@ -4,6 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include +#include #include "esp_log.h" #include "nvs_flash.h" /* BLE */ @@ -19,11 +21,26 @@ #endif static const char *tag = "NimBLE_HTP_CENT"; +static char remote_device_name[32]; static int ble_htp_cent_gap_event(struct ble_gap_event *event, void *arg); void ble_store_config_init(void); static void ble_htp_cent_scan(void); +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID +static char *esp_ble_htp_get_example_name(void) +{ + static char example_name[32]; + + memset(example_name, 0, sizeof(example_name)); + snprintf(example_name, sizeof(example_name), "BE%02X_%05X_%02X", + CONFIG_EXAMPLE_CI_ID & 0xFF, + CONFIG_EXAMPLE_CI_PIPELINE_ID & 0xFFFFF, + CONFIG_IDF_FIRMWARE_CHIP_ID & 0xFF); + return example_name; +} +#endif + #if MYNEWT_VAL(BLE_GATTC) /** * Application callback. Called when the attempt to subscribe to notifications @@ -318,6 +335,12 @@ ble_htp_cent_scan(void) disc_params.filter_policy = 0; disc_params.limited = 0; +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + /* Full scan improves discovery reliability in multi-board CI environments. */ + disc_params.itvl = BLE_GAP_SCAN_ITVL_MS(50); + disc_params.window = BLE_GAP_SCAN_ITVL_MS(50); +#endif + rc = ble_gap_disc(own_addr_type, BLE_HS_FOREVER, &disc_params, ble_htp_cent_gap_event, NULL); if (rc != 0) { @@ -354,6 +377,24 @@ ext_ble_htp_cent_should_connect(const struct ble_gap_ext_disc_desc *disc) } } +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + while (offset < disc->length_data) { + ad_struct_len = disc->data[offset]; + if (ad_struct_len == 0 || offset + ad_struct_len + 1 > disc->length_data) { + break; + } + if (disc->data[offset + 1] == BLE_HS_ADV_TYPE_COMP_NAME || + disc->data[offset + 1] == BLE_HS_ADV_TYPE_INCOMP_NAME) { + int name_len = ad_struct_len - 1; + if (name_len == (int)strlen(remote_device_name) && + memcmp(&disc->data[offset + 2], remote_device_name, name_len) == 0) { + return 1; + } + } + offset += ad_struct_len + 1; + } + return 0; +#else /* The device has to advertise support for the Health thermometer * service (0x1809). */ @@ -376,6 +417,7 @@ ext_ble_htp_cent_should_connect(const struct ble_gap_ext_disc_desc *disc) } return 0; +#endif } #else @@ -384,7 +426,6 @@ ble_htp_cent_should_connect(const struct ble_gap_disc_desc *disc) { struct ble_hs_adv_fields fields; int rc; - int i; uint8_t test_addr[6] = {0}; /* The device has to be advertising connectability. */ if (disc->event_type != BLE_HCI_ADV_RPT_EVTYPE_ADV_IND && @@ -409,16 +450,25 @@ ble_htp_cent_should_connect(const struct ble_gap_disc_desc *disc) } } +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + if (fields.name != NULL && + fields.name_len == strlen(remote_device_name) && + memcmp(fields.name, remote_device_name, fields.name_len) == 0) { + return 1; + } + return 0; +#else /* The device has to advertise support for the Health Thermometer * service (0x1809). */ - for (i = 0; i < fields.num_uuids16; i++) { + for (int i = 0; i < fields.num_uuids16; i++) { if (ble_uuid_u16(&fields.uuids16[i].u) == BLE_SVC_HTP_UUID16) { return 1; } } return 0; +#endif } #endif @@ -445,6 +495,16 @@ ble_htp_cent_connect_if_interesting(void *disc) } #endif +#if CONFIG_EXAMPLE_EXTENDED_ADV + addr = &((struct ble_gap_ext_disc_desc *)disc)->addr; +#else + addr = &((struct ble_gap_disc_desc *)disc)->addr; +#endif + +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + ESP_LOGI(tag, "Found device: %s, name: %s", addr_str(addr->val), remote_device_name); +#endif + #if !(MYNEWT_VAL(BLE_HOST_ALLOW_CONNECT_WITH_SCAN)) /* Scanning must be stopped before a connection can be initiated. */ rc = ble_gap_disc_cancel(); @@ -467,11 +527,6 @@ ble_htp_cent_connect_if_interesting(void *disc) /* Try to connect the the advertiser. Allow 30 seconds (30000 ms) for * timeout. */ -#if CONFIG_EXAMPLE_EXTENDED_ADV - addr = &((struct ble_gap_ext_disc_desc *)disc)->addr; -#else - addr = &((struct ble_gap_disc_desc *)disc)->addr; -#endif rc = ble_gap_connect(own_addr_type, addr, 30000, NULL, ble_htp_cent_gap_event, NULL); if (rc != 0) { @@ -535,6 +590,8 @@ ble_htp_cent_gap_event(struct ble_gap_event *event, void *arg) assert(rc == 0); print_conn_desc(&desc); MODLOG_DFLT(INFO, "\n"); + ESP_LOGI(tag, "Connected, conn_handle %d, remote %s", + event->connect.conn_handle, addr_str(desc.peer_ota_addr.val)); /* Remember peer. */ rc = peer_add(event->connect.conn_handle); @@ -747,6 +804,13 @@ app_main(void) return; } +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + strncpy(remote_device_name, esp_ble_htp_get_example_name(), sizeof(remote_device_name) - 1); + remote_device_name[sizeof(remote_device_name) - 1] = '\0'; + ESP_LOGI(tag, "DeviceName:%s, CIID:%02X, PipelineID:%05X, ChipID:%02X", + remote_device_name, CONFIG_EXAMPLE_CI_ID, CONFIG_EXAMPLE_CI_PIPELINE_ID, CONFIG_IDF_FIRMWARE_CHIP_ID); +#endif + /* Configure the host. */ ble_hs_cfg.reset_cb = ble_htp_cent_on_reset; ble_hs_cfg.sync_cb = ble_htp_cent_on_sync; diff --git a/examples/bluetooth/nimble/ble_htp/htp_cent/sdkconfig.ci.esp32c2_xtal26m b/examples/bluetooth/nimble/ble_htp/htp_cent/sdkconfig.ci.esp32c2_xtal26m new file mode 100644 index 00000000000..efd4f446276 --- /dev/null +++ b/examples/bluetooth/nimble/ble_htp/htp_cent/sdkconfig.ci.esp32c2_xtal26m @@ -0,0 +1,6 @@ +CONFIG_EXAMPLE_CI_ID=27 +CONFIG_IDF_TARGET="esp32c2" +CONFIG_XTAL_FREQ_26=y +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} +CONFIG_EXAMPLE_EXTENDED_ADV=n +CONFIG_EXAMPLE_ENCRYPTION=n diff --git a/examples/bluetooth/nimble/ble_htp/htp_cent/sdkconfig.ci.name b/examples/bluetooth/nimble/ble_htp/htp_cent/sdkconfig.ci.name new file mode 100644 index 00000000000..034bd3f79eb --- /dev/null +++ b/examples/bluetooth/nimble/ble_htp/htp_cent/sdkconfig.ci.name @@ -0,0 +1,4 @@ +CONFIG_EXAMPLE_CI_ID=27 +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} +CONFIG_EXAMPLE_EXTENDED_ADV=n +CONFIG_EXAMPLE_ENCRYPTION=n diff --git a/examples/bluetooth/nimble/ble_htp/htp_prph/main/Kconfig.projbuild b/examples/bluetooth/nimble/ble_htp/htp_prph/main/Kconfig.projbuild index 3705112d5e2..4cf399a365c 100644 --- a/examples/bluetooth/nimble/ble_htp/htp_prph/main/Kconfig.projbuild +++ b/examples/bluetooth/nimble/ble_htp/htp_prph/main/Kconfig.projbuild @@ -10,4 +10,17 @@ menu "Example Configuration" Use this option to enable extended advertising in the example. If this option is disabled, ensure config BT_NIMBLE_EXT_ADV is also disabled from Nimble stack menuconfig + + config EXAMPLE_CI_ID + int "example id for CI test" + default 0 + help + This config the example id for CI test. Only for internal used. + + config EXAMPLE_CI_PIPELINE_ID + int "The pipeline id for CI test" + default 0 + help + This config the pipeline id for CI test. Only for internal used. + endmenu diff --git a/examples/bluetooth/nimble/ble_htp/htp_prph/main/main.c b/examples/bluetooth/nimble/ble_htp/htp_prph/main/main.c index 9849775cf20..ca24ce3835c 100644 --- a/examples/bluetooth/nimble/ble_htp/htp_prph/main/main.c +++ b/examples/bluetooth/nimble/ble_htp/htp_prph/main/main.c @@ -4,6 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include +#include #include "esp_log.h" #include "nvs_flash.h" #include "freertos/FreeRTOSConfig.h" @@ -28,12 +30,26 @@ static uint8_t ext_adv_pattern_1[] = { static const char *tag = "NimBLE_HTP_PRPH"; static TimerHandle_t ble_htp_prph_tx_timer; static uint16_t conn_handle; -static const char *device_name = "ble_htp_prph"; +static char device_name[32] = "ble_htp_prph"; static int ble_htp_prph_gap_event(struct ble_gap_event *event, void *arg); static uint8_t ble_htp_prph_addr_type; +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID +static char *esp_ble_htp_get_example_name(void) +{ + static char example_name[32]; + + memset(example_name, 0, sizeof(example_name)); + snprintf(example_name, sizeof(example_name), "BE%02X_%05X_%02X", + CONFIG_EXAMPLE_CI_ID & 0xFF, + CONFIG_EXAMPLE_CI_PIPELINE_ID & 0xFFFFF, + CONFIG_IDF_FIRMWARE_CHIP_ID & 0xFF); + return example_name; +} +#endif + /** * Utility function to log an array of bytes. */ @@ -69,6 +85,11 @@ ext_ble_htp_prph_advertise(void) struct os_mbuf *data; uint8_t instance = 0; int rc; +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + uint8_t ci_adv_data[32]; + uint8_t ci_adv_len; + uint8_t name_len; +#endif /* First check if any instance is already active */ if (ble_gap_ext_adv_active(instance)) { @@ -98,6 +119,20 @@ ext_ble_htp_prph_advertise(void) /* in this case only scan response is allowed */ +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + name_len = strlen(device_name); + memset(ci_adv_data, 0, sizeof(ci_adv_data)); + ci_adv_data[0] = name_len + 1; + ci_adv_data[1] = BLE_HS_ADV_TYPE_COMP_NAME; + memcpy(&ci_adv_data[2], device_name, name_len); + ci_adv_len = 2 + name_len; + + data = os_msys_get_pkthdr(ci_adv_len, 0); + assert(data); + + rc = os_mbuf_append(data, ci_adv_data, ci_adv_len); + assert(rc == 0); +#else /* get mbuf for scan rsp data */ data = os_msys_get_pkthdr(sizeof(ext_adv_pattern_1), 0); assert(data); @@ -105,6 +140,7 @@ ext_ble_htp_prph_advertise(void) /* fill mbuf with scan rsp data */ rc = os_mbuf_append(data, ext_adv_pattern_1, sizeof(ext_adv_pattern_1)); assert(rc == 0); +#endif rc = ble_gap_ext_adv_set_data(instance, data); assert (rc == 0); @@ -150,12 +186,14 @@ ble_htp_prph_advertise(void) fields.name_len = strlen(device_name); fields.name_is_complete = 1; +#if !(CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID) static const ble_uuid16_t adv_uuids16[] = { BLE_UUID16_INIT(BLE_SVC_HTP_UUID16) }; fields.uuids16 = adv_uuids16; fields.num_uuids16 = 1; fields.uuids16_is_complete = 1; +#endif rc = ble_gap_adv_set_fields(&fields); if (rc != 0) { @@ -226,6 +264,9 @@ ble_htp_prph_tx(TimerHandle_t ev) static int ble_htp_prph_gap_event(struct ble_gap_event *event, void *arg) { + struct ble_gap_conn_desc desc; + int rc; + switch (event->type) { case BLE_GAP_EVENT_CONNECT: /* A new connection was established or a connection attempt failed */ @@ -233,7 +274,16 @@ ble_htp_prph_gap_event(struct ble_gap_event *event, void *arg) event->connect.status == 0 ? "established" : "failed", event->connect.status); - if (event->connect.status != 0) { + if (event->connect.status == 0) { + rc = ble_gap_conn_find(event->connect.conn_handle, &desc); + if (rc == 0) { + ESP_LOGI(tag, "Connected, conn_handle %d, remote %02x:%02x:%02x:%02x:%02x:%02x", + event->connect.conn_handle, + desc.peer_ota_addr.val[5], desc.peer_ota_addr.val[4], + desc.peer_ota_addr.val[3], desc.peer_ota_addr.val[2], + desc.peer_ota_addr.val[1], desc.peer_ota_addr.val[0]); + } + } else { /* Connection failed; resume advertising */ #if CONFIG_EXAMPLE_EXTENDED_ADV ext_ble_htp_prph_advertise(); @@ -377,6 +427,13 @@ void app_main(void) rc = gatt_svr_init(); assert(rc == 0); +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + strncpy(device_name, esp_ble_htp_get_example_name(), sizeof(device_name) - 1); + device_name[sizeof(device_name) - 1] = '\0'; + ESP_LOGI(tag, "DeviceName:%s, CIID:%02X, PipelineID:%05X, ChipID:%02X", + device_name, CONFIG_EXAMPLE_CI_ID, CONFIG_EXAMPLE_CI_PIPELINE_ID, CONFIG_IDF_FIRMWARE_CHIP_ID); +#endif + #if CONFIG_BT_NIMBLE_GAP_SERVICE /* Set the default device name */ rc = ble_svc_gap_device_name_set(device_name); diff --git a/examples/bluetooth/nimble/ble_htp/htp_prph/sdkconfig.ci.esp32c2_xtal26m b/examples/bluetooth/nimble/ble_htp/htp_prph/sdkconfig.ci.esp32c2_xtal26m new file mode 100644 index 00000000000..b36815970a9 --- /dev/null +++ b/examples/bluetooth/nimble/ble_htp/htp_prph/sdkconfig.ci.esp32c2_xtal26m @@ -0,0 +1,5 @@ +CONFIG_EXAMPLE_CI_ID=27 +CONFIG_IDF_TARGET="esp32c2" +CONFIG_XTAL_FREQ_26=y +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} +CONFIG_EXAMPLE_EXTENDED_ADV=n diff --git a/examples/bluetooth/nimble/ble_htp/htp_prph/sdkconfig.ci.name b/examples/bluetooth/nimble/ble_htp/htp_prph/sdkconfig.ci.name new file mode 100644 index 00000000000..69cf53eb525 --- /dev/null +++ b/examples/bluetooth/nimble/ble_htp/htp_prph/sdkconfig.ci.name @@ -0,0 +1,3 @@ +CONFIG_EXAMPLE_CI_ID=27 +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} +CONFIG_EXAMPLE_EXTENDED_ADV=n diff --git a/examples/bluetooth/nimble/ble_l2cap_coc/coc_blecent/main/Kconfig.projbuild b/examples/bluetooth/nimble/ble_l2cap_coc/coc_blecent/main/Kconfig.projbuild index b259360eb0e..b58c19aaf0f 100644 --- a/examples/bluetooth/nimble/ble_l2cap_coc/coc_blecent/main/Kconfig.projbuild +++ b/examples/bluetooth/nimble/ble_l2cap_coc/coc_blecent/main/Kconfig.projbuild @@ -16,4 +16,16 @@ menu "Example Configuration" Use this option to enable extended advertising in the example. If this option is disabled, ensure config BT_NIMBLE_EXT_ADV is also disabled from Nimble stack menuconfig + + config EXAMPLE_CI_ID + int "example id for CI test" + default 0 + help + This config the example id for CI test. Only for internal used. + + config EXAMPLE_CI_PIPELINE_ID + int "The pipeline id for CI test" + default 0 + help + This config the pipeline id for CI test. Only for internal used. endmenu diff --git a/examples/bluetooth/nimble/ble_l2cap_coc/coc_blecent/main/main.c b/examples/bluetooth/nimble/ble_l2cap_coc/coc_blecent/main/main.c index d333a0da919..45d45cdcbb1 100644 --- a/examples/bluetooth/nimble/ble_l2cap_coc/coc_blecent/main/main.c +++ b/examples/bluetooth/nimble/ble_l2cap_coc/coc_blecent/main/main.c @@ -6,6 +6,8 @@ #include "esp_log.h" #include "nvs_flash.h" +#include +#include /* BLE */ #include "nimble/nimble_port.h" #include "nimble/nimble_port_freertos.h" @@ -16,10 +18,25 @@ #include "coc_blecent.h" static const char *tag = "NimBLE_BLE_CENT_L2CAP_COC"; +static char remote_device_name[32]; static int blecent_gap_event(struct ble_gap_event *event, void *arg); void ble_store_config_init(void); +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID +static char *esp_ble_l2cap_coc_get_example_name(void) +{ + static char example_name[32]; + + memset(example_name, 0, sizeof(example_name)); + snprintf(example_name, sizeof(example_name), "BE%02X_%05X_%02X", + CONFIG_EXAMPLE_CI_ID & 0xFF, + CONFIG_EXAMPLE_CI_PIPELINE_ID & 0xFFFFF, + CONFIG_IDF_FIRMWARE_CHIP_ID & 0xFF); + return example_name; +} +#endif + #if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) >= 1 #define COC_BUF_COUNT (3 * MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM)) @@ -240,6 +257,12 @@ blecent_scan(void) disc_params.filter_policy = 0; disc_params.limited = 0; +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + /* Full scan improves discovery reliability in multi-board CI environments. */ + disc_params.itvl = BLE_GAP_SCAN_ITVL_MS(50); + disc_params.window = BLE_GAP_SCAN_ITVL_MS(50); +#endif + rc = ble_gap_disc(own_addr_type, BLE_HS_FOREVER, &disc_params, blecent_gap_event, NULL); if (rc != 0) { @@ -272,6 +295,24 @@ ext_blecent_should_connect(const struct ble_gap_ext_disc_desc *disc) return 0; } } +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + while (offset < disc->length_data) { + ad_struct_len = disc->data[offset]; + if (ad_struct_len == 0 || offset + ad_struct_len + 1 > disc->length_data) { + break; + } + if (disc->data[offset + 1] == BLE_HS_ADV_TYPE_COMP_NAME || + disc->data[offset + 1] == BLE_HS_ADV_TYPE_INCOMP_NAME) { + int name_len = ad_struct_len - 1; + if (name_len == (int)strlen(remote_device_name) && + memcmp(&disc->data[offset + 2], remote_device_name, name_len) == 0) { + return 1; + } + } + offset += ad_struct_len + 1; + } + return 0; +#else /* The device has to advertise support for L2CAP COC UUID (0x1812). */ do { @@ -301,6 +342,7 @@ ext_blecent_should_connect(const struct ble_gap_ext_disc_desc *disc) } while (offset < disc->length_data); return 0; +#endif } #else static int @@ -308,7 +350,6 @@ blecent_should_connect(const struct ble_gap_disc_desc *disc) { struct ble_hs_adv_fields fields; int rc; - int i; uint8_t test_addr[6]; /* The device has to be advertising connectability. */ if (disc->event_type != BLE_HCI_ADV_RPT_EVTYPE_ADV_IND && @@ -332,14 +373,23 @@ blecent_should_connect(const struct ble_gap_disc_desc *disc) } } +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + if (fields.name != NULL && + fields.name_len == strlen(remote_device_name) && + memcmp(fields.name, remote_device_name, fields.name_len) == 0) { + return 1; + } + return 0; +#else /* The device has to advertise support for L2CAP COC UUID (0x1812). */ - for (i = 0; i < fields.num_uuids16; i++) { + for (int i = 0; i < fields.num_uuids16; i++) { if (ble_uuid_u16(&fields.uuids16[i].u) == 0x1812) { return 1; } } return 0; +#endif } #endif @@ -366,6 +416,16 @@ blecent_connect_if_interesting(void *disc) } #endif +#if CONFIG_EXAMPLE_EXTENDED_ADV + addr = &((struct ble_gap_ext_disc_desc *)disc)->addr; +#else + addr = &((struct ble_gap_disc_desc *)disc)->addr; +#endif + +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + ESP_LOGI(tag, "Found device: %s, name: %s", addr_str(addr->val), remote_device_name); +#endif + #if !(MYNEWT_VAL(BLE_HOST_ALLOW_CONNECT_WITH_SCAN)) /* Scanning must be stopped before a connection can be initiated. */ rc = ble_gap_disc_cancel(); @@ -388,12 +448,6 @@ blecent_connect_if_interesting(void *disc) /* Try to connect the the advertiser. Allow 30 seconds (30000 ms) for * timeout. */ -#if CONFIG_EXAMPLE_EXTENDED_ADV - addr = &((struct ble_gap_ext_disc_desc *)disc)->addr; -#else - addr = &((struct ble_gap_disc_desc *)disc)->addr; -#endif - rc = ble_gap_connect(own_addr_type, addr, 30000, NULL, blecent_gap_event, NULL); if (rc != 0) { @@ -454,6 +508,8 @@ blecent_gap_event(struct ble_gap_event *event, void *arg) assert(rc == 0); print_conn_desc(&desc); MODLOG_DFLT(INFO, "\n"); + ESP_LOGI(tag, "Connected, conn_handle %d, remote %s", + event->connect.conn_handle, addr_str(desc.peer_ota_addr.val)); #if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) >= 1 conn_handle_coc = event->connect.conn_handle; @@ -599,6 +655,15 @@ app_main(void) rc = peer_init(MYNEWT_VAL(BLE_MAX_CONNECTIONS), 64, 64, 64); assert(rc == 0); #endif + +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + strncpy(remote_device_name, esp_ble_l2cap_coc_get_example_name(), sizeof(remote_device_name) - 1); + remote_device_name[sizeof(remote_device_name) - 1] = '\0'; + ESP_LOGI(tag, "DeviceName:%s, CIID:%02X, PipelineID:%05X, ChipID:%02X", + remote_device_name, CONFIG_EXAMPLE_CI_ID, CONFIG_EXAMPLE_CI_PIPELINE_ID, + CONFIG_IDF_FIRMWARE_CHIP_ID); +#endif + #if CONFIG_BT_NIMBLE_GAP_SERVICE /* Set the default device name. */ rc = ble_svc_gap_device_name_set("blecent-l2coc"); diff --git a/examples/bluetooth/nimble/ble_l2cap_coc/coc_blecent/sdkconfig.ci.esp32c2_xtal26m b/examples/bluetooth/nimble/ble_l2cap_coc/coc_blecent/sdkconfig.ci.esp32c2_xtal26m new file mode 100644 index 00000000000..b953c3f32cc --- /dev/null +++ b/examples/bluetooth/nimble/ble_l2cap_coc/coc_blecent/sdkconfig.ci.esp32c2_xtal26m @@ -0,0 +1,4 @@ +CONFIG_EXAMPLE_CI_ID=41 +CONFIG_IDF_TARGET="esp32c2" +CONFIG_XTAL_FREQ_26=y +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} diff --git a/examples/bluetooth/nimble/ble_l2cap_coc/coc_blecent/sdkconfig.ci.name b/examples/bluetooth/nimble/ble_l2cap_coc/coc_blecent/sdkconfig.ci.name new file mode 100644 index 00000000000..33f4c7d0de6 --- /dev/null +++ b/examples/bluetooth/nimble/ble_l2cap_coc/coc_blecent/sdkconfig.ci.name @@ -0,0 +1,2 @@ +CONFIG_EXAMPLE_CI_ID=41 +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} diff --git a/examples/bluetooth/nimble/ble_l2cap_coc/coc_bleprph/main/Kconfig.projbuild b/examples/bluetooth/nimble/ble_l2cap_coc/coc_bleprph/main/Kconfig.projbuild index 5d41352b16d..6c4e0e151a8 100644 --- a/examples/bluetooth/nimble/ble_l2cap_coc/coc_bleprph/main/Kconfig.projbuild +++ b/examples/bluetooth/nimble/ble_l2cap_coc/coc_bleprph/main/Kconfig.projbuild @@ -59,4 +59,16 @@ menu "Example Configuration" If this option is disabled, ensure config BT_NIMBLE_EXT_ADV is also disabled from Nimble stack menuconfig + config EXAMPLE_CI_ID + int "example id for CI test" + default 0 + help + This config the example id for CI test. Only for internal used. + + config EXAMPLE_CI_PIPELINE_ID + int "The pipeline id for CI test" + default 0 + help + This config the pipeline id for CI test. Only for internal used. + endmenu diff --git a/examples/bluetooth/nimble/ble_l2cap_coc/coc_bleprph/main/main.c b/examples/bluetooth/nimble/ble_l2cap_coc/coc_bleprph/main/main.c index d4f6a81f159..b9e95814e03 100644 --- a/examples/bluetooth/nimble/ble_l2cap_coc/coc_bleprph/main/main.c +++ b/examples/bluetooth/nimble/ble_l2cap_coc/coc_bleprph/main/main.c @@ -5,6 +5,9 @@ */ #include "nvs_flash.h" +#include "esp_log.h" +#include +#include /* BLE */ #include "nimble/nimble_port.h" #include "nimble/nimble_port_freertos.h" @@ -14,7 +17,7 @@ #include "services/gap/ble_svc_gap.h" #include "coc_bleprph.h" -#if CONFIG_EXAMPLE_EXTENDED_ADV +#if CONFIG_EXAMPLE_EXTENDED_ADV && !(CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID) static uint8_t ext_adv_pattern_1[] = { 0x02, BLE_HS_ADV_TYPE_FLAGS, 0x06, 0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0xab, 0xcd, @@ -24,11 +27,26 @@ static uint8_t ext_adv_pattern_1[] = { #endif static const char *tag = "NimBLE_BLE_PRPH_L2CAP_COC"; +static char device_name[32] = "bleprph-l2coc"; static int bleprph_gap_event(struct ble_gap_event *event, void *arg); static uint8_t own_addr_type; void ble_store_config_init(void); +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID +static char *esp_ble_l2cap_coc_get_example_name(void) +{ + static char example_name[32]; + + memset(example_name, 0, sizeof(example_name)); + snprintf(example_name, sizeof(example_name), "BE%02X_%05X_%02X", + CONFIG_EXAMPLE_CI_ID & 0xFF, + CONFIG_EXAMPLE_CI_PIPELINE_ID & 0xFFFFF, + CONFIG_IDF_FIRMWARE_CHIP_ID & 0xFF); + return example_name; +} +#endif + #if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) >= 1 #define COC_BUF_COUNT (20 * MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM)) @@ -81,6 +99,16 @@ ext_bleprph_advertise(void) struct os_mbuf *data; uint8_t instance = 0; int rc; +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + uint8_t ci_adv_data[32]; + uint8_t ci_adv_len; + uint8_t name_len; +#endif + + /* First check if any instance is already active */ + if (ble_gap_ext_adv_active(instance)) { + return; + } /* use defaults for non-set params */ memset (¶ms, 0, sizeof(params)); @@ -106,6 +134,20 @@ ext_bleprph_advertise(void) /* in this case only scan response is allowed */ +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + name_len = strlen(device_name); + memset(ci_adv_data, 0, sizeof(ci_adv_data)); + ci_adv_data[0] = name_len + 1; + ci_adv_data[1] = BLE_HS_ADV_TYPE_COMP_NAME; + memcpy(&ci_adv_data[2], device_name, name_len); + ci_adv_len = 2 + name_len; + + data = os_msys_get_pkthdr(ci_adv_len, 0); + assert(data); + + rc = os_mbuf_append(data, ci_adv_data, ci_adv_len); + assert(rc == 0); +#else /* get mbuf for scan rsp data */ data = os_msys_get_pkthdr(sizeof(ext_adv_pattern_1), 0); assert(data); @@ -113,6 +155,7 @@ ext_bleprph_advertise(void) /* fill mbuf with scan rsp data */ rc = os_mbuf_append(data, ext_adv_pattern_1, sizeof(ext_adv_pattern_1)); assert(rc == 0); +#endif rc = ble_gap_ext_adv_set_data(instance, data); assert (rc == 0); @@ -158,20 +201,18 @@ bleprph_advertise(void) fields.tx_pwr_lvl_is_present = 1; fields.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO; -#if CONFIG_BT_NIMBLE_GAP_SERVICE - const char *name; - name = ble_svc_gap_device_name(); - fields.name = (uint8_t *)name; - fields.name_len = strlen(name); + fields.name = (uint8_t *)device_name; + fields.name_len = strlen(device_name); fields.name_is_complete = 1; -#endif +#if !(CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID) static const ble_uuid16_t adv_uuids16[] = { BLE_UUID16_INIT(L2CAP_COC_UUID) }; fields.uuids16 = adv_uuids16; fields.num_uuids16 = 1; fields.uuids16_is_complete = 1; +#endif rc = ble_gap_adv_set_fields(&fields); if (rc != 0) { @@ -326,6 +367,11 @@ bleprph_gap_event(struct ble_gap_event *event, void *arg) rc = ble_gap_conn_find(event->connect.conn_handle, &desc); assert(rc == 0); bleprph_print_conn_desc(&desc); + ESP_LOGI(tag, "Connected, conn_handle %d, remote %02x:%02x:%02x:%02x:%02x:%02x", + event->connect.conn_handle, + desc.peer_ota_addr.val[5], desc.peer_ota_addr.val[4], + desc.peer_ota_addr.val[3], desc.peer_ota_addr.val[2], + desc.peer_ota_addr.val[1], desc.peer_ota_addr.val[0]); } MODLOG_DFLT(INFO, "\n"); @@ -477,9 +523,17 @@ app_main(void) bleprph_l2cap_coc_mem_init(); #endif +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + strncpy(device_name, esp_ble_l2cap_coc_get_example_name(), sizeof(device_name) - 1); + device_name[sizeof(device_name) - 1] = '\0'; + ESP_LOGI(tag, "DeviceName:%s, CIID:%02X, PipelineID:%05X, ChipID:%02X", + device_name, CONFIG_EXAMPLE_CI_ID, CONFIG_EXAMPLE_CI_PIPELINE_ID, + CONFIG_IDF_FIRMWARE_CHIP_ID); +#endif + #if CONFIG_BT_NIMBLE_GAP_SERVICE /* Set the default device name. */ - rc = ble_svc_gap_device_name_set("bleprph-l2coc"); + rc = ble_svc_gap_device_name_set(device_name); assert(rc == 0); #endif diff --git a/examples/bluetooth/nimble/ble_l2cap_coc/coc_bleprph/sdkconfig.ci.esp32c2_xtal26m b/examples/bluetooth/nimble/ble_l2cap_coc/coc_bleprph/sdkconfig.ci.esp32c2_xtal26m new file mode 100644 index 00000000000..b953c3f32cc --- /dev/null +++ b/examples/bluetooth/nimble/ble_l2cap_coc/coc_bleprph/sdkconfig.ci.esp32c2_xtal26m @@ -0,0 +1,4 @@ +CONFIG_EXAMPLE_CI_ID=41 +CONFIG_IDF_TARGET="esp32c2" +CONFIG_XTAL_FREQ_26=y +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} diff --git a/examples/bluetooth/nimble/ble_l2cap_coc/coc_bleprph/sdkconfig.ci.name b/examples/bluetooth/nimble/ble_l2cap_coc/coc_bleprph/sdkconfig.ci.name new file mode 100644 index 00000000000..33f4c7d0de6 --- /dev/null +++ b/examples/bluetooth/nimble/ble_l2cap_coc/coc_bleprph/sdkconfig.ci.name @@ -0,0 +1,2 @@ +CONFIG_EXAMPLE_CI_ID=41 +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} diff --git a/examples/bluetooth/nimble/ble_multi_adv/sdkconfig.ci.esp32c2_xtal26m b/examples/bluetooth/nimble/ble_multi_adv/sdkconfig.ci.esp32c2_xtal26m new file mode 100644 index 00000000000..172f022b67e --- /dev/null +++ b/examples/bluetooth/nimble/ble_multi_adv/sdkconfig.ci.esp32c2_xtal26m @@ -0,0 +1,2 @@ +CONFIG_IDF_TARGET="esp32c2" +CONFIG_XTAL_FREQ_26=y diff --git a/examples/bluetooth/nimble/ble_multi_adv/sdkconfig.ci.name b/examples/bluetooth/nimble/ble_multi_adv/sdkconfig.ci.name new file mode 100644 index 00000000000..3195ab2446d --- /dev/null +++ b/examples/bluetooth/nimble/ble_multi_adv/sdkconfig.ci.name @@ -0,0 +1 @@ +# Default CI configuration for the single-DUT smoke test. diff --git a/examples/bluetooth/nimble/ble_multi_conn/ble_multi_conn_cent/main/Kconfig.projbuild b/examples/bluetooth/nimble/ble_multi_conn/ble_multi_conn_cent/main/Kconfig.projbuild index 5d868c75d0c..ba6d6fe1b27 100644 --- a/examples/bluetooth/nimble/ble_multi_conn/ble_multi_conn_cent/main/Kconfig.projbuild +++ b/examples/bluetooth/nimble/ble_multi_conn/ble_multi_conn_cent/main/Kconfig.projbuild @@ -1,4 +1,15 @@ menu "Example Configuration" + config EXAMPLE_CI_ID + int "example id for CI test" + default 0 + help + This config the example id for CI test. Only for internal used. + + config EXAMPLE_CI_PIPELINE_ID + int "The pipeline id for CI test" + default 0 + help + This config the pipeline id for CI test. Only for internal used. endmenu diff --git a/examples/bluetooth/nimble/ble_multi_conn/ble_multi_conn_cent/main/main.c b/examples/bluetooth/nimble/ble_multi_conn/ble_multi_conn_cent/main/main.c index bfec7d71033..5b4875f43c2 100644 --- a/examples/bluetooth/nimble/ble_multi_conn/ble_multi_conn_cent/main/main.c +++ b/examples/bluetooth/nimble/ble_multi_conn/ble_multi_conn_cent/main/main.c @@ -20,12 +20,17 @@ "use a supported target from README.md (e.g. esp32h2, esp32c6) and run idf.py set-target." #endif -#define BLE_PEER_NAME "esp-multi-conn" +#define BLE_PEER_NAME_DEFAULT "esp-multi-conn" #define BLE_PEER_MAX_NUM (MYNEWT_VAL(BLE_MAX_CONNECTIONS) - 1) #define BLE_PREF_EVT_LEN_MS (5) #define BLE_PREF_CONN_ITVL_MS (BLE_PEER_MAX_NUM * BLE_PREF_EVT_LEN_MS) static const char *TAG = "ESP_MULTI_CONN_CENT"; +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID +static char remote_device_name[32]; +#else +static char remote_device_name[32] = BLE_PEER_NAME_DEFAULT; +#endif static const ble_uuid_t *remote_svc_uuid = BLE_UUID128_DECLARE(0x2d, 0x71, 0xa2, 0x59, 0xb4, 0x58, 0xc8, 0x12, @@ -44,6 +49,20 @@ static void ble_cent_connect(void *disc); static uint8_t own_addr_type; static uint8_t s_ble_multi_conn_num = 0; +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID +static char *esp_ble_multi_conn_get_example_name(void) +{ + static char example_name[32]; + + memset(example_name, 0, sizeof(example_name)); + snprintf(example_name, sizeof(example_name), "BE%02X_%05X_%02X", + CONFIG_EXAMPLE_CI_ID & 0xFF, + CONFIG_EXAMPLE_CI_PIPELINE_ID & 0xFFFFF, + CONFIG_IDF_FIRMWARE_CHIP_ID & 0xFF); + return example_name; +} +#endif + /** * Called when service discovery of the specified peer has completed. */ @@ -91,12 +110,26 @@ ble_cent_client_gap_event(struct ble_gap_event *event, void *arg) switch (event->type) { case BLE_GAP_EVENT_EXT_DISC: rc = ble_hs_adv_parse_fields(&fields, event->ext_disc.data, event->ext_disc.length_data); + if (rc != 0 || fields.name == NULL) { + return 0; + } - /* An advertisement report was received during GAP discovery. */ - if ((rc == 0) && fields.name && (fields.name_len >= strlen(BLE_PEER_NAME)) && - !strncmp((const char *)fields.name, BLE_PEER_NAME, strlen(BLE_PEER_NAME))) { +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + if (fields.name_len == strlen(remote_device_name) && + memcmp(fields.name, remote_device_name, fields.name_len) == 0) { + ESP_LOGI(TAG, "Found device: addr: %s, name: %s", + addr_str(event->ext_disc.addr.val), remote_device_name); ble_cent_connect(&event->ext_disc); } +#else + /* An advertisement report was received during GAP discovery. */ + if ((fields.name_len >= strlen(remote_device_name)) && + !strncmp((const char *)fields.name, remote_device_name, strlen(remote_device_name))) { + ESP_LOGI(TAG, "Found device: addr: %s, name: %.*s", + addr_str(event->ext_disc.addr.val), fields.name_len, fields.name); + ble_cent_connect(&event->ext_disc); + } +#endif return 0; @@ -312,7 +345,7 @@ ble_cent_scan(void) /** * Connects to the sender of the specified advertisement.The advertisement must contain its full - * name which we will compare with 'BLE_PEER_NAME'. + * name which we will compare with 'remote_device_name'. */ static void ble_cent_connect(void *disc) @@ -430,7 +463,7 @@ blecent_on_sync(void) } /* We will function as both the central and peripheral device, connecting to all peripherals - * with the name of BLE_PEER_NAME. Meanwhile, a connectable advertising will be enabled. + * with the name of remote_device_name. Meanwhile, a connectable advertising will be enabled. * In this example, we register two gap callback functions. * - ble_cent_client_gap_event: Used by the central. * - ble_cent_server_gap_event: Used by the peripheral. @@ -466,6 +499,13 @@ app_main(void) return; } +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + strncpy(remote_device_name, esp_ble_multi_conn_get_example_name(), sizeof(remote_device_name) - 1); + remote_device_name[sizeof(remote_device_name) - 1] = '\0'; + ESP_LOGI(TAG, "DeviceName:%s, CIID:%02X, PipelineID:%05X, ChipID:%02X", + remote_device_name, CONFIG_EXAMPLE_CI_ID, CONFIG_EXAMPLE_CI_PIPELINE_ID, CONFIG_IDF_FIRMWARE_CHIP_ID); +#endif + /* Configure the host. */ ble_hs_cfg.reset_cb = blecent_on_reset; ble_hs_cfg.sync_cb = blecent_on_sync; diff --git a/examples/bluetooth/nimble/ble_multi_conn/ble_multi_conn_cent/sdkconfig.ci.name b/examples/bluetooth/nimble/ble_multi_conn/ble_multi_conn_cent/sdkconfig.ci.name new file mode 100644 index 00000000000..d5e37ac9399 --- /dev/null +++ b/examples/bluetooth/nimble/ble_multi_conn/ble_multi_conn_cent/sdkconfig.ci.name @@ -0,0 +1,4 @@ +CONFIG_EXAMPLE_CI_ID=29 +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} +CONFIG_BT_NIMBLE_MAX_CONNECTIONS=5 +CONFIG_BT_NIMBLE_GATT_MAX_PROCS=5 diff --git a/examples/bluetooth/nimble/ble_multi_conn/ble_multi_conn_prph/main/Kconfig.projbuild b/examples/bluetooth/nimble/ble_multi_conn/ble_multi_conn_prph/main/Kconfig.projbuild index e57e163cccd..9f037f85963 100644 --- a/examples/bluetooth/nimble/ble_multi_conn/ble_multi_conn_prph/main/Kconfig.projbuild +++ b/examples/bluetooth/nimble/ble_multi_conn/ble_multi_conn_prph/main/Kconfig.projbuild @@ -17,4 +17,16 @@ menu "Example Configuration" To simulate multiple connections with only one device, restart the advertisement once a connection has been established. + config EXAMPLE_CI_ID + int "example id for CI test" + default 0 + help + This config the example id for CI test. Only for internal used. + + config EXAMPLE_CI_PIPELINE_ID + int "The pipeline id for CI test" + default 0 + help + This config the pipeline id for CI test. Only for internal used. + endmenu diff --git a/examples/bluetooth/nimble/ble_multi_conn/ble_multi_conn_prph/main/main.c b/examples/bluetooth/nimble/ble_multi_conn/ble_multi_conn_prph/main/main.c index 6d5b3ef6820..b7d34c96168 100644 --- a/examples/bluetooth/nimble/ble_multi_conn/ble_multi_conn_prph/main/main.c +++ b/examples/bluetooth/nimble/ble_multi_conn/ble_multi_conn_prph/main/main.c @@ -3,6 +3,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ +#include #include "esp_log.h" #include "nvs_flash.h" #include "esp_random.h" @@ -15,6 +16,7 @@ #include "ble_multi_conn_prph.h" #if CONFIG_EXAMPLE_EXTENDED_ADV +#if !(CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID) static uint8_t ext_adv_pattern_1[] = { 0x02, BLE_HS_ADV_TYPE_FLAGS, 0x06, 0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0xab, 0xcd, @@ -22,14 +24,30 @@ static uint8_t ext_adv_pattern_1[] = { 0x11, BLE_HS_ADV_TYPE_COMP_NAME, 'e', 's', 'p', '-', 'm', 'u', 'l', 't', 'i', '-', 'c', 'o', 'n', 'n', '-', 'e', }; #endif +#endif static const char *TAG = "ESP_MULTI_CONN_PRPH"; static volatile uint8_t s_ble_prph_conn_num = 0; static SemaphoreHandle_t s_sem_restart_adv = NULL; +static char device_name[32] = "esp-multi-conn"; static int ble_prph_gap_event(struct ble_gap_event *event, void *arg); void ble_store_config_init(void); +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID +static char *esp_ble_multi_conn_get_example_name(void) +{ + static char example_name[32]; + + memset(example_name, 0, sizeof(example_name)); + snprintf(example_name, sizeof(example_name), "BE%02X_%05X_%02X", + CONFIG_EXAMPLE_CI_ID & 0xFF, + CONFIG_EXAMPLE_CI_PIPELINE_ID & 0xFFFFF, + CONFIG_IDF_FIRMWARE_CHIP_ID & 0xFF); + return example_name; +} +#endif + /** * Enables advertising with the following parameters: * o General discoverable mode. @@ -49,6 +67,11 @@ ble_prph_advertise(void) struct ble_gap_ext_adv_params params; struct os_mbuf *data; uint8_t instance = 0; +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + uint8_t ci_adv_data[32]; + uint8_t ci_adv_len; + uint8_t name_len; +#endif /* First check if any instance is already active */ if(ble_gap_ext_adv_active(instance)) { @@ -73,10 +96,24 @@ ble_prph_advertise(void) ble_prph_gap_event, NULL); assert(rc == 0); +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + name_len = strlen(device_name); + memset(ci_adv_data, 0, sizeof(ci_adv_data)); + ci_adv_data[0] = name_len + 1; + ci_adv_data[1] = BLE_HS_ADV_TYPE_COMP_NAME; + memcpy(&ci_adv_data[2], device_name, name_len); + ci_adv_len = 2 + name_len; + + data = os_msys_get_pkthdr(ci_adv_len, 0); + assert(data); + rc = os_mbuf_append(data, ci_adv_data, ci_adv_len); + assert(rc == 0); +#else data = os_msys_get_pkthdr(sizeof(ext_adv_pattern_1), 0); assert(data); rc = os_mbuf_append(data, ext_adv_pattern_1, sizeof(ext_adv_pattern_1)); assert(rc == 0); +#endif rc = ble_gap_ext_adv_set_data(instance, data); assert(rc == 0); @@ -94,9 +131,6 @@ ble_prph_advertise(void) #else struct ble_gap_adv_params adv_params; struct ble_hs_adv_fields fields; -#if CONFIG_BT_NIMBLE_GAP_SERVICE - const char *name; -#endif if (ble_gap_adv_active()) { return; @@ -134,9 +168,8 @@ ble_prph_advertise(void) fields.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO; #if CONFIG_BT_NIMBLE_GAP_SERVICE - name = ble_svc_gap_device_name(); - fields.name = (uint8_t *)name; - fields.name_len = strlen(name); + fields.name = (uint8_t *)device_name; + fields.name_len = strlen(device_name); fields.name_is_complete = 1; #endif @@ -293,6 +326,15 @@ app_main(void) ESP_LOGE(TAG, "Failed to init nimble %d ", ret); return; } + +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + strncpy(device_name, esp_ble_multi_conn_get_example_name(), sizeof(device_name) - 1); + device_name[sizeof(device_name) - 1] = '\0'; + ESP_LOGI(TAG, "DeviceName:%s, CIID:%02X, PipelineID:%05X, ChipID:%02X", + device_name, CONFIG_EXAMPLE_CI_ID, CONFIG_EXAMPLE_CI_PIPELINE_ID, CONFIG_IDF_FIRMWARE_CHIP_ID); +#endif + ESP_LOGI(TAG, "CONFIG_BT_NIMBLE_MAX_CONNECTIONS=%d.", CONFIG_BT_NIMBLE_MAX_CONNECTIONS); + /* Initialize the NimBLE host configuration. */ ble_hs_cfg.reset_cb = bleprph_on_reset; ble_hs_cfg.sync_cb = bleprph_on_sync; @@ -306,7 +348,7 @@ app_main(void) #if CONFIG_BT_NIMBLE_GAP_SERVICE /* Set the default device name. */ - rc = ble_svc_gap_device_name_set("esp-multi-conn"); + rc = ble_svc_gap_device_name_set(device_name); assert(rc == 0); #endif diff --git a/examples/bluetooth/nimble/ble_multi_conn/ble_multi_conn_prph/sdkconfig.ci.name b/examples/bluetooth/nimble/ble_multi_conn/ble_multi_conn_prph/sdkconfig.ci.name new file mode 100644 index 00000000000..44c83dd903e --- /dev/null +++ b/examples/bluetooth/nimble/ble_multi_conn/ble_multi_conn_prph/sdkconfig.ci.name @@ -0,0 +1,3 @@ +CONFIG_EXAMPLE_CI_ID=29 +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} +CONFIG_BT_NIMBLE_MAX_CONNECTIONS=4 diff --git a/examples/bluetooth/nimble/ble_pawr_adv/ble_pawr_adv/main/Kconfig.projbuild b/examples/bluetooth/nimble/ble_pawr_adv/ble_pawr_adv/main/Kconfig.projbuild index c7b32ae16d8..53e0f1e8930 100644 --- a/examples/bluetooth/nimble/ble_pawr_adv/ble_pawr_adv/main/Kconfig.projbuild +++ b/examples/bluetooth/nimble/ble_pawr_adv/ble_pawr_adv/main/Kconfig.projbuild @@ -24,4 +24,16 @@ menu "Example Configuration" select BT_NIMBLE_PERIODIC_ADV_ENH help Use this option to enable periodic advertising enhancements + + config EXAMPLE_CI_ID + int "example id for CI test" + default 0 + help + This config the example id for CI test. Only for internal used. + + config EXAMPLE_CI_PIPELINE_ID + int "The pipeline id for CI test" + default 0 + help + This config the pipeline id for CI test. Only for internal used. endmenu diff --git a/examples/bluetooth/nimble/ble_pawr_adv/ble_pawr_adv/main/main.c b/examples/bluetooth/nimble/ble_pawr_adv/ble_pawr_adv/main/main.c index 7bfbffe7172..46b991b222a 100644 --- a/examples/bluetooth/nimble/ble_pawr_adv/ble_pawr_adv/main/main.c +++ b/examples/bluetooth/nimble/ble_pawr_adv/ble_pawr_adv/main/main.c @@ -3,6 +3,8 @@ * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ +#include +#include #include "esp_log.h" #include "nvs_flash.h" /* BLE */ @@ -24,6 +26,21 @@ static struct ble_gap_set_periodic_adv_subev_data_params sub_data_params[BLE_PAWR_NUM_SUBEVTS]; static uint8_t sub_data_pattern[BLE_PAWR_SUB_DATA_LEN] = {0}; +static char device_name[32] = "Nimble_PAwR"; + +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID +static char *esp_ble_pawr_get_example_name(void) +{ + static char example_name[32]; + + memset(example_name, 0, sizeof(example_name)); + snprintf(example_name, sizeof(example_name), "BE%02X_%05X_%02X", + CONFIG_EXAMPLE_CI_ID & 0xFF, + CONFIG_EXAMPLE_CI_PIPELINE_ID & 0xFFFFF, + CONFIG_IDF_FIRMWARE_CHIP_ID & 0xFF); + return example_name; +} +#endif static int gap_event_cb(struct ble_gap_event *event, void *arg) @@ -133,8 +150,8 @@ start_periodic_adv(uint8_t own_addr_type) assert (rc == 0); memset(&adv_fields, 0, sizeof(adv_fields)); - adv_fields.name = (const uint8_t *)"Nimble_PAwR"; - adv_fields.name_len = strlen((char *)adv_fields.name); + adv_fields.name = (const uint8_t *)device_name; + adv_fields.name_len = strlen(device_name); /* mbuf chain will be increased if needed */ data = os_msys_get_pkthdr(BLE_HCI_MAX_ADV_DATA_LEN, 0); @@ -228,6 +245,13 @@ app_main(void) return; } +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + strncpy(device_name, esp_ble_pawr_get_example_name(), sizeof(device_name) - 1); + device_name[sizeof(device_name) - 1] = '\0'; + ESP_LOGI(TAG, "DeviceName:%s, CIID:%02X, PipelineID:%05X, ChipID:%02X", + device_name, CONFIG_EXAMPLE_CI_ID, CONFIG_EXAMPLE_CI_PIPELINE_ID, CONFIG_IDF_FIRMWARE_CHIP_ID); +#endif + /* Initialize the NimBLE host configuration. */ ble_hs_cfg.reset_cb = on_reset; ble_hs_cfg.sync_cb = on_sync; diff --git a/examples/bluetooth/nimble/ble_pawr_adv/ble_pawr_adv/sdkconfig.ci.name b/examples/bluetooth/nimble/ble_pawr_adv/ble_pawr_adv/sdkconfig.ci.name new file mode 100644 index 00000000000..efe727a31e2 --- /dev/null +++ b/examples/bluetooth/nimble/ble_pawr_adv/ble_pawr_adv/sdkconfig.ci.name @@ -0,0 +1,2 @@ +CONFIG_EXAMPLE_CI_ID=32 +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} diff --git a/examples/bluetooth/nimble/ble_pawr_adv/ble_pawr_sync/main/Kconfig.projbuild b/examples/bluetooth/nimble/ble_pawr_adv/ble_pawr_sync/main/Kconfig.projbuild index c7b32ae16d8..53e0f1e8930 100644 --- a/examples/bluetooth/nimble/ble_pawr_adv/ble_pawr_sync/main/Kconfig.projbuild +++ b/examples/bluetooth/nimble/ble_pawr_adv/ble_pawr_sync/main/Kconfig.projbuild @@ -24,4 +24,16 @@ menu "Example Configuration" select BT_NIMBLE_PERIODIC_ADV_ENH help Use this option to enable periodic advertising enhancements + + config EXAMPLE_CI_ID + int "example id for CI test" + default 0 + help + This config the example id for CI test. Only for internal used. + + config EXAMPLE_CI_PIPELINE_ID + int "The pipeline id for CI test" + default 0 + help + This config the pipeline id for CI test. Only for internal used. endmenu diff --git a/examples/bluetooth/nimble/ble_pawr_adv/ble_pawr_sync/main/main.c b/examples/bluetooth/nimble/ble_pawr_adv/ble_pawr_sync/main/main.c index 1ef1b305550..b92a661062b 100644 --- a/examples/bluetooth/nimble/ble_pawr_adv/ble_pawr_sync/main/main.c +++ b/examples/bluetooth/nimble/ble_pawr_adv/ble_pawr_sync/main/main.c @@ -3,6 +3,8 @@ * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ +#include +#include #include "esp_log.h" #include "nvs_flash.h" /* BLE */ @@ -12,7 +14,6 @@ #include "host/util/util.h" #define TAG "NimBLE_BLE_PAwR" -#define TARGET_NAME "Nimble_PAwR" #define BLE_PAWR_RSP_DATA_IDX (2) #define BLE_PAWR_RSP_DATA_LEN (16) @@ -23,6 +24,21 @@ static void start_scan(void); static struct ble_hs_adv_fields fields; static bool synced = false; +static char remote_device_name[32] = "Nimble_PAwR"; + +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID +static char *esp_ble_pawr_get_example_name(void) +{ + static char example_name[32]; + + memset(example_name, 0, sizeof(example_name)); + snprintf(example_name, sizeof(example_name), "BE%02X_%05X_%02X", + CONFIG_EXAMPLE_CI_ID & 0xFF, + CONFIG_EXAMPLE_CI_PIPELINE_ID & 0xFFFFF, + CONFIG_IDF_FIRMWARE_CHIP_ID & 0xFF); + return example_name; +} +#endif static int gap_event_cb(struct ble_gap_event *event, void *arg) @@ -47,7 +63,13 @@ gap_event_cb(struct ble_gap_event *event, void *arg) return 0; } - if (disc->periodic_adv_itvl && fields.name_len == strlen(TARGET_NAME) && !memcmp(fields.name, TARGET_NAME, fields.name_len)) { + if (disc->periodic_adv_itvl && fields.name != NULL && + fields.name_len == strlen(remote_device_name) && + memcmp(fields.name, remote_device_name, fields.name_len) == 0) { +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + ESP_LOGI(TAG, "Found device: addr: %02x:%02x:%02x:%02x:%02x:%02x, name: %s", + addr[5], addr[4], addr[3], addr[2], addr[1], addr[0], remote_device_name); +#endif create_periodic_sync(disc); } return 0; @@ -169,8 +191,14 @@ start_scan(void) * each advertiser. */ memset(&disc_params, 0, sizeof(disc_params)); +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + /* Full scan under CI to improve discovery reliability in multi-board labs. */ + disc_params.itvl = BLE_GAP_SCAN_ITVL_MS(50); + disc_params.window = BLE_GAP_SCAN_ITVL_MS(50); +#else disc_params.itvl = BLE_GAP_SCAN_ITVL_MS(600); disc_params.window = BLE_GAP_SCAN_ITVL_MS(300); +#endif disc_params.passive = 1; /* Tell the controller to filter duplicates; we don't want to process @@ -237,6 +265,14 @@ app_main(void) return; } +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + strncpy(remote_device_name, esp_ble_pawr_get_example_name(), sizeof(remote_device_name) - 1); + remote_device_name[sizeof(remote_device_name) - 1] = '\0'; + ESP_LOGI(TAG, "DeviceName:%s, CIID:%02X, PipelineID:%05X, ChipID:%02X", + remote_device_name, CONFIG_EXAMPLE_CI_ID, CONFIG_EXAMPLE_CI_PIPELINE_ID, + CONFIG_IDF_FIRMWARE_CHIP_ID); +#endif + /* Initialize the NimBLE host configuration. */ ble_hs_cfg.reset_cb = on_reset; ble_hs_cfg.sync_cb = on_sync; diff --git a/examples/bluetooth/nimble/ble_pawr_adv/ble_pawr_sync/sdkconfig.ci.name b/examples/bluetooth/nimble/ble_pawr_adv/ble_pawr_sync/sdkconfig.ci.name new file mode 100644 index 00000000000..efe727a31e2 --- /dev/null +++ b/examples/bluetooth/nimble/ble_pawr_adv/ble_pawr_sync/sdkconfig.ci.name @@ -0,0 +1,2 @@ +CONFIG_EXAMPLE_CI_ID=32 +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} diff --git a/examples/bluetooth/nimble/ble_pawr_adv_conn/ble_pawr_adv_conn/main/Kconfig.projbuild b/examples/bluetooth/nimble/ble_pawr_adv_conn/ble_pawr_adv_conn/main/Kconfig.projbuild index c7b32ae16d8..53e0f1e8930 100644 --- a/examples/bluetooth/nimble/ble_pawr_adv_conn/ble_pawr_adv_conn/main/Kconfig.projbuild +++ b/examples/bluetooth/nimble/ble_pawr_adv_conn/ble_pawr_adv_conn/main/Kconfig.projbuild @@ -24,4 +24,16 @@ menu "Example Configuration" select BT_NIMBLE_PERIODIC_ADV_ENH help Use this option to enable periodic advertising enhancements + + config EXAMPLE_CI_ID + int "example id for CI test" + default 0 + help + This config the example id for CI test. Only for internal used. + + config EXAMPLE_CI_PIPELINE_ID + int "The pipeline id for CI test" + default 0 + help + This config the pipeline id for CI test. Only for internal used. endmenu diff --git a/examples/bluetooth/nimble/ble_pawr_adv_conn/ble_pawr_adv_conn/main/main.c b/examples/bluetooth/nimble/ble_pawr_adv_conn/ble_pawr_adv_conn/main/main.c index f5145169cc4..a391993e197 100644 --- a/examples/bluetooth/nimble/ble_pawr_adv_conn/ble_pawr_adv_conn/main/main.c +++ b/examples/bluetooth/nimble/ble_pawr_adv_conn/ble_pawr_adv_conn/main/main.c @@ -3,6 +3,8 @@ * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ +#include +#include #include "esp_log.h" #include "nvs_flash.h" /* BLE */ @@ -26,6 +28,21 @@ static uint8_t sub_data_pattern[BLE_PAWR_SUB_DATA_LEN] = {0}; static uint8_t conn; static uint8_t own_addr_type; static struct ble_gap_conn_desc desc; +static char device_name[32] = "Nimble_PAwR_CONN"; + +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID +static char *esp_ble_pawr_conn_get_example_name(void) +{ + static char example_name[32]; + + memset(example_name, 0, sizeof(example_name)); + snprintf(example_name, sizeof(example_name), "BE%02X_%05X_%02X", + CONFIG_EXAMPLE_CI_ID & 0xFF, + CONFIG_EXAMPLE_CI_PIPELINE_ID & 0xFFFFF, + CONFIG_IDF_FIRMWARE_CHIP_ID & 0xFF); + return example_name; +} +#endif char * addr_str(const void *addr) { @@ -221,8 +238,8 @@ start_periodic_adv(uint8_t own_addr_type) assert (rc == 0); memset(&adv_fields, 0, sizeof(adv_fields)); - adv_fields.name = (const uint8_t *)"Nimble_PAwR_CONN"; - adv_fields.name_len = strlen((char *)adv_fields.name); + adv_fields.name = (const uint8_t *)device_name; + adv_fields.name_len = strlen(device_name); /* mbuf chain will be increased if needed */ data = os_msys_get_pkthdr(BLE_HCI_MAX_ADV_DATA_LEN, 0); @@ -316,6 +333,13 @@ app_main(void) return; } +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + strncpy(device_name, esp_ble_pawr_conn_get_example_name(), sizeof(device_name) - 1); + device_name[sizeof(device_name) - 1] = '\0'; + ESP_LOGI(TAG, "DeviceName:%s, CIID:%02X, PipelineID:%05X, ChipID:%02X", + device_name, CONFIG_EXAMPLE_CI_ID, CONFIG_EXAMPLE_CI_PIPELINE_ID, CONFIG_IDF_FIRMWARE_CHIP_ID); +#endif + /* Initialize the NimBLE host configuration. */ ble_hs_cfg.reset_cb = on_reset; ble_hs_cfg.sync_cb = on_sync; diff --git a/examples/bluetooth/nimble/ble_pawr_adv_conn/ble_pawr_adv_conn/sdkconfig.ci.name b/examples/bluetooth/nimble/ble_pawr_adv_conn/ble_pawr_adv_conn/sdkconfig.ci.name new file mode 100644 index 00000000000..5965040f713 --- /dev/null +++ b/examples/bluetooth/nimble/ble_pawr_adv_conn/ble_pawr_adv_conn/sdkconfig.ci.name @@ -0,0 +1,2 @@ +CONFIG_EXAMPLE_CI_ID=31 +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} diff --git a/examples/bluetooth/nimble/ble_pawr_adv_conn/ble_pawr_sync_conn/main/Kconfig.projbuild b/examples/bluetooth/nimble/ble_pawr_adv_conn/ble_pawr_sync_conn/main/Kconfig.projbuild index c7b32ae16d8..53e0f1e8930 100644 --- a/examples/bluetooth/nimble/ble_pawr_adv_conn/ble_pawr_sync_conn/main/Kconfig.projbuild +++ b/examples/bluetooth/nimble/ble_pawr_adv_conn/ble_pawr_sync_conn/main/Kconfig.projbuild @@ -24,4 +24,16 @@ menu "Example Configuration" select BT_NIMBLE_PERIODIC_ADV_ENH help Use this option to enable periodic advertising enhancements + + config EXAMPLE_CI_ID + int "example id for CI test" + default 0 + help + This config the example id for CI test. Only for internal used. + + config EXAMPLE_CI_PIPELINE_ID + int "The pipeline id for CI test" + default 0 + help + This config the pipeline id for CI test. Only for internal used. endmenu diff --git a/examples/bluetooth/nimble/ble_pawr_adv_conn/ble_pawr_sync_conn/main/main.c b/examples/bluetooth/nimble/ble_pawr_adv_conn/ble_pawr_sync_conn/main/main.c index 3ab740b1dbc..fdd1e5b37f6 100644 --- a/examples/bluetooth/nimble/ble_pawr_adv_conn/ble_pawr_sync_conn/main/main.c +++ b/examples/bluetooth/nimble/ble_pawr_adv_conn/ble_pawr_sync_conn/main/main.c @@ -3,6 +3,8 @@ * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ +#include +#include #include "esp_log.h" #include "nvs_flash.h" /* BLE */ @@ -12,7 +14,6 @@ #include "host/util/util.h" #define TAG "NimBLE_BLE_PAwR_CONN" -#define TARGET_NAME "Nimble_PAwR_CONN" #define BLE_PAWR_RSP_SLOT_INDEX (2) #define BLE_PAWR_RSP_DATA_LEN (10) static uint8_t sub_data_pattern[BLE_PAWR_RSP_DATA_LEN] = {0}; @@ -23,6 +24,21 @@ static void start_scan(void); static struct ble_hs_adv_fields fields; static bool synced = false; uint8_t device_addr[6]; +static char remote_device_name[32] = "Nimble_PAwR_CONN"; + +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID +static char *esp_ble_pawr_conn_get_example_name(void) +{ + static char example_name[32]; + + memset(example_name, 0, sizeof(example_name)); + snprintf(example_name, sizeof(example_name), "BE%02X_%05X_%02X", + CONFIG_EXAMPLE_CI_ID & 0xFF, + CONFIG_EXAMPLE_CI_PIPELINE_ID & 0xFFFFF, + CONFIG_IDF_FIRMWARE_CHIP_ID & 0xFF); + return example_name; +} +#endif static struct ble_gap_conn_desc desc; char * @@ -100,7 +116,12 @@ gap_event_cb(struct ble_gap_event *event, void *arg) return 0; } - if (fields.name_len == strlen(TARGET_NAME) && !memcmp(fields.name, TARGET_NAME, fields.name_len)) { + if (fields.name != NULL && fields.name_len == strlen(remote_device_name) && + memcmp(fields.name, remote_device_name, fields.name_len) == 0) { +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + ESP_LOGI(TAG, "Found device: addr: %02x:%02x:%02x:%02x:%02x:%02x, name: %s", + addr[5], addr[4], addr[3], addr[2], addr[1], addr[0], remote_device_name); +#endif create_periodic_sync(disc); } return 0; @@ -238,8 +259,14 @@ start_scan(void) * each advertiser. */ memset(&disc_params, 0, sizeof(disc_params)); +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + /* Full scan under CI to improve discovery reliability in multi-board labs. */ + disc_params.itvl = BLE_GAP_SCAN_ITVL_MS(50); + disc_params.window = BLE_GAP_SCAN_ITVL_MS(50); +#else disc_params.itvl = BLE_GAP_SCAN_ITVL_MS(600); disc_params.window = BLE_GAP_SCAN_ITVL_MS(300); +#endif disc_params.passive = 1; /* Tell the controller to filter duplicates; we don't want to process @@ -306,6 +333,14 @@ app_main(void) return; } +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + strncpy(remote_device_name, esp_ble_pawr_conn_get_example_name(), sizeof(remote_device_name) - 1); + remote_device_name[sizeof(remote_device_name) - 1] = '\0'; + ESP_LOGI(TAG, "DeviceName:%s, CIID:%02X, PipelineID:%05X, ChipID:%02X", + remote_device_name, CONFIG_EXAMPLE_CI_ID, CONFIG_EXAMPLE_CI_PIPELINE_ID, + CONFIG_IDF_FIRMWARE_CHIP_ID); +#endif + /* Initialize the NimBLE host configuration. */ ble_hs_cfg.reset_cb = on_reset; ble_hs_cfg.sync_cb = on_sync; diff --git a/examples/bluetooth/nimble/ble_pawr_adv_conn/ble_pawr_sync_conn/sdkconfig.ci.name b/examples/bluetooth/nimble/ble_pawr_adv_conn/ble_pawr_sync_conn/sdkconfig.ci.name new file mode 100644 index 00000000000..5965040f713 --- /dev/null +++ b/examples/bluetooth/nimble/ble_pawr_adv_conn/ble_pawr_sync_conn/sdkconfig.ci.name @@ -0,0 +1,2 @@ +CONFIG_EXAMPLE_CI_ID=31 +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} diff --git a/examples/bluetooth/nimble/ble_periodic_adv/main/Kconfig.projbuild b/examples/bluetooth/nimble/ble_periodic_adv/main/Kconfig.projbuild index b996e2fb90f..20fad944bd0 100644 --- a/examples/bluetooth/nimble/ble_periodic_adv/main/Kconfig.projbuild +++ b/examples/bluetooth/nimble/ble_periodic_adv/main/Kconfig.projbuild @@ -13,4 +13,16 @@ menu "Example Configuration" select BT_NIMBLE_PERIODIC_ADV_ENH help Use this option to enable periodic advertising enhancements + + config EXAMPLE_CI_ID + int "example id for CI test" + default 0 + help + This config the example id for CI test. Only for internal used. + + config EXAMPLE_CI_PIPELINE_ID + int "The pipeline id for CI test" + default 0 + help + This config the pipeline id for CI test. Only for internal used. endmenu diff --git a/examples/bluetooth/nimble/ble_periodic_adv/main/main.c b/examples/bluetooth/nimble/ble_periodic_adv/main/main.c index c315ba9b7a1..53be1bacc58 100644 --- a/examples/bluetooth/nimble/ble_periodic_adv/main/main.c +++ b/examples/bluetooth/nimble/ble_periodic_adv/main/main.c @@ -5,6 +5,7 @@ */ #include +#include #include #include "esp_log.h" #include "nvs_flash.h" @@ -22,9 +23,24 @@ static uint8_t periodic_adv_raw_data[] = {'E', 'S', 'P', '_', 'P', 'E', 'R', 'I', 'O', 'D', 'I', 'C', '_', 'A', 'D', 'V'}; static const char *tag = "NimBLE_BLE_PERIODIC_ADV"; +static char device_name[32] = "Periodic ADV"; void ble_store_config_init(void); +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID +static char *esp_ble_periodic_get_example_name(void) +{ + static char example_name[32]; + + memset(example_name, 0, sizeof(example_name)); + snprintf(example_name, sizeof(example_name), "BE%02X_%05X_%02X", + CONFIG_EXAMPLE_CI_ID & 0xFF, + CONFIG_EXAMPLE_CI_PIPELINE_ID & 0xFFFFF, + CONFIG_IDF_FIRMWARE_CHIP_ID & 0xFF); + return example_name; +} +#endif + /** * Configures and starts periodic advertising with extended * non-connectable advertising on instance 0. @@ -68,8 +84,8 @@ start_periodic_adv(uint8_t own_addr_type) MODLOG_DFLT(INFO, "\n"); memset(&adv_fields, 0, sizeof(adv_fields)); - adv_fields.name = (const uint8_t *)"Periodic ADV"; - adv_fields.name_len = strlen((char *)adv_fields.name); + adv_fields.name = (const uint8_t *)device_name; + adv_fields.name_len = strlen(device_name); /* Default to legacy PDUs size, mbuf chain will be increased if needed */ @@ -173,6 +189,13 @@ app_main(void) return; } +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + strncpy(device_name, esp_ble_periodic_get_example_name(), sizeof(device_name) - 1); + device_name[sizeof(device_name) - 1] = '\0'; + ESP_LOGI(tag, "DeviceName:%s, CIID:%02X, PipelineID:%05X, ChipID:%02X", + device_name, CONFIG_EXAMPLE_CI_ID, CONFIG_EXAMPLE_CI_PIPELINE_ID, CONFIG_IDF_FIRMWARE_CHIP_ID); +#endif + /* Initialize the NimBLE host configuration. */ ble_hs_cfg.reset_cb = periodic_adv_on_reset; ble_hs_cfg.sync_cb = periodic_adv_on_sync; @@ -180,7 +203,7 @@ app_main(void) #if CONFIG_BT_NIMBLE_GAP_SERVICE /* Set the default device name. */ - int rc = ble_svc_gap_device_name_set("nimble_periodic_adv"); + int rc = ble_svc_gap_device_name_set(device_name); assert(rc == 0); #endif diff --git a/examples/bluetooth/nimble/ble_periodic_adv/sdkconfig.ci.esp32c2_xtal26m b/examples/bluetooth/nimble/ble_periodic_adv/sdkconfig.ci.esp32c2_xtal26m new file mode 100644 index 00000000000..8284f739707 --- /dev/null +++ b/examples/bluetooth/nimble/ble_periodic_adv/sdkconfig.ci.esp32c2_xtal26m @@ -0,0 +1,4 @@ +CONFIG_EXAMPLE_CI_ID=38 +CONFIG_IDF_TARGET="esp32c2" +CONFIG_XTAL_FREQ_26=y +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} diff --git a/examples/bluetooth/nimble/ble_periodic_adv/sdkconfig.ci.name b/examples/bluetooth/nimble/ble_periodic_adv/sdkconfig.ci.name new file mode 100644 index 00000000000..df426b9a958 --- /dev/null +++ b/examples/bluetooth/nimble/ble_periodic_adv/sdkconfig.ci.name @@ -0,0 +1,2 @@ +CONFIG_EXAMPLE_CI_ID=38 +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} diff --git a/examples/bluetooth/nimble/ble_periodic_sync/main/Kconfig.projbuild b/examples/bluetooth/nimble/ble_periodic_sync/main/Kconfig.projbuild index d30f44b046a..9b811ce7378 100644 --- a/examples/bluetooth/nimble/ble_periodic_sync/main/Kconfig.projbuild +++ b/examples/bluetooth/nimble/ble_periodic_sync/main/Kconfig.projbuild @@ -7,4 +7,16 @@ menu "Example Configuration" select BT_NIMBLE_PERIODIC_ADV_ENH help Use this option to enable periodic adv enhancements + + config EXAMPLE_CI_ID + int "example id for CI test" + default 0 + help + This config the example id for CI test. Only for internal used. + + config EXAMPLE_CI_PIPELINE_ID + int "The pipeline id for CI test" + default 0 + help + This config the pipeline id for CI test. Only for internal used. endmenu diff --git a/examples/bluetooth/nimble/ble_periodic_sync/main/main.c b/examples/bluetooth/nimble/ble_periodic_sync/main/main.c index 74632c3f951..c3c75b996e1 100644 --- a/examples/bluetooth/nimble/ble_periodic_sync/main/main.c +++ b/examples/bluetooth/nimble/ble_periodic_sync/main/main.c @@ -15,24 +15,40 @@ #include "nimble/nimble_port_freertos.h" #include "host/ble_hs.h" #include "host/ble_gap.h" +#include "host/ble_hs_adv.h" #include "host/util/util.h" #include "services/gap/ble_svc_gap.h" #include "modlog/modlog.h" static const char *tag = "NimBLE_BLE_PERIODIC_SYNC"; static int synced = 0; - +static char remote_device_name[32] = "Periodic ADV"; static int periodic_sync_gap_event(struct ble_gap_event *event, void *arg); void ble_store_config_init(void); +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID +static char *esp_ble_periodic_get_example_name(void) +{ + static char example_name[32]; + + memset(example_name, 0, sizeof(example_name)); + snprintf(example_name, sizeof(example_name), "BE%02X_%05X_%02X", + CONFIG_EXAMPLE_CI_ID & 0xFF, + CONFIG_EXAMPLE_CI_PIPELINE_ID & 0xFFFFF, + CONFIG_IDF_FIRMWARE_CHIP_ID & 0xFF); + return example_name; +} +#endif + static void periodic_sync_scan(void) { uint8_t own_addr_type; struct ble_gap_ext_disc_params disc_params = {0}; int rc; + uint8_t filter_duplicates = 0; /* Figure out address to use while advertising (no privacy for now) */ rc = ble_hs_id_infer_auto(0, &own_addr_type); @@ -42,9 +58,15 @@ periodic_sync_scan(void) } disc_params.passive = 1; +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + /* Full scan under CI to improve discovery reliability in multi-board labs. */ + disc_params.itvl = BLE_GAP_SCAN_ITVL_MS(50); + disc_params.window = BLE_GAP_SCAN_ITVL_MS(50); + filter_duplicates = 1; +#endif rc = ble_gap_ext_disc(own_addr_type, 0, 0, - 0, 0, 0, &disc_params, &disc_params, + filter_duplicates, 0, 0, &disc_params, &disc_params, periodic_sync_gap_event, NULL); if (rc != 0) { MODLOG_DFLT(ERROR, "Error initiating GAP discovery procedure; rc=%d\n", @@ -56,8 +78,13 @@ void print_periodic_sync_data(struct ble_gap_event *event) { MODLOG_DFLT(INFO, "status : %d\nperiodic_sync_handle : %d\nsid : %d\n", event->periodic_sync.status, event->periodic_sync.sync_handle, event->periodic_sync.sid); - MODLOG_DFLT(INFO, "adv addr : "); - ESP_LOG_BUFFER_HEX("NimBLE", event->periodic_sync.adv_addr.val, 6); + ESP_LOGI(tag, "Adv Addr: %02x:%02x:%02x:%02x:%02x:%02x", + event->periodic_sync.adv_addr.val[5], + event->periodic_sync.adv_addr.val[4], + event->periodic_sync.adv_addr.val[3], + event->periodic_sync.adv_addr.val[2], + event->periodic_sync.adv_addr.val[1], + event->periodic_sync.adv_addr.val[0]); MODLOG_DFLT(INFO, "adv_phy : %s\n", event->periodic_sync.adv_phy == 1 ? "1m" : (event->periodic_sync.adv_phy == 2 ? "2m" : "coded")); MODLOG_DFLT(INFO, "per_adv_ival : %d\n", event->periodic_sync.per_adv_ival); MODLOG_DFLT(INFO, "adv_clk_accuracy : %d\n", event->periodic_sync.adv_clk_accuracy); @@ -103,7 +130,30 @@ periodic_sync_gap_event(struct ble_gap_event *event, void *arg) case BLE_GAP_EVENT_EXT_DISC: { /* An advertisement report was received during GAP discovery. */ const struct ble_gap_ext_disc_desc *disc = &event->ext_disc; - if (disc->sid == 2 && synced == 0) { + bool should_sync = false; + + if (synced != 0) { + return 0; + } + +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + struct ble_hs_adv_fields fields; + int rc_parse = ble_hs_adv_parse_fields(&fields, disc->data, disc->length_data); + if (rc_parse == 0 && disc->sid == 2 && disc->periodic_adv_itvl && + fields.name != NULL && + fields.name_len == strlen(remote_device_name) && + memcmp(fields.name, remote_device_name, fields.name_len) == 0) { + const uint8_t *addr = disc->addr.val; + ESP_LOGI(tag, "Found device: addr: %02x:%02x:%02x:%02x:%02x:%02x, name: %s", + addr[5], addr[4], addr[3], addr[2], addr[1], addr[0], remote_device_name); + should_sync = true; + } +#else + if (disc->sid == 2) { + should_sync = true; + } +#endif + if (should_sync) { struct ble_gap_periodic_sync_params params = {0}; int rc; params.skip = 10; @@ -120,6 +170,7 @@ periodic_sync_gap_event(struct ble_gap_event *event, void *arg) MODLOG_DFLT(ERROR, "Failed to create periodic sync; rc=%d\n", rc); } else { synced++; + ESP_LOGI(tag, "Create sync"); } } return 0; @@ -137,10 +188,12 @@ periodic_sync_gap_event(struct ble_gap_event *event, void *arg) return 0; case BLE_GAP_EVENT_PERIODIC_SYNC: MODLOG_DFLT(INFO, "Periodic sync event : \n"); - print_periodic_sync_data(event); if (event->periodic_sync.status != 0) { + ESP_LOGE(tag, "Periodic Sync Failed; status=%d", event->periodic_sync.status); synced = 0; } else { + ESP_LOGI(tag, "Periodic Sync Established"); + print_periodic_sync_data(event); /* Cancel scanning since sync is established */ ble_gap_disc_cancel(); } @@ -195,6 +248,14 @@ app_main(void) return; } +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + strncpy(remote_device_name, esp_ble_periodic_get_example_name(), sizeof(remote_device_name) - 1); + remote_device_name[sizeof(remote_device_name) - 1] = '\0'; + ESP_LOGI(tag, "DeviceName:%s, CIID:%02X, PipelineID:%05X, ChipID:%02X", + remote_device_name, CONFIG_EXAMPLE_CI_ID, CONFIG_EXAMPLE_CI_PIPELINE_ID, + CONFIG_IDF_FIRMWARE_CHIP_ID); +#endif + /* Configure the host. */ ble_hs_cfg.reset_cb = periodic_sync_on_reset; ble_hs_cfg.sync_cb = periodic_sync_on_sync; diff --git a/examples/bluetooth/nimble/ble_periodic_sync/sdkconfig.ci.esp32c2_xtal26m b/examples/bluetooth/nimble/ble_periodic_sync/sdkconfig.ci.esp32c2_xtal26m new file mode 100644 index 00000000000..8284f739707 --- /dev/null +++ b/examples/bluetooth/nimble/ble_periodic_sync/sdkconfig.ci.esp32c2_xtal26m @@ -0,0 +1,4 @@ +CONFIG_EXAMPLE_CI_ID=38 +CONFIG_IDF_TARGET="esp32c2" +CONFIG_XTAL_FREQ_26=y +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} diff --git a/examples/bluetooth/nimble/ble_periodic_sync/sdkconfig.ci.name b/examples/bluetooth/nimble/ble_periodic_sync/sdkconfig.ci.name new file mode 100644 index 00000000000..df426b9a958 --- /dev/null +++ b/examples/bluetooth/nimble/ble_periodic_sync/sdkconfig.ci.name @@ -0,0 +1,2 @@ +CONFIG_EXAMPLE_CI_ID=38 +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} diff --git a/examples/bluetooth/nimble/ble_phy/phy_cent/main/Kconfig.projbuild b/examples/bluetooth/nimble/ble_phy/phy_cent/main/Kconfig.projbuild index dbfbdb13241..458159d5eeb 100644 --- a/examples/bluetooth/nimble/ble_phy/phy_cent/main/Kconfig.projbuild +++ b/examples/bluetooth/nimble/ble_phy/phy_cent/main/Kconfig.projbuild @@ -6,4 +6,16 @@ menu "Example Configuration" help Enter the peer address in aa:bb:cc:dd:ee:ff form to connect to a specific peripheral + config EXAMPLE_CI_ID + int "example id for CI test" + default 0 + help + This config the example id for CI test. Only for internal used. + + config EXAMPLE_CI_PIPELINE_ID + int "The pipeline id for CI test" + default 0 + help + This config the pipeline id for CI test. Only for internal used. + endmenu diff --git a/examples/bluetooth/nimble/ble_phy/phy_cent/main/main.c b/examples/bluetooth/nimble/ble_phy/phy_cent/main/main.c index 219a4ba7531..7c308cb2529 100644 --- a/examples/bluetooth/nimble/ble_phy/phy_cent/main/main.c +++ b/examples/bluetooth/nimble/ble_phy/phy_cent/main/main.c @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ +#include #include "esp_log.h" #include "nvs_flash.h" /* BLE */ @@ -18,12 +19,29 @@ static const char *tag = "NimBLE_BLE_PHY_CENT"; static int blecent_gap_event(struct ble_gap_event *event, void *arg); static ble_addr_t conn_addr; +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID +static char remote_device_name[32]; +#endif static void blecent_scan(void); static uint8_t s_current_phy; void ble_store_config_init(void); +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID +static char *esp_ble_phy_get_example_name(void) +{ + static char example_name[32]; + + memset(example_name, 0, sizeof(example_name)); + snprintf(example_name, sizeof(example_name), "BE%02X_%05X_%02X", + CONFIG_EXAMPLE_CI_ID & 0xFF, + CONFIG_EXAMPLE_CI_PIPELINE_ID & 0xFFFFF, + CONFIG_IDF_FIRMWARE_CHIP_ID & 0xFF); + return example_name; +} +#endif + #if MYNEWT_VAL(BLE_GATTC) /** * Performs GATT operation against the specified peer: @@ -234,6 +252,12 @@ blecent_scan(void) disc_params.filter_policy = 0; disc_params.limited = 0; +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + /* Full scan improves discovery reliability in multi-board CI environments. */ + disc_params.itvl = BLE_GAP_SCAN_ITVL_MS(50); + disc_params.window = BLE_GAP_SCAN_ITVL_MS(50); +#endif + rc = ble_gap_disc(own_addr_type, BLE_HS_FOREVER, &disc_params, blecent_gap_event, NULL); if (rc != 0) { @@ -268,6 +292,24 @@ ext_blecent_should_connect(const struct ble_gap_ext_disc_desc *disc) } } +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + while (offset < disc->length_data) { + ad_struct_len = disc->data[offset]; + if (ad_struct_len == 0 || offset + ad_struct_len + 1 > disc->length_data) { + break; + } + if (disc->data[offset + 1] == BLE_HS_ADV_TYPE_COMP_NAME || + disc->data[offset + 1] == BLE_HS_ADV_TYPE_INCOMP_NAME) { + int name_len = ad_struct_len - 1; + if (name_len == (int)strlen(remote_device_name) && + memcmp(&disc->data[offset + 2], remote_device_name, name_len) == 0) { + return 1; + } + } + offset += ad_struct_len + 1; + } + return 0; +#else /* The device has to advertise support LE PHY UUID (0xABF2). */ while (offset < disc->length_data) { @@ -289,6 +331,7 @@ ext_blecent_should_connect(const struct ble_gap_ext_disc_desc *disc) offset += ad_struct_len + 1; } return 0; +#endif } /** @@ -308,6 +351,11 @@ blecent_connect_if_interesting(void *disc) return; } +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + ESP_LOGI(tag, "Found device: addr: %s, name: %s", + addr_str(((struct ble_gap_ext_disc_desc *)disc)->addr.val), remote_device_name); +#endif + #if !(MYNEWT_VAL(BLE_HOST_ALLOW_CONNECT_WITH_SCAN)) /* Scanning must be stopped before a connection can be initiated. */ rc = ble_gap_disc_cancel(); @@ -577,6 +625,13 @@ app_main(void) return; } +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + strncpy(remote_device_name, esp_ble_phy_get_example_name(), sizeof(remote_device_name) - 1); + remote_device_name[sizeof(remote_device_name) - 1] = '\0'; + ESP_LOGI(tag, "DeviceName:%s, CIID:%02X, PipelineID:%05X, ChipID:%02X", + remote_device_name, CONFIG_EXAMPLE_CI_ID, CONFIG_EXAMPLE_CI_PIPELINE_ID, CONFIG_IDF_FIRMWARE_CHIP_ID); +#endif + /* Configure the host. */ ble_hs_cfg.reset_cb = blecent_on_reset; ble_hs_cfg.sync_cb = blecent_on_sync; diff --git a/examples/bluetooth/nimble/ble_phy/phy_cent/sdkconfig.ci.esp32c2_xtal26m b/examples/bluetooth/nimble/ble_phy/phy_cent/sdkconfig.ci.esp32c2_xtal26m new file mode 100644 index 00000000000..1c1307c7044 --- /dev/null +++ b/examples/bluetooth/nimble/ble_phy/phy_cent/sdkconfig.ci.esp32c2_xtal26m @@ -0,0 +1,4 @@ +CONFIG_EXAMPLE_CI_ID=30 +CONFIG_IDF_TARGET="esp32c2" +CONFIG_XTAL_FREQ_26=y +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} diff --git a/examples/bluetooth/nimble/ble_phy/phy_cent/sdkconfig.ci.name b/examples/bluetooth/nimble/ble_phy/phy_cent/sdkconfig.ci.name new file mode 100644 index 00000000000..71425fe31bf --- /dev/null +++ b/examples/bluetooth/nimble/ble_phy/phy_cent/sdkconfig.ci.name @@ -0,0 +1,2 @@ +CONFIG_EXAMPLE_CI_ID=30 +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} diff --git a/examples/bluetooth/nimble/ble_phy/phy_prph/main/Kconfig.projbuild b/examples/bluetooth/nimble/ble_phy/phy_prph/main/Kconfig.projbuild index 0d088c0d202..303b4e6dd82 100644 --- a/examples/bluetooth/nimble/ble_phy/phy_prph/main/Kconfig.projbuild +++ b/examples/bluetooth/nimble/ble_phy/phy_prph/main/Kconfig.projbuild @@ -44,4 +44,16 @@ menu "Example Configuration" prompt "Use Secure Connection feature" help Use this option to enable/disable Security Manager Secure Connection 4.2 feature. + + config EXAMPLE_CI_ID + int "example id for CI test" + default 0 + help + This config the example id for CI test. Only for internal used. + + config EXAMPLE_CI_PIPELINE_ID + int "The pipeline id for CI test" + default 0 + help + This config the pipeline id for CI test. Only for internal used. endmenu diff --git a/examples/bluetooth/nimble/ble_phy/phy_prph/main/main.c b/examples/bluetooth/nimble/ble_phy/phy_prph/main/main.c index 44e9b30875c..56ed186a042 100644 --- a/examples/bluetooth/nimble/ble_phy/phy_prph/main/main.c +++ b/examples/bluetooth/nimble/ble_phy/phy_prph/main/main.c @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ +#include #include "esp_log.h" #include "nvs_flash.h" /* BLE */ @@ -15,6 +16,7 @@ #include "services/gap/ble_svc_gap.h" #include "phy_prph.h" +#if !(CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID) static uint8_t ext_adv_pattern_1M[] = { 0x02, BLE_HS_ADV_TYPE_FLAGS, 0x06, 0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0xF2, 0xAB, @@ -33,14 +35,30 @@ static uint8_t ext_adv_pattern_coded[] = { 0x11, BLE_HS_ADV_TYPE_COMP_NAME, 'b', 'l', 'e', 'p', 'r', 'p', 'h', '-', 'p', 'h', 'y', '-', 'c', 'o', 'd', 'e', 'd', }; +#endif static const char *tag = "NimBLE_BLE_PHY_PRPH"; static int bleprph_gap_event(struct ble_gap_event *event, void *arg); static uint8_t own_addr_type; +static char device_name[32] = "bleprph-phy"; static uint8_t s_current_phy; void ble_store_config_init(void); +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID +static char *esp_ble_phy_get_example_name(void) +{ + static char example_name[32]; + + memset(example_name, 0, sizeof(example_name)); + snprintf(example_name, sizeof(example_name), "BE%02X_%05X_%02X", + CONFIG_EXAMPLE_CI_ID & 0xFF, + CONFIG_EXAMPLE_CI_PIPELINE_ID & 0xFFFFF, + CONFIG_IDF_FIRMWARE_CHIP_ID & 0xFF); + return example_name; +} +#endif + /* Set default LE PHY before establishing connection */ void set_default_le_phy(uint8_t tx_phys_mask, uint8_t rx_phys_mask) { @@ -91,6 +109,24 @@ ext_get_data(uint8_t ext_adv_pattern[], int size) return data; } +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID +/* Build CI advertisement data that contains only the Complete Local Name. */ +static struct os_mbuf * +build_ci_adv_data(const char *name) +{ + uint8_t buf[32]; + uint8_t name_len = (uint8_t)strlen(name); + + if (name_len > sizeof(buf) - 2) { + name_len = sizeof(buf) - 2; + } + buf[0] = name_len + 1; + buf[1] = BLE_HS_ADV_TYPE_COMP_NAME; + memcpy(&buf[2], name, name_len); + return ext_get_data(buf, 2 + name_len); +} +#endif + /** * Enables advertising with the following parameters: * o General discoverable mode. @@ -123,21 +159,33 @@ ext_bleprph_advertise(void) case BLE_HCI_LE_PHY_1M_PREF_MASK: params.primary_phy = BLE_HCI_LE_PHY_1M; params.secondary_phy = BLE_HCI_LE_PHY_1M; +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + data = build_ci_adv_data(device_name); +#else data = ext_get_data(ext_adv_pattern_1M, sizeof(ext_adv_pattern_1M)); +#endif params.sid = 0; break; case BLE_HCI_LE_PHY_2M_PREF_MASK: params.primary_phy = BLE_HCI_LE_PHY_1M; params.secondary_phy = BLE_HCI_LE_PHY_2M; +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + data = build_ci_adv_data(device_name); +#else data = ext_get_data(ext_adv_pattern_2M, sizeof(ext_adv_pattern_2M)); +#endif params.sid = 1; break; case BLE_HCI_LE_PHY_CODED_PREF_MASK: params.primary_phy = BLE_HCI_LE_PHY_CODED; params.secondary_phy = BLE_HCI_LE_PHY_CODED; +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + data = build_ci_adv_data(device_name); +#else data = ext_get_data(ext_adv_pattern_coded, sizeof(ext_adv_pattern_coded)); +#endif params.sid = 2; break; } @@ -324,6 +372,13 @@ app_main(void) return; } +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + strncpy(device_name, esp_ble_phy_get_example_name(), sizeof(device_name) - 1); + device_name[sizeof(device_name) - 1] = '\0'; + ESP_LOGI(tag, "DeviceName:%s, CIID:%02X, PipelineID:%05X, ChipID:%02X", + device_name, CONFIG_EXAMPLE_CI_ID, CONFIG_EXAMPLE_CI_PIPELINE_ID, CONFIG_IDF_FIRMWARE_CHIP_ID); +#endif + /* Initialize the NimBLE host configuration. */ ble_hs_cfg.reset_cb = bleprph_on_reset; ble_hs_cfg.sync_cb = bleprph_on_sync; @@ -354,7 +409,7 @@ app_main(void) #if CONFIG_BT_NIMBLE_GAP_SERVICE /* Set the default device name. */ - rc = ble_svc_gap_device_name_set("bleprph-phy"); + rc = ble_svc_gap_device_name_set(device_name); assert(rc == 0); #endif diff --git a/examples/bluetooth/nimble/ble_phy/phy_prph/sdkconfig.ci.esp32c2_xtal26m b/examples/bluetooth/nimble/ble_phy/phy_prph/sdkconfig.ci.esp32c2_xtal26m new file mode 100644 index 00000000000..1c1307c7044 --- /dev/null +++ b/examples/bluetooth/nimble/ble_phy/phy_prph/sdkconfig.ci.esp32c2_xtal26m @@ -0,0 +1,4 @@ +CONFIG_EXAMPLE_CI_ID=30 +CONFIG_IDF_TARGET="esp32c2" +CONFIG_XTAL_FREQ_26=y +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} diff --git a/examples/bluetooth/nimble/ble_phy/phy_prph/sdkconfig.ci.name b/examples/bluetooth/nimble/ble_phy/phy_prph/sdkconfig.ci.name new file mode 100644 index 00000000000..71425fe31bf --- /dev/null +++ b/examples/bluetooth/nimble/ble_phy/phy_prph/sdkconfig.ci.name @@ -0,0 +1,2 @@ +CONFIG_EXAMPLE_CI_ID=30 +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} diff --git a/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_cent/main/Kconfig.projbuild b/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_cent/main/Kconfig.projbuild index eefb5c98154..ea153b6c0a0 100644 --- a/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_cent/main/Kconfig.projbuild +++ b/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_cent/main/Kconfig.projbuild @@ -23,4 +23,16 @@ menu "Example Configuration" Use this option to enable extended advertising in the example. If this option is disabled, ensure config BT_NIMBLE_EXT_ADV is also disabled from Nimble stack menuconfig + + config EXAMPLE_CI_ID + int "Example ID for CI test" + default 0 + help + This config sets the example ID for CI test. For internal use only. + + config EXAMPLE_CI_PIPELINE_ID + int "Pipeline ID for CI test" + default 0 + help + This config sets the pipeline ID for CI test. For internal use only. endmenu diff --git a/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_cent/main/main.c b/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_cent/main/main.c index b5b584c1b98..96d6cc8459f 100644 --- a/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_cent/main/main.c +++ b/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_cent/main/main.c @@ -4,6 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include +#include #include "esp_log.h" #include "nvs_flash.h" /* BLE */ @@ -18,11 +20,33 @@ #include "host/ble_esp_gattc_cache.h" #endif +#define EXAMPLE_ADV_NAME_LEN_MAX 29 + +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID +static char *get_example_name(void) +{ + static char example_name[EXAMPLE_ADV_NAME_LEN_MAX]; + memset(example_name, 0, sizeof(example_name)); + snprintf(example_name, sizeof(example_name), "BE%02X_%05X_%02X", CONFIG_EXAMPLE_CI_ID & 0xFF, + CONFIG_EXAMPLE_CI_PIPELINE_ID & 0xFFFFF, CONFIG_IDF_FIRMWARE_CHIP_ID & 0xFF); + return example_name; +} +#endif + static const char *tag = "NimBLE_PROX_CENT"; +static char remote_device_name[EXAMPLE_ADV_NAME_LEN_MAX]; static int8_t tx_pwr_lvl; static struct ble_prox_cent_conn_peer conn_peer[MYNEWT_VAL(BLE_MAX_CONNECTIONS) + 1]; static struct ble_prox_cent_link_lost_peer disconn_peer[MYNEWT_VAL(BLE_MAX_CONNECTIONS) + 1]; +/* Note: Path loss is calculated using formula : threshold - RSSI value + * by default threshold is kept -128 as per the spec + * high_threshold and low_threshold are hardcoded after testing and noting + * RSSI values when distance between devices are less and more. + */ +static int8_t high_threshold = -70; +static int8_t low_threshold = -100; + void ble_store_config_init(void); static void ble_prox_cent_scan(void); static int ble_prox_cent_gap_event(struct ble_gap_event *event, void *arg); @@ -212,6 +236,12 @@ ble_prox_cent_scan(void) disc_params.filter_policy = 0; disc_params.limited = 0; +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + /* Full scan improves discovery reliability in multi-board CI environments. */ + disc_params.itvl = BLE_GAP_SCAN_ITVL_MS(50); + disc_params.window = BLE_GAP_SCAN_ITVL_MS(50); +#endif + rc = ble_gap_disc(own_addr_type, BLE_HS_FOREVER, &disc_params, ble_prox_cent_gap_event, NULL); if (rc != 0) { @@ -232,18 +262,26 @@ ext_ble_prox_cent_should_connect(const struct ble_gap_ext_disc_desc *disc) { int offset = 0; int ad_struct_len = 0; - uint8_t test_addr[6]; + int link_loss_uuid_found = 0; +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + char dev_name[EXAMPLE_ADV_NAME_LEN_MAX]; + int name_matched = 0; +#endif if (!(disc->props & BLE_HCI_ADV_CONN_MASK)) { return 0; } - if (strlen(CONFIG_EXAMPLE_PEER_ADDR) && (strncmp(CONFIG_EXAMPLE_PEER_ADDR, "ADDR_ANY", strlen ("ADDR_ANY")) != 0)) { - ESP_LOGI(tag, "Peer address from menuconfig: %s", CONFIG_EXAMPLE_PEER_ADDR); - /* Convert string to address; peer_addr_parse outputs little-endian matching disc->addr.val */ - peer_addr_parse(CONFIG_EXAMPLE_PEER_ADDR, test_addr); - if (memcmp(test_addr, disc->addr.val, sizeof(disc->addr.val)) != 0) { - return 0; +#if !(CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID) + { + uint8_t test_addr[6]; + if (strlen(CONFIG_EXAMPLE_PEER_ADDR) && (strncmp(CONFIG_EXAMPLE_PEER_ADDR, "ADDR_ANY", strlen("ADDR_ANY")) != 0)) { + ESP_LOGI(tag, "Peer address from menuconfig: %s", CONFIG_EXAMPLE_PEER_ADDR); + peer_addr_parse(CONFIG_EXAMPLE_PEER_ADDR, test_addr); + if (memcmp(test_addr, disc->addr.val, sizeof(disc->addr.val)) != 0) { + return 0; + } } } +#endif /* The device has to advertise support for Proximity sensor (link loss) * service (0x1803). @@ -255,17 +293,37 @@ ext_ble_prox_cent_should_connect(const struct ble_gap_ext_disc_desc *disc) break; } - /* Search if Proximity Sensor (Link loss) UUID 0x1803 is advertised (little-endian: [0x03, 0x18]) */ - if (disc->data[offset] == 0x03 && disc->data[offset + 1] == 0x03) { - if ( disc->data[offset + 2] == 0x03 && disc->data[offset + 3] == 0x18 ) { - return 1; +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + if (disc->data[offset + 1] == BLE_HS_ADV_TYPE_COMP_NAME || + disc->data[offset + 1] == BLE_HS_ADV_TYPE_INCOMP_NAME) { + int name_len = ad_struct_len - 1; + if (name_len == (int)strlen(remote_device_name) && + memcmp(&disc->data[offset + 2], remote_device_name, name_len) == 0) { + name_matched = 1; + memcpy(dev_name, remote_device_name, name_len + 1); + } + } +#endif + /* UUID 0x1803 little-endian [0x03, 0x18] */ + if (disc->data[offset] == 0x03 && disc->data[offset + 1] == 0x03) { + if (disc->data[offset + 2] == 0x03 && disc->data[offset + 3] == 0x18) { + link_loss_uuid_found = 1; } } - offset += ad_struct_len + 1; } +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + if (name_matched && link_loss_uuid_found) { + ESP_LOGI(tag, "Found device: addr: %02x:%02x:%02x:%02x:%02x:%02x, name: %s", + disc->addr.val[5], disc->addr.val[4], disc->addr.val[3], + disc->addr.val[2], disc->addr.val[1], disc->addr.val[0], dev_name); + return 1; + } return 0; +#else + return link_loss_uuid_found; +#endif } #else @@ -275,7 +333,7 @@ ble_prox_cent_should_connect(const struct ble_gap_disc_desc *disc) struct ble_hs_adv_fields fields; int rc; int i; - uint8_t test_addr[6]; + /* The device has to be advertising connectability. */ if (disc->event_type != BLE_HCI_ADV_RPT_EVTYPE_ADV_IND && disc->event_type != BLE_HCI_ADV_RPT_EVTYPE_DIR_IND) { @@ -288,18 +346,38 @@ ble_prox_cent_should_connect(const struct ble_gap_disc_desc *disc) return rc; } - if (strlen(CONFIG_EXAMPLE_PEER_ADDR) && (strncmp(CONFIG_EXAMPLE_PEER_ADDR, "ADDR_ANY", strlen("ADDR_ANY")) != 0)) { - ESP_LOGI(tag, "Peer address from menuconfig: %s", CONFIG_EXAMPLE_PEER_ADDR); - /* Convert string to address */ - peer_addr_parse(CONFIG_EXAMPLE_PEER_ADDR, test_addr); - if (memcmp(test_addr, disc->addr.val, sizeof(disc->addr.val)) != 0) { - return 0; +#if !(CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID) + { + uint8_t test_addr[6]; + if (strlen(CONFIG_EXAMPLE_PEER_ADDR) && (strncmp(CONFIG_EXAMPLE_PEER_ADDR, "ADDR_ANY", strlen("ADDR_ANY")) != 0)) { + ESP_LOGI(tag, "Peer address from menuconfig: %s", CONFIG_EXAMPLE_PEER_ADDR); + peer_addr_parse(CONFIG_EXAMPLE_PEER_ADDR, test_addr); + if (memcmp(test_addr, disc->addr.val, sizeof(disc->addr.val)) != 0) { + return 0; + } } } +#endif /* The device has to advertise support for the Proximity sensor (link loss) * service (0x1803). */ +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + if (fields.name != NULL && + fields.name_len == strlen(remote_device_name) && + memcmp(fields.name, remote_device_name, fields.name_len) == 0) { + for (i = 0; i < fields.num_uuids16; i++) { + if (ble_uuid_u16(&fields.uuids16[i].u) == BLE_SVC_LINK_LOSS_UUID16) { + ESP_LOGI(tag, "Found device: addr: %02x:%02x:%02x:%02x:%02x:%02x, name: %s", + disc->addr.val[5], disc->addr.val[4], disc->addr.val[3], + disc->addr.val[2], disc->addr.val[1], disc->addr.val[0], + remote_device_name); + return 1; + } + } + } + return 0; +#else for (i = 0; i < fields.num_uuids16; i++) { if (ble_uuid_u16(&fields.uuids16[i].u) == BLE_SVC_LINK_LOSS_UUID16) { return 1; @@ -307,6 +385,7 @@ ble_prox_cent_should_connect(const struct ble_gap_disc_desc *disc) } return 0; +#endif } #endif @@ -478,9 +557,8 @@ ble_prox_cent_gap_event(struct ble_gap_event *event, void *arg) /* Connection attempt failed; resume scanning. */ MODLOG_DFLT(ERROR, "Error: Connection failed; status=%d\n", event->connect.status); - - ble_prox_cent_scan(); } + ble_prox_cent_scan(); return 0; case BLE_GAP_EVENT_DISCONNECT: @@ -639,9 +717,16 @@ ble_prox_cent_path_loss_task(void *pvParameters) MODLOG_DFLT(INFO, "path loss = %d pwr lvl = %d rssi = %d", path_loss, tx_pwr_lvl, rssi); - if (conn_peer[i].val_handle != 0) { - int8_t path_loss_val = (int8_t)path_loss; + if ((conn_peer[i].val_handle != 0) && + (path_loss > high_threshold || path_loss < low_threshold)) { + + if (path_loss < low_threshold) { + path_loss = 0; + } + #if MYNEWT_VAL(BLE_GATTC) + /* Alert Level is a single-octet characteristic (UUID 0x2A06). */ + uint8_t path_loss_val = (uint8_t)path_loss; rc = ble_gattc_write_no_rsp_flat(i, conn_peer[i].val_handle, &path_loss_val, sizeof(path_loss_val)); if (rc != 0) { @@ -757,6 +842,14 @@ app_main(void) assert(rc == 0); #endif +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + strncpy(remote_device_name, get_example_name(), sizeof(remote_device_name) - 1); + remote_device_name[sizeof(remote_device_name) - 1] = '\0'; + ESP_LOGI(tag, "DeviceName:%s, CIID:%02X, PipelineID:%05X, ChipID:%02X", + remote_device_name, CONFIG_EXAMPLE_CI_ID, CONFIG_EXAMPLE_CI_PIPELINE_ID, + CONFIG_IDF_FIRMWARE_CHIP_ID); +#endif + /* XXX Need to have template for store */ ble_store_config_init(); diff --git a/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_cent/sdkconfig.ci.conn_with_scan b/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_cent/sdkconfig.ci.conn_with_scan new file mode 100644 index 00000000000..91b9986e5c0 --- /dev/null +++ b/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_cent/sdkconfig.ci.conn_with_scan @@ -0,0 +1,3 @@ +CONFIG_EXAMPLE_CI_ID=34 +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} +CONFIG_BT_NIMBLE_HOST_ALLOW_CONNECT_WITH_SCAN=y diff --git a/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_cent/sdkconfig.ci.conn_with_scan_v4 b/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_cent/sdkconfig.ci.conn_with_scan_v4 new file mode 100644 index 00000000000..16fda98bc27 --- /dev/null +++ b/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_cent/sdkconfig.ci.conn_with_scan_v4 @@ -0,0 +1,4 @@ +CONFIG_EXAMPLE_CI_ID=36 +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} +CONFIG_EXAMPLE_EXTENDED_ADV=n +CONFIG_BT_NIMBLE_HOST_ALLOW_CONNECT_WITH_SCAN=y diff --git a/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_cent/sdkconfig.ci.esp32_name_v4 b/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_cent/sdkconfig.ci.esp32_name_v4 new file mode 100644 index 00000000000..748cb9e6f1a --- /dev/null +++ b/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_cent/sdkconfig.ci.esp32_name_v4 @@ -0,0 +1,3 @@ +CONFIG_EXAMPLE_CI_ID=37 +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} +CONFIG_EXAMPLE_EXTENDED_ADV=n diff --git a/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_cent/sdkconfig.ci.esp32c2_xtal26m b/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_cent/sdkconfig.ci.esp32c2_xtal26m new file mode 100644 index 00000000000..9a36b52ff8d --- /dev/null +++ b/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_cent/sdkconfig.ci.esp32c2_xtal26m @@ -0,0 +1,5 @@ +CONFIG_EXAMPLE_CI_ID=33 +CONFIG_IDF_TARGET="esp32c2" +CONFIG_XTAL_FREQ_26=y +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} +CONFIG_BT_NIMBLE_HOST_ALLOW_CONNECT_WITH_SCAN=n diff --git a/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_cent/sdkconfig.ci.esp32c2_xtal26m_conn_with_scan b/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_cent/sdkconfig.ci.esp32c2_xtal26m_conn_with_scan new file mode 100644 index 00000000000..8c20b239eaa --- /dev/null +++ b/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_cent/sdkconfig.ci.esp32c2_xtal26m_conn_with_scan @@ -0,0 +1,5 @@ +CONFIG_EXAMPLE_CI_ID=34 +CONFIG_IDF_TARGET="esp32c2" +CONFIG_XTAL_FREQ_26=y +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} +CONFIG_BT_NIMBLE_HOST_ALLOW_CONNECT_WITH_SCAN=y diff --git a/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_cent/sdkconfig.ci.esp32c2_xtal26m_conn_with_scan_v4 b/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_cent/sdkconfig.ci.esp32c2_xtal26m_conn_with_scan_v4 new file mode 100644 index 00000000000..d25dd11a24a --- /dev/null +++ b/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_cent/sdkconfig.ci.esp32c2_xtal26m_conn_with_scan_v4 @@ -0,0 +1,6 @@ +CONFIG_EXAMPLE_CI_ID=36 +CONFIG_IDF_TARGET="esp32c2" +CONFIG_XTAL_FREQ_26=y +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} +CONFIG_EXAMPLE_EXTENDED_ADV=n +CONFIG_BT_NIMBLE_HOST_ALLOW_CONNECT_WITH_SCAN=y diff --git a/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_cent/sdkconfig.ci.esp32c2_xtal26m_name_v4 b/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_cent/sdkconfig.ci.esp32c2_xtal26m_name_v4 new file mode 100644 index 00000000000..68fa35e24bf --- /dev/null +++ b/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_cent/sdkconfig.ci.esp32c2_xtal26m_name_v4 @@ -0,0 +1,6 @@ +CONFIG_EXAMPLE_CI_ID=35 +CONFIG_IDF_TARGET="esp32c2" +CONFIG_XTAL_FREQ_26=y +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} +CONFIG_EXAMPLE_EXTENDED_ADV=n +CONFIG_BT_NIMBLE_HOST_ALLOW_CONNECT_WITH_SCAN=n diff --git a/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_cent/sdkconfig.ci.name b/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_cent/sdkconfig.ci.name new file mode 100644 index 00000000000..276f2d64ca4 --- /dev/null +++ b/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_cent/sdkconfig.ci.name @@ -0,0 +1,3 @@ +CONFIG_EXAMPLE_CI_ID=33 +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} +CONFIG_BT_NIMBLE_HOST_ALLOW_CONNECT_WITH_SCAN=n diff --git a/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_cent/sdkconfig.ci.name_v4 b/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_cent/sdkconfig.ci.name_v4 new file mode 100644 index 00000000000..5b964c871c0 --- /dev/null +++ b/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_cent/sdkconfig.ci.name_v4 @@ -0,0 +1,4 @@ +CONFIG_EXAMPLE_CI_ID=35 +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} +CONFIG_EXAMPLE_EXTENDED_ADV=n +CONFIG_BT_NIMBLE_HOST_ALLOW_CONNECT_WITH_SCAN=n diff --git a/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_prph/main/Kconfig.projbuild b/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_prph/main/Kconfig.projbuild index 3705112d5e2..1896226706f 100644 --- a/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_prph/main/Kconfig.projbuild +++ b/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_prph/main/Kconfig.projbuild @@ -10,4 +10,16 @@ menu "Example Configuration" Use this option to enable extended advertising in the example. If this option is disabled, ensure config BT_NIMBLE_EXT_ADV is also disabled from Nimble stack menuconfig + + config EXAMPLE_CI_ID + int "Example ID for CI test" + default 0 + help + This config sets the example ID for CI test. For internal use only. + + config EXAMPLE_CI_PIPELINE_ID + int "Pipeline ID for CI test" + default 0 + help + This config sets the pipeline ID for CI test. For internal use only. endmenu diff --git a/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_prph/main/main.c b/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_prph/main/main.c index 169e5f0fdfe..da75bb25c0e 100644 --- a/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_prph/main/main.c +++ b/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_prph/main/main.c @@ -4,6 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include +#include #include "esp_log.h" #include "nvs_flash.h" #include "freertos/FreeRTOSConfig.h" @@ -17,6 +19,19 @@ #include "services/gatt/ble_svc_gatt.h" #include "ble_prox_prph.h" +#define EXAMPLE_ADV_NAME_LEN_MAX 29 + +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID +static char *get_example_name(void) +{ + static char example_name[EXAMPLE_ADV_NAME_LEN_MAX]; + memset(example_name, 0, sizeof(example_name)); + snprintf(example_name, sizeof(example_name), "BE%02X_%05X_%02X", CONFIG_EXAMPLE_CI_ID & 0xFF, + CONFIG_EXAMPLE_CI_PIPELINE_ID & 0xFFFFF, CONFIG_IDF_FIRMWARE_CHIP_ID & 0xFF); + return example_name; +} +#endif + #if CONFIG_EXAMPLE_EXTENDED_ADV static uint8_t ext_adv_pattern_1[] = { 0x02, BLE_HS_ADV_TYPE_FLAGS, 0x06, @@ -24,10 +39,14 @@ static uint8_t ext_adv_pattern_1[] = { 0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0x03, 0x18, /* UUID 0x1803 in little-endian */ 0x13, BLE_HS_ADV_TYPE_COMP_NAME, 'n', 'i', 'm', 'b', 'l', 'e', '-', 'p', 'r', 'o', 'x', '-', 'p', 'r', 'p', 'h', '-', 'e', }; +/* AD layout: [0..2] flags, [3..6] UUID, [7..10] Link Loss 0x1803, [11..] Complete Local Name */ +#define EXT_ADV_NAME_LEN_OFFSET 11 /* len field of name AD = 1 (type) + strlen(name) */ +#define EXT_ADV_NAME_OFFSET 13 /* name bytes follow [len][0x09] */ #endif static const char *tag = "NimBLE_PROX_PRPH"; -static const char *device_name = "ble_prox_prph"; +static char device_name_buf[EXAMPLE_ADV_NAME_LEN_MAX] = "ble_prox_prph"; +static const char *device_name = device_name_buf; static int ble_prox_prph_gap_event(struct ble_gap_event *event, void *arg); @@ -101,8 +120,23 @@ ext_ble_prox_prph_advertise(void) data = os_msys_get_pkthdr(sizeof(ext_adv_pattern_1), 0); assert(data); +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + { + uint8_t adv_buf[sizeof(ext_adv_pattern_1)]; + uint8_t name_len = (uint8_t)strlen(get_example_name()); + + if (name_len > sizeof(adv_buf) - EXT_ADV_NAME_OFFSET) { + name_len = sizeof(adv_buf) - EXT_ADV_NAME_OFFSET; + } + memcpy(adv_buf, ext_adv_pattern_1, EXT_ADV_NAME_OFFSET); + adv_buf[EXT_ADV_NAME_LEN_OFFSET] = (uint8_t)(name_len + 1); + memcpy(&adv_buf[EXT_ADV_NAME_OFFSET], get_example_name(), name_len); + rc = os_mbuf_append(data, adv_buf, EXT_ADV_NAME_OFFSET + name_len); + } +#else /* fill mbuf with scan rsp data */ rc = os_mbuf_append(data, ext_adv_pattern_1, sizeof(ext_adv_pattern_1)); +#endif assert(rc == 0); rc = ble_gap_ext_adv_set_data(instance, data); @@ -312,6 +346,13 @@ void app_main(void) #if CONFIG_BT_NIMBLE_GAP_SERVICE int rc; +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + strncpy(device_name_buf, get_example_name(), sizeof(device_name_buf) - 1); + device_name_buf[sizeof(device_name_buf) - 1] = '\0'; + ESP_LOGI(tag, "DeviceName:%s, CIID:%02X, PipelineID:%05X, ChipID:%02X", + device_name_buf, CONFIG_EXAMPLE_CI_ID, CONFIG_EXAMPLE_CI_PIPELINE_ID, + CONFIG_IDF_FIRMWARE_CHIP_ID); +#endif /* Set the default device name */ rc = ble_svc_gap_device_name_set(device_name); assert(rc == 0); diff --git a/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_prph/sdkconfig.ci.conn_with_scan b/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_prph/sdkconfig.ci.conn_with_scan new file mode 100644 index 00000000000..91b9986e5c0 --- /dev/null +++ b/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_prph/sdkconfig.ci.conn_with_scan @@ -0,0 +1,3 @@ +CONFIG_EXAMPLE_CI_ID=34 +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} +CONFIG_BT_NIMBLE_HOST_ALLOW_CONNECT_WITH_SCAN=y diff --git a/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_prph/sdkconfig.ci.conn_with_scan_v4 b/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_prph/sdkconfig.ci.conn_with_scan_v4 new file mode 100644 index 00000000000..16fda98bc27 --- /dev/null +++ b/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_prph/sdkconfig.ci.conn_with_scan_v4 @@ -0,0 +1,4 @@ +CONFIG_EXAMPLE_CI_ID=36 +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} +CONFIG_EXAMPLE_EXTENDED_ADV=n +CONFIG_BT_NIMBLE_HOST_ALLOW_CONNECT_WITH_SCAN=y diff --git a/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_prph/sdkconfig.ci.esp32_name_v4 b/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_prph/sdkconfig.ci.esp32_name_v4 new file mode 100644 index 00000000000..748cb9e6f1a --- /dev/null +++ b/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_prph/sdkconfig.ci.esp32_name_v4 @@ -0,0 +1,3 @@ +CONFIG_EXAMPLE_CI_ID=37 +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} +CONFIG_EXAMPLE_EXTENDED_ADV=n diff --git a/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_prph/sdkconfig.ci.esp32c2_xtal26m b/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_prph/sdkconfig.ci.esp32c2_xtal26m new file mode 100644 index 00000000000..9a36b52ff8d --- /dev/null +++ b/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_prph/sdkconfig.ci.esp32c2_xtal26m @@ -0,0 +1,5 @@ +CONFIG_EXAMPLE_CI_ID=33 +CONFIG_IDF_TARGET="esp32c2" +CONFIG_XTAL_FREQ_26=y +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} +CONFIG_BT_NIMBLE_HOST_ALLOW_CONNECT_WITH_SCAN=n diff --git a/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_prph/sdkconfig.ci.esp32c2_xtal26m_conn_with_scan b/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_prph/sdkconfig.ci.esp32c2_xtal26m_conn_with_scan new file mode 100644 index 00000000000..8c20b239eaa --- /dev/null +++ b/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_prph/sdkconfig.ci.esp32c2_xtal26m_conn_with_scan @@ -0,0 +1,5 @@ +CONFIG_EXAMPLE_CI_ID=34 +CONFIG_IDF_TARGET="esp32c2" +CONFIG_XTAL_FREQ_26=y +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} +CONFIG_BT_NIMBLE_HOST_ALLOW_CONNECT_WITH_SCAN=y diff --git a/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_prph/sdkconfig.ci.esp32c2_xtal26m_conn_with_scan_v4 b/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_prph/sdkconfig.ci.esp32c2_xtal26m_conn_with_scan_v4 new file mode 100644 index 00000000000..d25dd11a24a --- /dev/null +++ b/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_prph/sdkconfig.ci.esp32c2_xtal26m_conn_with_scan_v4 @@ -0,0 +1,6 @@ +CONFIG_EXAMPLE_CI_ID=36 +CONFIG_IDF_TARGET="esp32c2" +CONFIG_XTAL_FREQ_26=y +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} +CONFIG_EXAMPLE_EXTENDED_ADV=n +CONFIG_BT_NIMBLE_HOST_ALLOW_CONNECT_WITH_SCAN=y diff --git a/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_prph/sdkconfig.ci.esp32c2_xtal26m_name_v4 b/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_prph/sdkconfig.ci.esp32c2_xtal26m_name_v4 new file mode 100644 index 00000000000..68fa35e24bf --- /dev/null +++ b/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_prph/sdkconfig.ci.esp32c2_xtal26m_name_v4 @@ -0,0 +1,6 @@ +CONFIG_EXAMPLE_CI_ID=35 +CONFIG_IDF_TARGET="esp32c2" +CONFIG_XTAL_FREQ_26=y +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} +CONFIG_EXAMPLE_EXTENDED_ADV=n +CONFIG_BT_NIMBLE_HOST_ALLOW_CONNECT_WITH_SCAN=n diff --git a/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_prph/sdkconfig.ci.name b/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_prph/sdkconfig.ci.name new file mode 100644 index 00000000000..276f2d64ca4 --- /dev/null +++ b/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_prph/sdkconfig.ci.name @@ -0,0 +1,3 @@ +CONFIG_EXAMPLE_CI_ID=33 +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} +CONFIG_BT_NIMBLE_HOST_ALLOW_CONNECT_WITH_SCAN=n diff --git a/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_prph/sdkconfig.ci.name_v4 b/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_prph/sdkconfig.ci.name_v4 new file mode 100644 index 00000000000..5b964c871c0 --- /dev/null +++ b/examples/bluetooth/nimble/ble_proximity_sensor/proximity_sensor_prph/sdkconfig.ci.name_v4 @@ -0,0 +1,4 @@ +CONFIG_EXAMPLE_CI_ID=35 +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} +CONFIG_EXAMPLE_EXTENDED_ADV=n +CONFIG_BT_NIMBLE_HOST_ALLOW_CONNECT_WITH_SCAN=n diff --git a/examples/bluetooth/nimble/ble_spp/spp_client/main/Kconfig.projbuild b/examples/bluetooth/nimble/ble_spp/spp_client/main/Kconfig.projbuild new file mode 100644 index 00000000000..ba6d6fe1b27 --- /dev/null +++ b/examples/bluetooth/nimble/ble_spp/spp_client/main/Kconfig.projbuild @@ -0,0 +1,15 @@ +menu "Example Configuration" + + config EXAMPLE_CI_ID + int "example id for CI test" + default 0 + help + This config the example id for CI test. Only for internal used. + + config EXAMPLE_CI_PIPELINE_ID + int "The pipeline id for CI test" + default 0 + help + This config the pipeline id for CI test. Only for internal used. + +endmenu diff --git a/examples/bluetooth/nimble/ble_spp/spp_client/main/main.c b/examples/bluetooth/nimble/ble_spp/spp_client/main/main.c index 1c3308129a7..786afa68183 100644 --- a/examples/bluetooth/nimble/ble_spp/spp_client/main/main.c +++ b/examples/bluetooth/nimble/ble_spp/spp_client/main/main.c @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ +#include #include "esp_log.h" #include "nvs_flash.h" /* BLE */ @@ -18,7 +19,7 @@ #define PEER_ADDR_VAL_SIZE 6 -static const char *tag = "NimBLE_SPP_BLE_CENT"; +static const char *tag = "NimBLE_SPP_CLIENT"; static int ble_spp_client_gap_event(struct ble_gap_event *event, void *arg); QueueHandle_t spp_common_uart_queue = NULL; void ble_store_config_init(void); @@ -27,6 +28,22 @@ static SemaphoreHandle_t g_attr_handle_mutex = NULL; static void ble_spp_client_scan(void); static ble_addr_t connected_addr[CONFIG_BT_NIMBLE_MAX_CONNECTIONS + 1]; +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID +static char remote_device_name[32]; + +static char *esp_ble_spp_get_example_name(void) +{ + static char example_name[32]; + + memset(example_name, 0, sizeof(example_name)); + snprintf(example_name, sizeof(example_name), "BE%02X_%05X_%02X", + CONFIG_EXAMPLE_CI_ID & 0xFF, + CONFIG_EXAMPLE_CI_PIPELINE_ID & 0xFFFFF, + CONFIG_IDF_FIRMWARE_CHIP_ID & 0xFF); + return example_name; +} +#endif + #if MYNEWT_VAL(BLE_GATTC) static void ble_spp_client_write_subscribe(const struct peer *peer) { @@ -156,6 +173,12 @@ ble_spp_client_scan(void) disc_params.filter_policy = 0; disc_params.limited = 0; +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + /* Full scan improves discovery reliability in multi-board CI environments. */ + disc_params.itvl = BLE_GAP_SCAN_ITVL_MS(50); + disc_params.window = BLE_GAP_SCAN_ITVL_MS(50); +#endif + rc = ble_gap_disc(own_addr_type, BLE_HS_FOREVER, &disc_params, ble_spp_client_gap_event, NULL); if (rc != 0) { @@ -196,6 +219,14 @@ ble_spp_client_should_connect(const struct ble_gap_disc_desc *disc) return 0; } +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + if (fields.name != NULL && + fields.name_len == strlen(remote_device_name) && + memcmp(fields.name, remote_device_name, fields.name_len) == 0) { + return 1; + } + return 0; +#else /* The device has to advertise support for the SPP * service (0xABF0). */ @@ -205,6 +236,7 @@ ble_spp_client_should_connect(const struct ble_gap_disc_desc *disc) } } return 0; +#endif } /** @@ -223,6 +255,10 @@ ble_spp_client_connect_if_interesting(const struct ble_gap_disc_desc *disc) return; } +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + ESP_LOGI(tag, "Found device: %s, name: %s", addr_str(disc->addr.val), remote_device_name); +#endif + #if !(MYNEWT_VAL(BLE_HOST_ALLOW_CONNECT_WITH_SCAN)) /* Scanning must be stopped before a connection can be initiated. */ rc = ble_gap_disc_cancel(); @@ -308,6 +344,8 @@ ble_spp_client_gap_event(struct ble_gap_event *event, void *arg) } print_conn_desc(&desc); MODLOG_DFLT(INFO, "\n"); + ESP_LOGI(tag, "Connected, conn_handle %d, remote %s", + event->connect.conn_handle, addr_str(desc.peer_ota_addr.val)); /* Remember peer. */ rc = peer_add(event->connect.conn_handle); @@ -486,7 +524,8 @@ void ble_client_uart_task(void *pvParameters) static void ble_spp_uart_init(void) { uart_config_t uart_config = { - .baud_rate = 115200, + /* Keep console baud (e.g. 74880 on ESP32-C2 26MHz XTAL) when sharing UART0. */ + .baud_rate = CONFIG_ESP_CONSOLE_UART_BAUDRATE, .data_bits = UART_DATA_8_BITS, .parity = UART_PARITY_DISABLE, .stop_bits = UART_STOP_BITS_1, @@ -536,6 +575,14 @@ app_main(void) /* Initialize UART driver and start uart task */ ble_spp_uart_init(); +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + /* Log after UART0 init so DeviceName is not corrupted by uart_driver_install. */ + strncpy(remote_device_name, esp_ble_spp_get_example_name(), sizeof(remote_device_name) - 1); + remote_device_name[sizeof(remote_device_name) - 1] = '\0'; + ESP_LOGI(tag, "DeviceName:%s, CIID:%02X, PipelineID:%05X, ChipID:%02X", + remote_device_name, CONFIG_EXAMPLE_CI_ID, CONFIG_EXAMPLE_CI_PIPELINE_ID, CONFIG_IDF_FIRMWARE_CHIP_ID); +#endif + /* Configure the host. */ ble_hs_cfg.reset_cb = ble_spp_client_on_reset; ble_hs_cfg.sync_cb = ble_spp_client_on_sync; diff --git a/examples/bluetooth/nimble/ble_spp/spp_client/sdkconfig.ci.esp32c2_xtal26m b/examples/bluetooth/nimble/ble_spp/spp_client/sdkconfig.ci.esp32c2_xtal26m new file mode 100644 index 00000000000..5bb04a7b160 --- /dev/null +++ b/examples/bluetooth/nimble/ble_spp/spp_client/sdkconfig.ci.esp32c2_xtal26m @@ -0,0 +1,4 @@ +CONFIG_EXAMPLE_CI_ID=28 +CONFIG_IDF_TARGET="esp32c2" +CONFIG_XTAL_FREQ_26=y +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} diff --git a/examples/bluetooth/nimble/ble_spp/spp_client/sdkconfig.ci.name b/examples/bluetooth/nimble/ble_spp/spp_client/sdkconfig.ci.name new file mode 100644 index 00000000000..699ca5b9956 --- /dev/null +++ b/examples/bluetooth/nimble/ble_spp/spp_client/sdkconfig.ci.name @@ -0,0 +1,2 @@ +CONFIG_EXAMPLE_CI_ID=28 +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} diff --git a/examples/bluetooth/nimble/ble_spp/spp_server/main/Kconfig.projbuild b/examples/bluetooth/nimble/ble_spp/spp_server/main/Kconfig.projbuild index ad7ae8bcc28..1391d926863 100644 --- a/examples/bluetooth/nimble/ble_spp/spp_server/main/Kconfig.projbuild +++ b/examples/bluetooth/nimble/ble_spp/spp_server/main/Kconfig.projbuild @@ -4,4 +4,16 @@ menu "Example Configuration" int "IO Type" default 3 + config EXAMPLE_CI_ID + int "example id for CI test" + default 0 + help + This config the example id for CI test. Only for internal used. + + config EXAMPLE_CI_PIPELINE_ID + int "The pipeline id for CI test" + default 0 + help + This config the pipeline id for CI test. Only for internal used. + endmenu diff --git a/examples/bluetooth/nimble/ble_spp/spp_server/main/main.c b/examples/bluetooth/nimble/ble_spp/spp_server/main/main.c index 20ba388fece..0c7d57c7334 100644 --- a/examples/bluetooth/nimble/ble_spp/spp_server/main/main.c +++ b/examples/bluetooth/nimble/ble_spp/spp_server/main/main.c @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ +#include #include "esp_log.h" #include "nvs_flash.h" /* BLE */ @@ -17,15 +18,31 @@ #include "ble_spp_server.h" #include "driver/uart.h" +static const char *tag = "NimBLE_SPP_SERVER"; static int ble_spp_server_gap_event(struct ble_gap_event *event, void *arg); static uint8_t own_addr_type; int gatt_svr_register(void); QueueHandle_t spp_common_uart_queue = NULL; static bool conn_handle_subs[CONFIG_BT_NIMBLE_MAX_CONNECTIONS + 1]; static uint16_t ble_spp_svc_gatt_read_val_handle; +static char device_name[32] = "nimble-ble-spp-svr"; void ble_store_config_init(void); +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID +static char *esp_ble_spp_get_example_name(void) +{ + static char example_name[32]; + + memset(example_name, 0, sizeof(example_name)); + snprintf(example_name, sizeof(example_name), "BE%02X_%05X_%02X", + CONFIG_EXAMPLE_CI_ID & 0xFF, + CONFIG_EXAMPLE_CI_PIPELINE_ID & 0xFFFFF, + CONFIG_IDF_FIRMWARE_CHIP_ID & 0xFF); + return example_name; +} +#endif + /** * Logs information about a connection to the console. */ @@ -90,18 +107,19 @@ ble_spp_server_advertise(void) fields.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO; #if CONFIG_BT_NIMBLE_GAP_SERVICE - const char *name; - name = ble_svc_gap_device_name(); - fields.name = (uint8_t *)name; - fields.name_len = strlen(name); + fields.name = (uint8_t *)device_name; + fields.name_len = strlen(device_name); fields.name_is_complete = 1; #endif - fields.uuids16 = (ble_uuid16_t[]) { +#if !(CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID) + static const ble_uuid16_t adv_uuids16[] = { BLE_UUID16_INIT(BLE_SVC_SPP_UUID16) }; + fields.uuids16 = adv_uuids16; fields.num_uuids16 = 1; fields.uuids16_is_complete = 1; +#endif rc = ble_gap_adv_set_fields(&fields); if (rc != 0) { @@ -152,6 +170,11 @@ ble_spp_server_gap_event(struct ble_gap_event *event, void *arg) rc = ble_gap_conn_find(event->connect.conn_handle, &desc); assert(rc == 0); ble_spp_server_print_conn_desc(&desc); + ESP_LOGI(tag, "Connected, conn_handle %d, remote %02x:%02x:%02x:%02x:%02x:%02x", + event->connect.conn_handle, + desc.peer_ota_addr.val[5], desc.peer_ota_addr.val[4], + desc.peer_ota_addr.val[3], desc.peer_ota_addr.val[2], + desc.peer_ota_addr.val[1], desc.peer_ota_addr.val[0]); } MODLOG_DFLT(INFO, "\n"); if (event->connect.status != 0 || CONFIG_BT_NIMBLE_MAX_CONNECTIONS > 1) { @@ -250,7 +273,7 @@ ble_spp_server_on_sync(void) void ble_spp_server_host_task(void *param) { - MODLOG_DFLT(INFO, "BLE Host Task Started"); + ESP_LOGI(tag, "BLE Host Task Started"); /* This function will return only when nimble_port_stop() is executed */ nimble_port_run(); @@ -404,7 +427,8 @@ void ble_server_uart_task(void *pvParameters) static void ble_spp_uart_init(void) { uart_config_t uart_config = { - .baud_rate = 115200, + /* Keep console baud (e.g. 74880 on ESP32-C2 26MHz XTAL) when sharing UART0. */ + .baud_rate = CONFIG_ESP_CONSOLE_UART_BAUDRATE, .data_bits = UART_DATA_8_BITS, .parity = UART_PARITY_DISABLE, .stop_bits = UART_STOP_BITS_1, @@ -480,9 +504,16 @@ app_main(void) rc = gatt_svr_init(); assert(rc == 0); +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + strncpy(device_name, esp_ble_spp_get_example_name(), sizeof(device_name) - 1); + device_name[sizeof(device_name) - 1] = '\0'; + ESP_LOGI(tag, "DeviceName:%s, CIID:%02X, PipelineID:%05X, ChipID:%02X", + device_name, CONFIG_EXAMPLE_CI_ID, CONFIG_EXAMPLE_CI_PIPELINE_ID, CONFIG_IDF_FIRMWARE_CHIP_ID); +#endif + #if CONFIG_BT_NIMBLE_GAP_SERVICE /* Set the default device name. */ - rc = ble_svc_gap_device_name_set("nimble-ble-spp-svr"); + rc = ble_svc_gap_device_name_set(device_name); assert(rc == 0); #endif #endif diff --git a/examples/bluetooth/nimble/ble_spp/spp_server/sdkconfig.ci.esp32c2_xtal26m b/examples/bluetooth/nimble/ble_spp/spp_server/sdkconfig.ci.esp32c2_xtal26m new file mode 100644 index 00000000000..5bb04a7b160 --- /dev/null +++ b/examples/bluetooth/nimble/ble_spp/spp_server/sdkconfig.ci.esp32c2_xtal26m @@ -0,0 +1,4 @@ +CONFIG_EXAMPLE_CI_ID=28 +CONFIG_IDF_TARGET="esp32c2" +CONFIG_XTAL_FREQ_26=y +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} diff --git a/examples/bluetooth/nimble/ble_spp/spp_server/sdkconfig.ci.name b/examples/bluetooth/nimble/ble_spp/spp_server/sdkconfig.ci.name new file mode 100644 index 00000000000..699ca5b9956 --- /dev/null +++ b/examples/bluetooth/nimble/ble_spp/spp_server/sdkconfig.ci.name @@ -0,0 +1,2 @@ +CONFIG_EXAMPLE_CI_ID=28 +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} diff --git a/examples/bluetooth/nimble/blecent/main/Kconfig.projbuild b/examples/bluetooth/nimble/blecent/main/Kconfig.projbuild index 13d5cd0ddf0..b1a4c207dd9 100644 --- a/examples/bluetooth/nimble/blecent/main/Kconfig.projbuild +++ b/examples/bluetooth/nimble/blecent/main/Kconfig.projbuild @@ -36,4 +36,12 @@ menu "Example Configuration" help Used for internal test ONLY. Use this option to advertise in a specific random address. + + config EXAMPLE_CI_ID + int "example id for CI test" + default 0 + + config EXAMPLE_CI_PIPELINE_ID + int "The pipeline id for CI test" + default 0 endmenu diff --git a/examples/bluetooth/nimble/blecent/main/main.c b/examples/bluetooth/nimble/blecent/main/main.c index 99851b6b5f9..75cf7008f5e 100644 --- a/examples/bluetooth/nimble/blecent/main/main.c +++ b/examples/bluetooth/nimble/blecent/main/main.c @@ -17,6 +17,8 @@ * under the License. */ +#include +#include #include "esp_log.h" #include "nvs_flash.h" /* BLE */ @@ -44,6 +46,9 @@ static const ble_uuid_t * remote_chr_uuid = #endif static const char *tag = "NimBLE_BLE_CENT"; +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID +static char remote_device_name[32]; +#endif static int blecent_gap_event(struct ble_gap_event *event, void *arg); #if MYNEWT_VAL(BLE_EATT_CHAN_NUM) > 0 @@ -53,6 +58,20 @@ static uint16_t bearers; void ble_store_config_init(void); +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID +static char *esp_blecent_get_example_name(void) +{ + static char example_name[32]; + + memset(example_name, 0, sizeof(example_name)); + snprintf(example_name, sizeof(example_name), "BE%02X_%05X_%02X", + CONFIG_EXAMPLE_CI_ID & 0xFF, + CONFIG_EXAMPLE_CI_PIPELINE_ID & 0xFFFFF, + CONFIG_IDF_FIRMWARE_CHIP_ID & 0xFF); + return example_name; +} +#endif + #if MYNEWT_VAL(BLE_GATTC) /** * Application Callback. Called when the custom subscribable chatacteristic @@ -462,6 +481,12 @@ blecent_scan(void) disc_params.filter_policy = 0; disc_params.limited = 0; +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + /* Full scan improves discovery reliability in multi-board CI environments. */ + disc_params.itvl = BLE_GAP_SCAN_ITVL_MS(50); + disc_params.window = BLE_GAP_SCAN_ITVL_MS(50); +#endif + rc = ble_gap_disc(own_addr_type, BLE_HS_FOREVER, &disc_params, blecent_gap_event, NULL); if (rc != 0) { @@ -504,9 +529,27 @@ ext_blecent_should_connect(const struct ble_gap_ext_disc_desc *disc) } } +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + while (offset < disc->length_data) { + ad_struct_len = disc->data[offset]; + if (ad_struct_len == 0 || offset + ad_struct_len + 1 > disc->length_data) { + break; + } + if (disc->data[offset + 1] == BLE_HS_ADV_TYPE_COMP_NAME || + disc->data[offset + 1] == BLE_HS_ADV_TYPE_INCOMP_NAME) { + int name_len = ad_struct_len - 1; + if (name_len == (int)strlen(remote_device_name) && + memcmp(&disc->data[offset + 2], remote_device_name, name_len) == 0) { + return 1; + } + } + offset += ad_struct_len + 1; + } + return 0; +#else /* The device has to advertise support for the Alert Notification - * service (0x1811). - */ + * service (0x1811). + */ while (offset < disc->length_data) { ad_struct_len = disc->data[offset]; @@ -527,6 +570,7 @@ ext_blecent_should_connect(const struct ble_gap_ext_disc_desc *disc) } return 0; +#endif } #else static int @@ -534,7 +578,6 @@ blecent_should_connect(const struct ble_gap_disc_desc *disc) { struct ble_hs_adv_fields fields; int rc; - int i; uint8_t test_addr[6]; /* The device has to be advertising connectability. */ if (disc->event_type != BLE_HCI_ADV_RPT_EVTYPE_ADV_IND && @@ -567,16 +610,25 @@ blecent_should_connect(const struct ble_gap_disc_desc *disc) } } +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + if (fields.name != NULL && + fields.name_len == strlen(remote_device_name) && + memcmp(fields.name, remote_device_name, fields.name_len) == 0) { + return 1; + } + return 0; +#else /* The device has to advertise support for the Alert Notification * service (0x1811). */ - for (i = 0; i < fields.num_uuids16; i++) { + for (int i = 0; i < fields.num_uuids16; i++) { if (ble_uuid_u16(&fields.uuids16[i].u) == BLECENT_SVC_ALERT_UUID) { return 1; } } return 0; +#endif } #endif @@ -631,6 +683,10 @@ blecent_connect_if_interesting(void *disc) addr = &((struct ble_gap_disc_desc *)disc)->addr; #endif +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + ESP_LOGI(tag, "Found device: %s, name: %s", addr_str(addr->val), remote_device_name); +#endif + rc = ble_gap_connect(own_addr_type, addr, 30000, NULL, blecent_gap_event, NULL); if (rc != 0) { @@ -727,6 +783,8 @@ blecent_gap_event(struct ble_gap_event *event, void *arg) assert(rc == 0); print_conn_desc(&desc); MODLOG_DFLT(INFO, "\n"); + ESP_LOGI(tag, "Connected, conn_handle %d, remote %s", + event->connect.conn_handle, addr_str(desc.peer_ota_addr.val)); /* Remember peer. */ rc = peer_add(event->connect.conn_handle); @@ -1079,6 +1137,14 @@ app_main(void) return; } +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + strncpy(remote_device_name, esp_blecent_get_example_name(), sizeof(remote_device_name) - 1); + remote_device_name[sizeof(remote_device_name) - 1] = '\0'; + ESP_LOGI(tag, "DeviceName:%s, CIID:%02X, PipelineID:%05X, ChipID:%02X", + remote_device_name, CONFIG_EXAMPLE_CI_ID, CONFIG_EXAMPLE_CI_PIPELINE_ID, + CONFIG_IDF_FIRMWARE_CHIP_ID); +#endif + /* Configure the host. */ ble_hs_cfg.reset_cb = blecent_on_reset; ble_hs_cfg.sync_cb = blecent_on_sync; diff --git a/examples/bluetooth/nimble/blecent/sdkconfig.ci.bleprph_esp32c2_xtal26m b/examples/bluetooth/nimble/blecent/sdkconfig.ci.bleprph_esp32c2_xtal26m new file mode 100644 index 00000000000..1e0afd41560 --- /dev/null +++ b/examples/bluetooth/nimble/blecent/sdkconfig.ci.bleprph_esp32c2_xtal26m @@ -0,0 +1,7 @@ +CONFIG_EXAMPLE_CI_ID=39 +CONFIG_IDF_TARGET="esp32c2" +CONFIG_XTAL_FREQ_26=y +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} +CONFIG_EXAMPLE_EXTENDED_ADV=n +CONFIG_EXAMPLE_ENCRYPTION=n +CONFIG_BT_NIMBLE_EXT_ADV=n diff --git a/examples/bluetooth/nimble/blecent/sdkconfig.ci.name b/examples/bluetooth/nimble/blecent/sdkconfig.ci.name new file mode 100644 index 00000000000..a282509a498 --- /dev/null +++ b/examples/bluetooth/nimble/blecent/sdkconfig.ci.name @@ -0,0 +1,5 @@ +CONFIG_EXAMPLE_CI_ID=39 +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} +CONFIG_EXAMPLE_EXTENDED_ADV=n +CONFIG_EXAMPLE_ENCRYPTION=n +CONFIG_BT_NIMBLE_EXT_ADV=n diff --git a/examples/bluetooth/nimble/bleprph/main/Kconfig.projbuild b/examples/bluetooth/nimble/bleprph/main/Kconfig.projbuild index 2529f3bab9a..91c191babf4 100644 --- a/examples/bluetooth/nimble/bleprph/main/Kconfig.projbuild +++ b/examples/bluetooth/nimble/bleprph/main/Kconfig.projbuild @@ -77,4 +77,12 @@ menu "Example Configuration" help Use this option to enable resolving peer's address. + config EXAMPLE_CI_ID + int "example id for CI test" + default 0 + + config EXAMPLE_CI_PIPELINE_ID + int "The pipeline id for CI test" + default 0 + endmenu diff --git a/examples/bluetooth/nimble/bleprph/main/main.c b/examples/bluetooth/nimble/bleprph/main/main.c index 802f813ba17..08fe6b3c19e 100644 --- a/examples/bluetooth/nimble/bleprph/main/main.c +++ b/examples/bluetooth/nimble/bleprph/main/main.c @@ -17,6 +17,8 @@ * under the License. */ +#include +#include #include "esp_log.h" #include "nvs_flash.h" /* BLE */ @@ -38,6 +40,9 @@ static uint8_t ext_adv_pattern_1[] = { #endif static const char *tag = "NimBLE_BLE_PRPH"; +#if CONFIG_BT_NIMBLE_GAP_SERVICE || (CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID) +static char device_name[32] = "nimble-bleprph"; +#endif static int bleprph_gap_event(struct ble_gap_event *event, void *arg); #if CONFIG_EXAMPLE_RANDOM_ADDR static uint8_t own_addr_type = BLE_OWN_ADDR_RANDOM; @@ -52,6 +57,20 @@ static uint16_t bearers; void ble_store_config_init(void); +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID +static char *esp_bleprph_get_example_name(void) +{ + static char example_name[32]; + + memset(example_name, 0, sizeof(example_name)); + snprintf(example_name, sizeof(example_name), "BE%02X_%05X_%02X", + CONFIG_EXAMPLE_CI_ID & 0xFF, + CONFIG_EXAMPLE_CI_PIPELINE_ID & 0xFFFFF, + CONFIG_IDF_FIRMWARE_CHIP_ID & 0xFF); + return example_name; +} +#endif + #if NIMBLE_BLE_CONNECT /** * Logs information about a connection to the console. @@ -94,6 +113,11 @@ ext_bleprph_advertise(void) struct os_mbuf *data; uint8_t instance = 0; int rc; +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + uint8_t ci_adv_data[32]; + uint8_t ci_adv_len; + uint8_t name_len; +#endif /* First check if any instance is already active */ if(ble_gap_ext_adv_active(instance)) { @@ -124,6 +148,20 @@ ext_bleprph_advertise(void) /* in this case only scan response is allowed */ +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + name_len = strlen(device_name); + memset(ci_adv_data, 0, sizeof(ci_adv_data)); + ci_adv_data[0] = name_len + 1; + ci_adv_data[1] = BLE_HS_ADV_TYPE_COMP_NAME; + memcpy(&ci_adv_data[2], device_name, name_len); + ci_adv_len = 2 + name_len; + + data = os_msys_get_pkthdr(ci_adv_len, 0); + assert(data); + + rc = os_mbuf_append(data, ci_adv_data, ci_adv_len); + assert(rc == 0); +#else /* get mbuf for scan rsp data */ data = os_msys_get_pkthdr(sizeof(ext_adv_pattern_1), 0); assert(data); @@ -131,6 +169,7 @@ ext_bleprph_advertise(void) /* fill mbuf with scan rsp data */ rc = os_mbuf_append(data, ext_adv_pattern_1, sizeof(ext_adv_pattern_1)); assert(rc == 0); +#endif rc = ble_gap_ext_adv_set_data(instance, data); assert (rc == 0); @@ -150,9 +189,6 @@ bleprph_advertise(void) { struct ble_gap_adv_params adv_params; struct ble_hs_adv_fields fields; -#if CONFIG_BT_NIMBLE_GAP_SERVICE - const char *name; -#endif int rc; /** @@ -180,18 +216,19 @@ bleprph_advertise(void) fields.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO; #if CONFIG_BT_NIMBLE_GAP_SERVICE - name = ble_svc_gap_device_name(); - fields.name = (uint8_t *)name; - fields.name_len = strlen(name); + fields.name = (uint8_t *)device_name; + fields.name_len = strlen(device_name); fields.name_is_complete = 1; #endif +#if !(CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID) static const ble_uuid16_t adv_uuids16[] = { BLE_UUID16_INIT(GATT_SVR_SVC_ALERT_UUID) }; fields.uuids16 = adv_uuids16; fields.num_uuids16 = 1; fields.uuids16_is_complete = 1; +#endif rc = ble_gap_adv_set_fields(&fields); if (rc != 0) { @@ -265,6 +302,11 @@ bleprph_gap_event(struct ble_gap_event *event, void *arg) rc = ble_gap_conn_find(event->connect.conn_handle, &desc); assert(rc == 0); bleprph_print_conn_desc(&desc); + ESP_LOGI(tag, "Connected, conn_handle %d, remote %02x:%02x:%02x:%02x:%02x:%02x", + event->connect.conn_handle, + desc.peer_ota_addr.val[5], desc.peer_ota_addr.val[4], + desc.peer_ota_addr.val[3], desc.peer_ota_addr.val[2], + desc.peer_ota_addr.val[1], desc.peer_ota_addr.val[0]); } MODLOG_DFLT(INFO, "\n"); @@ -632,8 +674,15 @@ app_main(void) #endif #if CONFIG_BT_NIMBLE_GAP_SERVICE +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + strncpy(device_name, esp_bleprph_get_example_name(), sizeof(device_name) - 1); + device_name[sizeof(device_name) - 1] = '\0'; + ESP_LOGI(tag, "DeviceName:%s, CIID:%02X, PipelineID:%05X, ChipID:%02X", + device_name, CONFIG_EXAMPLE_CI_ID, CONFIG_EXAMPLE_CI_PIPELINE_ID, + CONFIG_IDF_FIRMWARE_CHIP_ID); +#endif /* Set the default device name. */ - rc = ble_svc_gap_device_name_set("nimble-bleprph"); + rc = ble_svc_gap_device_name_set(device_name); assert(rc == 0); #endif diff --git a/examples/bluetooth/nimble/bleprph/sdkconfig.ci.bleprph_esp32c2_xtal26m b/examples/bluetooth/nimble/bleprph/sdkconfig.ci.bleprph_esp32c2_xtal26m new file mode 100644 index 00000000000..1e0afd41560 --- /dev/null +++ b/examples/bluetooth/nimble/bleprph/sdkconfig.ci.bleprph_esp32c2_xtal26m @@ -0,0 +1,7 @@ +CONFIG_EXAMPLE_CI_ID=39 +CONFIG_IDF_TARGET="esp32c2" +CONFIG_XTAL_FREQ_26=y +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} +CONFIG_EXAMPLE_EXTENDED_ADV=n +CONFIG_EXAMPLE_ENCRYPTION=n +CONFIG_BT_NIMBLE_EXT_ADV=n diff --git a/examples/bluetooth/nimble/bleprph/sdkconfig.ci.name b/examples/bluetooth/nimble/bleprph/sdkconfig.ci.name new file mode 100644 index 00000000000..a282509a498 --- /dev/null +++ b/examples/bluetooth/nimble/bleprph/sdkconfig.ci.name @@ -0,0 +1,5 @@ +CONFIG_EXAMPLE_CI_ID=39 +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} +CONFIG_EXAMPLE_EXTENDED_ADV=n +CONFIG_EXAMPLE_ENCRYPTION=n +CONFIG_BT_NIMBLE_EXT_ADV=n diff --git a/examples/bluetooth/nimble/pytest_nimble_test.py b/examples/bluetooth/nimble/pytest_nimble_test.py index c2144b7314b..f32225dfe38 100644 --- a/examples/bluetooth/nimble/pytest_nimble_test.py +++ b/examples/bluetooth/nimble/pytest_nimble_test.py @@ -28,17 +28,16 @@ CUR_DIR = Path(__file__).parent.resolve() ['esp32c6', 'esp32h2', 'esp32c3', 'esp32s3', 'esp32c5', 'esp32c61', 'esp32', 'esp32h4'], indirect=['target'], ) -@pytest.mark.temp_skip_ci(targets=['esp32s31'], reason='lack of runners') def test_power_save_conn(app_path: str, dut: tuple[IdfDut, IdfDut]) -> None: peripheral = dut[0] central = dut[1] - peripheral.expect('NimBLE_BLE_PRPH: BLE Host Task Started', timeout=30) - central.expect('NimBLE_BLE_CENT: BLE Host Task Started', timeout=30) - peripheral.expect('Returned from app_main()', timeout=30) - central.expect('Returned from app_main()', timeout=30) - central.expect('Connection established', timeout=30) - peripheral.expect('connection established; status=0', timeout=30) + peripheral.expect_exact('NimBLE_BLE_PRPH: BLE Host Task Started', timeout=30) + central.expect_exact('NimBLE_BLE_CENT: BLE Host Task Started', timeout=30) + peripheral.expect_exact('Returned from app_main()', timeout=30) + central.expect_exact('Returned from app_main()', timeout=30) + central.expect_exact('Connection established', timeout=30) + peripheral.expect_exact('connection established; status=0', timeout=30) output = peripheral.expect(pexpect.TIMEOUT, timeout=30) assert 'rst:' not in str(output) and 'boot:' not in str(output) @@ -63,12 +62,12 @@ def test_power_save_conn_esp32c2_26mhz(dut: tuple[IdfDut, IdfDut]) -> None: peripheral = dut[0] central = dut[1] - peripheral.expect('NimBLE_BLE_PRPH: BLE Host Task Started', timeout=5) - central.expect('NimBLE_BLE_CENT: BLE Host Task Started', timeout=5) - peripheral.expect('Returned from app_main()', timeout=5) - central.expect('Returned from app_main()', timeout=5) - central.expect('Connection established', timeout=30) - peripheral.expect('connection established; status=0', timeout=30) + peripheral.expect_exact('NimBLE_BLE_PRPH: BLE Host Task Started', timeout=5) + central.expect_exact('NimBLE_BLE_CENT: BLE Host Task Started', timeout=5) + peripheral.expect_exact('Returned from app_main()', timeout=5) + central.expect_exact('Returned from app_main()', timeout=5) + central.expect_exact('Connection established', timeout=30) + peripheral.expect_exact('connection established; status=0', timeout=30) output = peripheral.expect(pexpect.TIMEOUT, timeout=30) assert 'rst:' not in str(output) and 'boot:' not in str(output) @@ -94,12 +93,12 @@ def test_power_save_conn_esp32c2_rev2(dut: tuple[IdfDut, IdfDut]) -> None: peripheral = dut[0] central = dut[1] - peripheral.expect('NimBLE_BLE_PRPH: BLE Host Task Started', timeout=5) - central.expect('NimBLE_BLE_CENT: BLE Host Task Started', timeout=5) - peripheral.expect('Returned from app_main()', timeout=5) - central.expect('Returned from app_main()', timeout=5) - central.expect('Connection established', timeout=30) - peripheral.expect('connection established; status=0', timeout=30) + peripheral.expect_exact('NimBLE_BLE_PRPH: BLE Host Task Started', timeout=5) + central.expect_exact('NimBLE_BLE_CENT: BLE Host Task Started', timeout=5) + peripheral.expect_exact('Returned from app_main()', timeout=5) + central.expect_exact('Returned from app_main()', timeout=5) + central.expect_exact('Connection established', timeout=30) + peripheral.expect_exact('connection established; status=0', timeout=30) output = peripheral.expect(pexpect.TIMEOUT, timeout=30) assert 'rst:' not in str(output) and 'boot:' not in str(output) @@ -123,11 +122,1764 @@ def test_power_save_conn_esp32c3_rev1(dut: tuple[IdfDut, IdfDut]) -> None: peripheral = dut[0] central = dut[1] - peripheral.expect('NimBLE_BLE_PRPH: BLE Host Task Started', timeout=5) - central.expect('NimBLE_BLE_CENT: BLE Host Task Started', timeout=5) - peripheral.expect('Returned from app_main()', timeout=5) - central.expect('Returned from app_main()', timeout=5) - central.expect('Connection established', timeout=30) - peripheral.expect('connection established; status=0', timeout=30) + peripheral.expect_exact('NimBLE_BLE_PRPH: BLE Host Task Started', timeout=5) + central.expect_exact('NimBLE_BLE_CENT: BLE Host Task Started', timeout=5) + peripheral.expect_exact('Returned from app_main()', timeout=5) + central.expect_exact('Returned from app_main()', timeout=5) + central.expect_exact('Connection established', timeout=30) + peripheral.expect_exact('connection established; status=0', timeout=30) output = peripheral.expect(pexpect.TIMEOUT, timeout=30) assert 'rst:' not in str(output) and 'boot:' not in str(output) + + +CTE_PERIODIC_ADV_SYNC_APP_PATH = ( + f'{str(CUR_DIR / "ble_cte" / "ble_periodic_adv_with_cte")}|' + f'{str(CUR_DIR / "ble_cte" / "ble_periodic_sync_with_cte")}' +) +NIMBLE_CTE_TARGETS = ['esp32h2', 'esp32c5', 'esp32c61', 'esp32s31', 'esp32h4'] + + +def _run_nimble_periodic_adv_sync_with_cte_func(dut: tuple[IdfDut, IdfDut]) -> None: + adv = dut[0] + sync = dut[1] + + adv.expect_exact('DIRECTION_FINDING Example Periodic Adv AOA Mode', timeout=30) + adv.expect_exact('BLE Host Task Started', timeout=30) + sync.expect_exact('BLE Host Task Started', timeout=30) + + adv_addr = adv.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') + name = adv.expect(r'DeviceName:(.+?)\,', timeout=30).group(1).decode('utf8') + adv.expect_exact('Instance 0 started (periodic)', timeout=30) + + sync.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30) + peer_name = sync.expect(r'DeviceName:(.+?)\,', timeout=30).group(1).decode('utf8') + assert peer_name == name, ( + 'advertiser and synchronizer must use the same CI device name from ' + 'esp_ble_cte_get_example_name(); mismatch means sdkconfig.ci or CI ID is wrong' + ) + sync.expect_exact('Receive CTE Antenna Pattern Info:', timeout=30) + + sync.expect_exact('Started periodic sync with device', timeout=60) + sync.expect_exact('Periodic Sync Established', timeout=60) + + found_addr = ( + sync.expect( + r'Adv Addr: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', + timeout=30, + ) + .group(1) + .decode('utf8') + ) + assert found_addr.lower() == adv_addr.lower(), ( + 'periodic sync must lock to the advertiser board MAC, not another periodic advertiser' + ) + + sync.expect_exact('IQ Report | Sync Handle:', timeout=60) + + adv_output = adv.expect(pexpect.TIMEOUT, timeout=10) + sync_output = sync.expect(pexpect.TIMEOUT, timeout=10) + assert 'rst:' not in str(adv_output) and 'boot:' not in str(adv_output) + assert 'rst:' not in str(sync_output) and 'boot:' not in str(sync_output) + assert 'Sync Lost' not in str(sync_output) + + +# Case 4: nimble periodic adv/sync with CTE test +# EXAMPLE_CI_ID=25 +@pytest.mark.temp_skip_ci(targets=['esp32h4'], reason='lack of runner # TODO: IDFCI-11112') +@pytest.mark.two_duts +@pytest.mark.parametrize( + 'count, app_path, config, erase_nvs', + [ + ( + 2, + CTE_PERIODIC_ADV_SYNC_APP_PATH, + 'name', + 'y', + ), + ], + indirect=True, +) +@idf_parametrize('target', NIMBLE_CTE_TARGETS, indirect=['target']) +def test_nimble_periodic_adv_sync_with_cte_func(app_path: str, dut: tuple[IdfDut, IdfDut]) -> None: + _run_nimble_periodic_adv_sync_with_cte_func(dut) + + +CTS_APP_PATH = f'{str(CUR_DIR / "ble_cts" / "cts_prph")}|{str(CUR_DIR / "ble_cts" / "cts_cent")}' +NIMBLE_CTS_TARGETS = [ + 'esp32', + 'esp32c3', + 'esp32c6', + 'esp32c5', + 'esp32h2', + 'esp32s3', + 'esp32c61', + 'esp32h4', + 'esp32s31', +] + + +def _run_nimble_cts_func(dut: tuple[IdfDut, IdfDut]) -> None: + peripheral = dut[0] + central = dut[1] + + peripheral_addr = ( + peripheral.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') + ) + central_addr = ( + central.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') + ) + name = peripheral.expect(r'DeviceName:(.+?)\,', timeout=30).group(1).decode('utf8') + peer_name = central.expect(r'DeviceName:(.+?)\,', timeout=30).group(1).decode('utf8') + assert peer_name == name, ( + 'central and peripheral must use the same CI device name from ' + 'esp_ble_cts_get_example_name(); mismatch means sdkconfig.ci or CI ID is wrong' + ) + + peripheral.expect_exact('NimBLE_CTS_PRPH: BLE Host Task Started', timeout=30) + central.expect_exact('NimBLE_CTS_CENT: BLE Host Task Started', timeout=30) + + found_addr = ( + central.expect( + rf'Found device: (([0-9a-fA-F]{{2}}:){{5}}[0-9a-fA-F]{{2}}), name: {name}', + timeout=60, + ) + .group(1) + .decode('utf8') + ) + assert found_addr.lower() == peripheral_addr.lower(), ( + 'scan must report the peripheral board MAC, not another advertiser with the same CI name' + ) + + connected_remote = ( + central.expect( + r'Connected, conn_handle \d+, remote (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', + timeout=30, + ) + .group(1) + .decode('utf8') + ) + assert connected_remote.lower() == peripheral_addr.lower(), ( + 'central must connect to the peripheral board MAC, not a colliding device in RF environment' + ) + peripheral_remote = ( + peripheral.expect( + r'Connected, conn_handle \d+, remote (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', + timeout=30, + ) + .group(1) + .decode('utf8') + ) + assert peripheral_remote.lower() == central_addr.lower(), 'peripheral must see central board MAC as connection peer' + + central.expect_exact('Service discovery complete; status=0', timeout=60) + central.expect_exact('Read Current time complete; status=0', timeout=30) + central.expect_exact('Date :', timeout=30) + + out_central = central.expect(pexpect.TIMEOUT, timeout=10) + out_peripheral = peripheral.expect(pexpect.TIMEOUT, timeout=10) + assert 'rst:' not in str(out_central) and 'boot:' not in str(out_central) + assert 'rst:' not in str(out_peripheral) and 'boot:' not in str(out_peripheral) + assert 'disconnect' not in str(out_central).lower() + assert 'disconnect' not in str(out_peripheral).lower() + + +# Case 5: nimble CTS peripheral/central test +# EXAMPLE_CI_ID=26 +@pytest.mark.temp_skip_ci(targets=['esp32h4'], reason='lack of runner # TODO: IDFCI-11112') +@pytest.mark.two_duts +@pytest.mark.parametrize( + 'count, app_path, config, erase_nvs', + [ + ( + 2, + CTS_APP_PATH, + 'name', + 'y', + ), + ], + indirect=True, +) +@idf_parametrize('target', NIMBLE_CTS_TARGETS, indirect=['target']) +def test_nimble_cts_func(app_path: str, dut: tuple[IdfDut, IdfDut]) -> None: + _run_nimble_cts_func(dut) + + +# Case 6: nimble CTS test for ESP32C2 26MHz +# EXAMPLE_CI_ID=26 +@pytest.mark.two_duts +@pytest.mark.xtal_26mhz +@pytest.mark.parametrize( + 'count, target, baud, app_path, config, erase_nvs', + [ + ( + 2, + 'esp32c2|esp32c2', + '74880', + CTS_APP_PATH, + 'esp32c2_xtal26m', + 'y', + ), + ], + indirect=True, +) +def test_nimble_cts_func_esp32c2_26mhz(app_path: str, dut: tuple[IdfDut, IdfDut]) -> None: + _run_nimble_cts_func(dut) + + +HTP_APP_PATH = f'{str(CUR_DIR / "ble_htp" / "htp_prph")}|{str(CUR_DIR / "ble_htp" / "htp_cent")}' +NIMBLE_HTP_TARGETS = [ + 'esp32', + 'esp32c3', + 'esp32c6', + 'esp32c5', + 'esp32h2', + 'esp32s3', + 'esp32c61', + 'esp32h4', + 'esp32s31', +] + + +def _run_nimble_htp_func(dut: tuple[IdfDut, IdfDut]) -> None: + peripheral = dut[0] + central = dut[1] + + peripheral_addr = ( + peripheral.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') + ) + central_addr = ( + central.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') + ) + name = peripheral.expect(r'DeviceName:(.+?)\,', timeout=30).group(1).decode('utf8') + peer_name = central.expect(r'DeviceName:(.+?)\,', timeout=30).group(1).decode('utf8') + assert peer_name == name, ( + 'central and peripheral must use the same CI device name from ' + 'esp_ble_htp_get_example_name(); mismatch means sdkconfig.ci or CI ID is wrong' + ) + + peripheral.expect_exact('NimBLE_HTP_PRPH: BLE Host Task Started', timeout=30) + central.expect_exact('NimBLE_HTP_CENT: BLE Host Task Started', timeout=30) + + found_addr = ( + central.expect( + rf'Found device: (([0-9a-fA-F]{{2}}:){{5}}[0-9a-fA-F]{{2}}), name: {name}', + timeout=60, + ) + .group(1) + .decode('utf8') + ) + assert found_addr.lower() == peripheral_addr.lower(), ( + 'scan must report the peripheral board MAC, not another advertiser with the same CI name' + ) + + connected_remote = ( + central.expect( + r'Connected, conn_handle \d+, remote (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', + timeout=30, + ) + .group(1) + .decode('utf8') + ) + assert connected_remote.lower() == peripheral_addr.lower(), ( + 'central must connect to the peripheral board MAC, not a colliding device in RF environment' + ) + peripheral_remote = ( + peripheral.expect( + r'Connected, conn_handle \d+, remote (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', + timeout=30, + ) + .group(1) + .decode('utf8') + ) + assert peripheral_remote.lower() == central_addr.lower(), 'peripheral must see central board MAC as connection peer' + + central.expect_exact('Service discovery complete; status=0', timeout=60) + central.expect_exact('Read temperature type char completed; status=0', timeout=30) + central.expect_exact('Write to measurement interval char completed; status=0', timeout=30) + central.expect_exact('Subscribe to temperature measurement char completed; status=0', timeout=30) + central.expect_exact('Subscribe to intermediate temperature char completed; status=0', timeout=30) + + out_central = central.expect(pexpect.TIMEOUT, timeout=10) + out_peripheral = peripheral.expect(pexpect.TIMEOUT, timeout=10) + assert 'rst:' not in str(out_central) and 'boot:' not in str(out_central) + assert 'rst:' not in str(out_peripheral) and 'boot:' not in str(out_peripheral) + assert 'disconnect' not in str(out_central).lower() + assert 'disconnect' not in str(out_peripheral).lower() + + +# Case 7: nimble HTP peripheral/central test +# EXAMPLE_CI_ID=27 +@pytest.mark.temp_skip_ci(targets=['esp32h4'], reason='lack of runner # TODO: IDFCI-11112') +@pytest.mark.two_duts +@pytest.mark.parametrize( + 'count, app_path, config, erase_nvs', + [ + ( + 2, + HTP_APP_PATH, + 'name', + 'y', + ), + ], + indirect=True, +) +@idf_parametrize('target', NIMBLE_HTP_TARGETS, indirect=['target']) +def test_nimble_htp_func(app_path: str, dut: tuple[IdfDut, IdfDut]) -> None: + _run_nimble_htp_func(dut) + + +# Case 8: nimble HTP test for ESP32C2 26MHz +# EXAMPLE_CI_ID=27 +@pytest.mark.two_duts +@pytest.mark.xtal_26mhz +@pytest.mark.parametrize( + 'count, target, baud, app_path, config, erase_nvs', + [ + ( + 2, + 'esp32c2|esp32c2', + '74880', + HTP_APP_PATH, + 'esp32c2_xtal26m', + 'y', + ), + ], + indirect=True, +) +def test_nimble_htp_func_esp32c2_26mhz(app_path: str, dut: tuple[IdfDut, IdfDut]) -> None: + _run_nimble_htp_func(dut) + + +SPP_APP_PATH = f'{str(CUR_DIR / "ble_spp" / "spp_server")}|{str(CUR_DIR / "ble_spp" / "spp_client")}' +NIMBLE_SPP_TARGETS = [ + 'esp32', + 'esp32c3', + 'esp32c6', + 'esp32c5', + 'esp32h2', + 'esp32s3', + 'esp32c61', + 'esp32h4', + 'esp32s31', +] + + +def _run_nimble_spp_func(dut: tuple[IdfDut, IdfDut]) -> None: + server = dut[0] + client = dut[1] + + server_addr = ( + server.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') + ) + client_addr = ( + client.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') + ) + name = server.expect(r'DeviceName:(.+?)\,', timeout=30).group(1).decode('utf8') + peer_name = client.expect(r'DeviceName:(.+?)\,', timeout=30).group(1).decode('utf8') + assert peer_name == name, ( + 'client and server must use the same CI device name from ' + 'esp_ble_spp_get_example_name(); mismatch means sdkconfig.ci or CI ID is wrong' + ) + + server.expect_exact('NimBLE_SPP_SERVER: BLE Host Task Started', timeout=30) + client.expect_exact('NimBLE_SPP_CLIENT: BLE Host Task Started', timeout=30) + + found_addr = ( + client.expect( + rf'Found device: (([0-9a-fA-F]{{2}}:){{5}}[0-9a-fA-F]{{2}}), name: {name}', + timeout=60, + ) + .group(1) + .decode('utf8') + ) + assert found_addr.lower() == server_addr.lower(), ( + 'scan must report the server board MAC, not another advertiser with the same CI name' + ) + + connected_remote = ( + client.expect( + r'Connected, conn_handle \d+, remote (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', + timeout=30, + ) + .group(1) + .decode('utf8') + ) + assert connected_remote.lower() == server_addr.lower(), ( + 'client must connect to the server board MAC, not a colliding device in RF environment' + ) + server_remote = ( + server.expect( + r'Connected, conn_handle \d+, remote (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', + timeout=30, + ) + .group(1) + .decode('utf8') + ) + assert server_remote.lower() == client_addr.lower(), 'server must see client board MAC as connection peer' + + client.expect_exact('Service discovery complete; status=0', timeout=60) + client.expect(r'attribute_handle [0-9a-fA-F]+', timeout=30) + server.expect_exact('subscribe event; conn_handle=', timeout=30) + + out_client = client.expect(pexpect.TIMEOUT, timeout=10) + out_server = server.expect(pexpect.TIMEOUT, timeout=10) + assert 'rst:' not in str(out_client) and 'boot:' not in str(out_client) + assert 'rst:' not in str(out_server) and 'boot:' not in str(out_server) + assert 'disconnect' not in str(out_client).lower() + assert 'disconnect' not in str(out_server).lower() + + +# Case 9: nimble SPP server/client test +# EXAMPLE_CI_ID=28 +@pytest.mark.temp_skip_ci(targets=['esp32h4'], reason='lack of runner # TODO: IDFCI-11112') +@pytest.mark.two_duts +@pytest.mark.parametrize( + 'count, app_path, config, erase_nvs', + [ + ( + 2, + SPP_APP_PATH, + 'name', + 'y', + ), + ], + indirect=True, +) +@idf_parametrize('target', NIMBLE_SPP_TARGETS, indirect=['target']) +def test_nimble_spp_func(app_path: str, dut: tuple[IdfDut, IdfDut]) -> None: + _run_nimble_spp_func(dut) + + +# Case 10: nimble SPP test for ESP32C2 26MHz +# EXAMPLE_CI_ID=28 +@pytest.mark.two_duts +@pytest.mark.xtal_26mhz +@pytest.mark.parametrize( + 'count, target, baud, app_path, config, erase_nvs', + [ + ( + 2, + 'esp32c2|esp32c2', + '74880', + SPP_APP_PATH, + 'esp32c2_xtal26m', + 'y', + ), + ], + indirect=True, +) +def test_nimble_spp_func_esp32c2_26mhz(app_path: str, dut: tuple[IdfDut, IdfDut]) -> None: + _run_nimble_spp_func(dut) + + +MAC_PATTERN = r'(([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})' +MULTI_CONN_APP_PATH = ( + f'{str(CUR_DIR / "ble_multi_conn" / "ble_multi_conn_prph")}|' + f'{str(CUR_DIR / "ble_multi_conn" / "ble_multi_conn_cent")}' +) +NIMBLE_MULTI_CONN_TARGETS = ['esp32c5', 'esp32c6', 'esp32c61', 'esp32h2', 'esp32h21', 'esp32s31'] + + +def _run_nimble_multi_conn_func(dut: tuple[IdfDut, IdfDut]) -> None: + prph_dut, cent_dut = dut[0], dut[1] + + prph_dut.expect(r'Bluetooth MAC: ' + MAC_PATTERN, timeout=30) + cent_dut.expect(r'Bluetooth MAC: ' + MAC_PATTERN, timeout=30) + name = prph_dut.expect(r'DeviceName:(.+?)\,', timeout=30).group(1).decode('utf8') + peer_name = cent_dut.expect(r'DeviceName:(.+?)\,', timeout=30).group(1).decode('utf8') + assert peer_name == name, ( + 'central and peripheral must use the same CI device name from ' + 'esp_ble_multi_conn_get_example_name(); mismatch means sdkconfig.ci or CI ID is wrong' + ) + + max_cfg = int( + prph_dut.expect( + r'ESP_MULTI_CONN_PRPH: CONFIG_BT_NIMBLE_MAX_CONNECTIONS=(\d+)\.', + timeout=30, + ) + .group(1) + .decode('utf8') + ) + assert max_cfg >= 1, 'peripheral MAX_CONNECTIONS must be at least 1 for multi-conn test' + + prph_dut.expect_exact('ESP_MULTI_CONN_PRPH: BLE Host Task Started', timeout=30) + cent_dut.expect_exact('ESP_MULTI_CONN_CENT: BLE Host Task Started', timeout=30) + + for i in range(1, max_cfg + 1): + prph_addr = ( + prph_dut.expect( + r'ESP_MULTI_CONN_PRPH: Started adv, Device Address ' + MAC_PATTERN + r'.', + timeout=30, + ) + .group(1) + .decode('utf8') + ) + + found = ( + cent_dut.expect( + r'ESP_MULTI_CONN_CENT: Found device: addr: ' + MAC_PATTERN + rf', name: {name}', + timeout=90, + ) + .group(1) + .decode('utf8') + ) + assert found.lower() == prph_addr.lower(), ( + f'Round {i}: scan must report the peripheral adv address, ' + f'cent found {found.lower()} != prph adv {prph_addr.lower()}' + ) + + create = cent_dut.expect( + r'ESP_MULTI_CONN_CENT: Create connection\. -> peer addr ' + MAC_PATTERN, + timeout=30, + ) + assert create.group(1).decode('utf8').lower() == prph_addr.lower(), ( + f'Round {i}: central must connect to the peripheral adv address' + ) + prph_dut.expect_exact( + 'ESP_MULTI_CONN_PRPH: advertisement completed. Reason=0.', + timeout=30, + ) + cent_dut.expect( + rf'ESP_MULTI_CONN_CENT: Connection established\. Handle:\d+, Total:{i}\b', + timeout=120, + ) + prph_dut.expect( + rf'ESP_MULTI_CONN_PRPH: Connection established\. Handle:\d+\. Total:{i}\b', + timeout=60, + ) + + prph_output = prph_dut.expect(pexpect.TIMEOUT, timeout=5) + cent_output = cent_dut.expect(pexpect.TIMEOUT, timeout=5) + assert 'rst:' not in str(prph_output) and 'boot:' not in str(prph_output) + assert 'rst:' not in str(cent_output) and 'boot:' not in str(cent_output) + assert 'disconnect' not in str(prph_output).lower() + assert 'disconnect' not in str(cent_output).lower() + + +# Case 11: NimBLE multi-conn peripheral and central +# EXAMPLE_CI_ID=29 +@pytest.mark.temp_skip_ci(targets=['esp32h21'], reason='lack of runner') +@pytest.mark.two_duts +@pytest.mark.parametrize( + 'count, app_path, config, erase_nvs', + [ + ( + 2, + MULTI_CONN_APP_PATH, + 'name', + 'y', + ), + ], + indirect=True, +) +@idf_parametrize('target', NIMBLE_MULTI_CONN_TARGETS, indirect=['target']) +def test_nimble_multi_conn_prph_cent(app_path: str, dut: tuple[IdfDut, IdfDut]) -> None: + _run_nimble_multi_conn_func(dut) + + +PHY_APP_PATH = f'{str(CUR_DIR / "ble_phy" / "phy_prph")}|{str(CUR_DIR / "ble_phy" / "phy_cent")}' +NIMBLE_PHY_TARGETS = [ + 'esp32c3', + 'esp32c6', + 'esp32c5', + 'esp32h2', + 'esp32s3', + 'esp32c61', + 'esp32h4', + 'esp32s31', +] + + +def _run_nimble_phy_prph_cent_func(dut: tuple[IdfDut, IdfDut]) -> None: + prph_dut, cent_dut = dut[0], dut[1] + + def _cent_gatt_read_write_terminate() -> None: + cent_dut.expect_exact('NimBLE: GATT procedure initiated: discover all services', timeout=30) + cent_dut.expect_exact('NimBLE: Service discovery complete; status=0', timeout=60) + cent_dut.expect_exact('NimBLE: Read complete; status=', timeout=30) + cent_dut.expect_exact('NimBLE: Write complete; status=', timeout=30) + cent_dut.expect_exact('NimBLE: GAP procedure initiated: terminate connection', timeout=30) + + def _prph_adv_then_conn() -> None: + prph_dut.expect_exact('NimBLE: advertise complete; reason=0', timeout=30) + prph_dut.expect_exact('NimBLE: connection established; status=0', timeout=30) + + def _disconnect_then_prph_re_adv() -> None: + prph_dut.expect_exact('NimBLE: disconnect;', timeout=30) + cent_dut.expect_exact('NimBLE: disconnect;', timeout=30) + prph_dut.expect_exact('NimBLE: GAP procedure initiated: extended advertise', timeout=30) + + prph_bt_mac = prph_dut.expect(r'Bluetooth MAC: ' + MAC_PATTERN, timeout=30).group(1).decode('utf8') + cent_bt_mac = cent_dut.expect(r'Bluetooth MAC: ' + MAC_PATTERN, timeout=30).group(1).decode('utf8') + assert prph_bt_mac.lower() != cent_bt_mac.lower(), ( + 'peripheral and central boards must have different Bluetooth MACs' + ) + + name = prph_dut.expect(r'DeviceName:(.+?)\,', timeout=30).group(1).decode('utf8') + peer_name = cent_dut.expect(r'DeviceName:(.+?)\,', timeout=30).group(1).decode('utf8') + assert peer_name == name, ( + 'central and peripheral must use the same CI device name from ' + 'esp_ble_phy_get_example_name(); mismatch means sdkconfig.ci or CI ID is wrong' + ) + + prph_dut.expect_exact('NimBLE_BLE_PHY_PRPH: BLE Host Task Started', timeout=30) + cent_dut.expect_exact('NimBLE_BLE_PHY_CENT: BLE Host Task Started', timeout=30) + prph_dut.expect_exact('NimBLE: Default LE PHY set successfully', timeout=30) + prph_dut.expect_exact('NimBLE: GAP procedure initiated: extended advertise', timeout=30) + cent_dut.expect_exact('NimBLE: Default LE PHY set successfully', timeout=30) + cent_dut.expect_exact('NimBLE: GAP procedure initiated: extended discovery', timeout=30) + + found = cent_dut.expect( + r'NimBLE_BLE_PHY_CENT: Found device: addr: ' + MAC_PATTERN + rf', name: {name}', + timeout=90, + ) + found_addr = found.group(1).decode('utf8') + assert found_addr.lower() == prph_bt_mac.lower(), ( + 'scan must report the peripheral board identity address, not another advertiser' + ) + + # 1M + cent_dut.expect_exact('NimBLE: Attempting to connect to :', timeout=30) + cent_dut.expect_exact('NimBLE: GAP procedure initiated: extended connect', timeout=30) + _prph_adv_then_conn() + cent_dut.expect_exact('Connection established on 1M Phy', timeout=90) + _cent_gatt_read_write_terminate() + + # 2M + _disconnect_then_prph_re_adv() + cent_dut.expect_exact('Attempting to initiate connection on 2M PHY', timeout=60) + cent_dut.expect_exact('NimBLE: GAP procedure initiated: extended connect', timeout=30) + _prph_adv_then_conn() + cent_dut.expect_exact('Connection established on 2M Phy', timeout=90) + _cent_gatt_read_write_terminate() + + # Coded + _disconnect_then_prph_re_adv() + cent_dut.expect_exact('Attempting to initiate connection on Coded PHY', timeout=60) + cent_dut.expect_exact('NimBLE: GAP procedure initiated: extended connect', timeout=30) + _prph_adv_then_conn() + cent_dut.expect_exact('Connection established on Coded Phy', timeout=90) + _cent_gatt_read_write_terminate() + + prph_dut.expect_exact('NimBLE: disconnect;', timeout=30) + cent_dut.expect_exact('NimBLE: disconnect;', timeout=30) + + prph_output = prph_dut.expect(pexpect.TIMEOUT, timeout=5) + cent_output = cent_dut.expect(pexpect.TIMEOUT, timeout=5) + assert 'rst:' not in str(prph_output) and 'boot:' not in str(prph_output) + assert 'rst:' not in str(cent_output) and 'boot:' not in str(cent_output) + + +# Case 12: NimBLE PHY peripheral/central test +# EXAMPLE_CI_ID=30 +@pytest.mark.temp_skip_ci(targets=['esp32h4'], reason='lack of runner # TODO: IDFCI-11112') +@pytest.mark.two_duts +@pytest.mark.parametrize( + 'count, app_path, config, erase_nvs', + [ + ( + 2, + PHY_APP_PATH, + 'name', + 'y', + ), + ], + indirect=True, +) +@idf_parametrize('target', NIMBLE_PHY_TARGETS, indirect=['target']) +def test_nimble_phy_prph_cent(app_path: str, dut: tuple[IdfDut, IdfDut]) -> None: + _run_nimble_phy_prph_cent_func(dut) + + +# Case 13: NimBLE PHY test for ESP32C2 26MHz +# EXAMPLE_CI_ID=30 +@pytest.mark.two_duts +@pytest.mark.xtal_26mhz +@pytest.mark.parametrize( + 'count, target, baud, app_path, config, erase_nvs', + [ + ( + 2, + 'esp32c2|esp32c2', + '74880', + PHY_APP_PATH, + 'esp32c2_xtal26m', + 'y', + ), + ], + indirect=True, +) +def test_esp32c2_26mhz_nimble_phy_prph_cent(app_path: str, dut: tuple[IdfDut, IdfDut]) -> None: + _run_nimble_phy_prph_cent_func(dut) + + +PAWR_CONN_APP_PATH = ( + f'{str(CUR_DIR / "ble_pawr_adv_conn" / "ble_pawr_adv_conn")}' + f'|{str(CUR_DIR / "ble_pawr_adv_conn" / "ble_pawr_sync_conn")}' +) +NIMBLE_PAWR_CONN_TARGETS = [ + 'esp32h2', + 'esp32c6', + 'esp32c5', + 'esp32c61', + 'esp32s31', + 'esp32h21', + 'esp32h4', +] + + +def _run_nimble_pawr_adv_conn_sync_func(dut: tuple[IdfDut, IdfDut]) -> None: + adv_dut, sync_dut = dut[0], dut[1] + + adv_bt_mac = adv_dut.expect(r'Bluetooth MAC: ' + MAC_PATTERN, timeout=30).group(1).decode('utf8') + sync_bt_mac = sync_dut.expect(r'Bluetooth MAC: ' + MAC_PATTERN, timeout=30).group(1).decode('utf8') + assert adv_bt_mac.lower() != sync_bt_mac.lower(), ( + 'advertiser and synchronizer boards must have different Bluetooth MACs' + ) + + name = adv_dut.expect(r'DeviceName:(.+?)\,', timeout=30).group(1).decode('utf8') + peer_name = sync_dut.expect(r'DeviceName:(.+?)\,', timeout=30).group(1).decode('utf8') + assert peer_name == name, ( + 'advertiser and synchronizer must use the same CI device name from ' + 'esp_ble_pawr_conn_get_example_name(); mismatch means sdkconfig.ci or CI ID is wrong' + ) + + adv_dut.expect_exact('NimBLE_BLE_PAwR_CONN: BLE Host Task Started', timeout=30) + sync_dut.expect_exact('NimBLE_BLE_PAwR_CONN: BLE Host Task Started', timeout=30) + adv_dut.expect_exact('NimBLE_BLE_PAwR_CONN: instance 0 started (periodic)', timeout=30) + + found = sync_dut.expect( + r'NimBLE_BLE_PAwR_CONN: Found device: addr: ' + MAC_PATTERN + rf', name: {name}', + timeout=90, + ) + found_addr = found.group(1).decode('utf8') + assert found_addr.lower() == adv_bt_mac.lower(), ( + 'scan must report the advertiser board identity address, not another advertiser' + ) + + sync_dut.expect_exact('NimBLE_BLE_PAwR_CONN: Create sync', timeout=60) + sync_dut.expect_exact('NimBLE_BLE_PAwR_CONN: [Periodic Sync Established] sync handle:', timeout=60) + sync_dut.expect_exact('NimBLE_BLE_PAwR_CONN: [Subevent Sync OK] sync handle:', timeout=30) + + sync_dut.expect_exact('NimBLE_BLE_PAwR_CONN: [Periodic Adv Report] handle:', timeout=60) + sync_dut.expect_exact('NimBLE_BLE_PAwR_CONN: [RSP Data Set] sync handle:', timeout=60) + + adv_dut.expect_exact('NimBLE_BLE_PAwR_CONN: [Response] subevent:', timeout=90) + adv_dut.expect_exact('NimBLE_BLE_PAwR_CONN: Connection create sent, adv handle =', timeout=60) + + adv_dut.expect_exact('NimBLE_BLE_PAwR_CONN: [Connection established], conn_handle =', timeout=60) + sync_dut.expect_exact('NimBLE_BLE_PAwR_CONN: Connection established, conn_handle =', timeout=60) + + adv_peer = adv_dut.expect(r'peer_id_addr_type=\d+ peer_id_addr=' + MAC_PATTERN, timeout=30).group(1).decode('utf8') + assert adv_peer.lower() == sync_bt_mac.lower(), 'advertiser must see synchronizer board MAC as connection peer' + sync_peer = ( + sync_dut.expect(r'peer_id_addr_type=\d+ peer_id_addr=' + MAC_PATTERN, timeout=30).group(1).decode('utf8') + ) + assert sync_peer.lower() == adv_bt_mac.lower(), 'synchronizer must see advertiser board MAC as connection peer' + + adv_output = adv_dut.expect(pexpect.TIMEOUT, timeout=10) + sync_output = sync_dut.expect(pexpect.TIMEOUT, timeout=10) + assert 'rst:' not in str(adv_output) and 'boot:' not in str(adv_output) + assert 'rst:' not in str(sync_output) and 'boot:' not in str(sync_output) + assert 'Periodic Sync Lost' not in str(sync_output) + assert 'Disconnected' not in str(adv_output) + assert 'Disconnected' not in str(sync_output) + + +# Case 14: NimBLE PAwR advertiser_conn / synchronizer_conn test +# EXAMPLE_CI_ID=31 +@pytest.mark.temp_skip_ci(targets=['esp32h4'], reason='lack of runner # TODO: IDFCI-11112') +@pytest.mark.temp_skip_ci(targets=['esp32h21'], reason='lack of runner') +@pytest.mark.two_duts +@pytest.mark.parametrize( + 'count, app_path, config, erase_nvs', + [ + ( + 2, + PAWR_CONN_APP_PATH, + 'name', + 'y', + ), + ], + indirect=True, +) +@idf_parametrize('target', NIMBLE_PAWR_CONN_TARGETS, indirect=['target']) +def test_nimble_pawr_adv_conn_sync_func(app_path: str, dut: tuple[IdfDut, IdfDut]) -> None: + _run_nimble_pawr_adv_conn_sync_func(dut) + + +PAWR_ADV_APP_PATH = ( + f'{str(CUR_DIR / "ble_pawr_adv" / "ble_pawr_adv")}|{str(CUR_DIR / "ble_pawr_adv" / "ble_pawr_sync")}' +) +NIMBLE_PAWR_ADV_TARGETS = [ + 'esp32h2', + 'esp32c6', + 'esp32c5', + 'esp32c61', + 'esp32s31', + 'esp32h21', + 'esp32h4', +] + + +def _run_nimble_pawr_adv_sync_func(dut: tuple[IdfDut, IdfDut]) -> None: + adv_dut, sync_dut = dut[0], dut[1] + + adv_bt_mac = adv_dut.expect(r'Bluetooth MAC: ' + MAC_PATTERN, timeout=30).group(1).decode('utf8') + sync_bt_mac = sync_dut.expect(r'Bluetooth MAC: ' + MAC_PATTERN, timeout=30).group(1).decode('utf8') + assert adv_bt_mac.lower() != sync_bt_mac.lower(), ( + 'advertiser and synchronizer boards must have different Bluetooth MACs' + ) + + name = adv_dut.expect(r'DeviceName:(.+?)\,', timeout=30).group(1).decode('utf8') + peer_name = sync_dut.expect(r'DeviceName:(.+?)\,', timeout=30).group(1).decode('utf8') + assert peer_name == name, ( + 'advertiser and synchronizer must use the same CI device name from ' + 'esp_ble_pawr_get_example_name(); mismatch means sdkconfig.ci or CI ID is wrong' + ) + + adv_dut.expect_exact('NimBLE_BLE_PAwR: BLE Host Task Started', timeout=30) + sync_dut.expect_exact('NimBLE_BLE_PAwR: BLE Host Task Started', timeout=30) + adv_dut.expect_exact('NimBLE_BLE_PAwR: instance 0 started (periodic)', timeout=30) + adv_dut.expect_exact('NimBLE_BLE_PAwR: [Request] data:', timeout=60) + + found = sync_dut.expect( + r'NimBLE_BLE_PAwR: Found device: addr: ' + MAC_PATTERN + rf', name: {name}', + timeout=90, + ) + found_addr = found.group(1).decode('utf8') + assert found_addr.lower() == adv_bt_mac.lower(), ( + 'scan must report the advertiser board identity address, not another advertiser' + ) + + sync_dut.expect_exact('NimBLE_BLE_PAwR: Create sync', timeout=60) + sync_dut.expect_exact('NimBLE_BLE_PAwR: [Periodic Sync Established] sync handle:', timeout=60) + sync_dut.expect_exact('NimBLE_BLE_PAwR: [Subevent Sync OK] sync handle:', timeout=30) + + sync_dut.expect_exact('NimBLE_BLE_PAwR: [Periodic Adv Report] handle:', timeout=60) + sync_dut.expect_exact('NimBLE_BLE_PAwR: [RSP Data Set] sync handle:', timeout=60) + + adv_dut.expect_exact('NimBLE_BLE_PAwR: [Response] subevent:', timeout=90) + adv_dut.expect_exact('NimBLE_BLE_PAwR: data:', timeout=30) + + adv_output = adv_dut.expect(pexpect.TIMEOUT, timeout=10) + sync_output = sync_dut.expect(pexpect.TIMEOUT, timeout=10) + assert 'rst:' not in str(adv_output) and 'boot:' not in str(adv_output) + assert 'rst:' not in str(sync_output) and 'boot:' not in str(sync_output) + assert 'Periodic Sync Lost' not in str(sync_output) + + +# Case 15: NimBLE PAwR advertiser / synchronizer test +# EXAMPLE_CI_ID=32 +@pytest.mark.temp_skip_ci(targets=['esp32h4'], reason='lack of runner # TODO: IDFCI-11112') +@pytest.mark.temp_skip_ci(targets=['esp32h21'], reason='lack of runner') +@pytest.mark.two_duts +@pytest.mark.parametrize( + 'count, app_path, config, erase_nvs', + [ + ( + 2, + PAWR_ADV_APP_PATH, + 'name', + 'y', + ), + ], + indirect=True, +) +@idf_parametrize('target', NIMBLE_PAWR_ADV_TARGETS, indirect=['target']) +def test_nimble_pawr_adv_sync_func(app_path: str, dut: tuple[IdfDut, IdfDut]) -> None: + _run_nimble_pawr_adv_sync_func(dut) + + +# Case 16: NimBLE proximity sensor peripheral / central +# EXAMPLE_CI_ID: name/esp32c2_xtal26m=33, conn_with_scan/esp32c2_xtal26m_conn_with_scan=34, +# name_v4/esp32c2_xtal26m_name_v4=35, conn_with_scan_v4/esp32c2_xtal26m_conn_with_scan_v4=36, +# esp32_name_v4=37 +BLE_PROXIMITY_SENSOR_V5_CONFIGS = ['name', 'conn_with_scan'] +BLE_PROXIMITY_SENSOR_APP_PATH = ( + f'{str(CUR_DIR / "ble_proximity_sensor" / "proximity_sensor_prph")}' + f'|{str(CUR_DIR / "ble_proximity_sensor" / "proximity_sensor_cent")}' +) + + +def _run_nimble_proximity_sensor_prph_cent(dut: tuple[IdfDut, IdfDut]) -> None: + prph_dut, cent_dut = dut[0], dut[1] + + prph_bt_mac = prph_dut.expect(r'Bluetooth MAC: ' + MAC_PATTERN, timeout=30).group(1).decode('utf8') + cent_dut.expect(r'Bluetooth MAC: ' + MAC_PATTERN, timeout=30) + + name = prph_dut.expect(r'DeviceName:(.+?)\,', timeout=30).group(1).decode('utf8') + peer_name = cent_dut.expect(r'DeviceName:(.+?)\,', timeout=30).group(1).decode('utf8') + assert peer_name == name, ( + 'central and peripheral must use the same CI device name from get_example_name(); ' + 'mismatch means sdkconfig.ci or CI ID is wrong' + ) + + prph_dut.expect_exact('NimBLE_PROX_PRPH: BLE Host Task Started', timeout=30) + cent_dut.expect_exact('NimBLE_PROX_CENT: BLE Host Task Started', timeout=30) + + found = cent_dut.expect( + r'NimBLE_PROX_CENT: Found device: addr: ' + MAC_PATTERN + rf', name: {name}', + timeout=90, + ) + found_addr = found.group(1).decode('utf8') + assert found_addr.lower() == prph_bt_mac.lower(), ( + 'scan must report the peripheral board MAC, not another advertiser with the same CI name' + ) + + cent_dut.expect_exact('Connection established', timeout=90) + prph_dut.expect_exact('connection established; status=0', timeout=30) + + cent_dut.expect_exact('Connection secured', timeout=45) + cent_dut.expect_exact('encryption change event; status=', timeout=30) + cent_dut.expect_exact('Service discovery complete; status=0', timeout=120) + cent_dut.expect_exact('Write alert level char completed; status=', timeout=30) + cent_dut.expect_exact('Read on tx power level char completed; status=0', timeout=30) + cent_dut.expect_exact('Connection handle :', timeout=30) + cent_dut.expect_exact('Current RSSI =', timeout=30) + cent_dut.expect_exact('path loss =', timeout=30) + + prph_output = prph_dut.expect(pexpect.TIMEOUT, timeout=5) + cent_output = cent_dut.expect(pexpect.TIMEOUT, timeout=5) + assert 'rst:' not in str(prph_output) and 'boot:' not in str(prph_output) + assert 'rst:' not in str(cent_output) and 'boot:' not in str(cent_output) + assert 'disconnect' not in str(cent_output).lower() + assert 'disconnect' not in str(prph_output).lower() + + +@pytest.mark.temp_skip_ci(targets=['esp32h4'], reason='lack of runner # TODO: IDFCI-11112') +@pytest.mark.temp_skip_ci(targets=['esp32h21'], reason='lack of runner') +@pytest.mark.temp_skip_ci(targets=['esp32s31'], reason='ble bugs # TODO: BLEQABR25-2508') +@pytest.mark.two_duts +@pytest.mark.parametrize( + 'count, app_path, config, erase_nvs', + [(2, BLE_PROXIMITY_SENSOR_APP_PATH, config, 'y') for config in BLE_PROXIMITY_SENSOR_V5_CONFIGS], + indirect=True, +) +@idf_parametrize( + 'target', + ['esp32c6', 'esp32h2', 'esp32c5', 'esp32c61', 'esp32c3', 'esp32s3', 'esp32h21', 'esp32s31'], + indirect=['target'], +) +def test_nimble_proximity_sensor_prph_cent(dut: tuple[IdfDut, IdfDut]) -> None: + _run_nimble_proximity_sensor_prph_cent(dut) + + +BLE_PROXIMITY_SENSOR_V4_CONFIGS = ['name_v4', 'conn_with_scan_v4'] + + +# Case 17: NimBLE proximity sensor peripheral / central for V4 +@pytest.mark.temp_skip_ci(targets=['esp32h4'], reason='lack of runner # TODO: IDFCI-11112') +@pytest.mark.temp_skip_ci(targets=['esp32h21'], reason='lack of runner') +@pytest.mark.temp_skip_ci(targets=['esp32s31'], reason='ble bugs # TODO: BLEQABR25-2508') +@pytest.mark.two_duts +@pytest.mark.parametrize( + 'count, app_path, config, erase_nvs', + [(2, BLE_PROXIMITY_SENSOR_APP_PATH, config, 'y') for config in BLE_PROXIMITY_SENSOR_V4_CONFIGS], + indirect=True, +) +@idf_parametrize( + 'target', + ['esp32c6', 'esp32h2', 'esp32c5', 'esp32c61', 'esp32c3', 'esp32s3', 'esp32h21', 'esp32s31'], + indirect=['target'], +) +def test_v4_nimble_proximity_sensor_prph_cent(dut: tuple[IdfDut, IdfDut]) -> None: + _run_nimble_proximity_sensor_prph_cent(dut) + + +# Case 18: NimBLE proximity sensor peripheral / central for ESP32 +BLE_PROXIMITY_SENSOR_32_CONFIGS = ['esp32_name_v4'] + + +@pytest.mark.two_duts +@pytest.mark.parametrize( + 'count, app_path, config, erase_nvs', + [(2, BLE_PROXIMITY_SENSOR_APP_PATH, config, 'y') for config in BLE_PROXIMITY_SENSOR_32_CONFIGS], + indirect=True, +) +@idf_parametrize('target', ['esp32'], indirect=['target']) +def test_esp32_nimble_proximity_sensor_prph_cent(dut: tuple[IdfDut, IdfDut]) -> None: + _run_nimble_proximity_sensor_prph_cent(dut) + + +# Case 19: NimBLE proximity sensor for ESP32-C2 26MHz +# Must use configs with CONFIG_XTAL_FREQ_26=y; plain name/name_v4 builds assume 40MHz XTAL +# and BLE RF will not work on 26MHz boards (UART may still work at baud 74880). +BLE_PROXIMITY_SENSOR_C2_CONFIGS = [ + 'esp32c2_xtal26m', + 'esp32c2_xtal26m_conn_with_scan', + 'esp32c2_xtal26m_name_v4', + 'esp32c2_xtal26m_conn_with_scan_v4', +] + + +@pytest.mark.two_duts +@pytest.mark.xtal_26mhz +@pytest.mark.parametrize( + 'baud, count, app_path, config, erase_nvs', + [('74880', 2, BLE_PROXIMITY_SENSOR_APP_PATH, config, 'y') for config in BLE_PROXIMITY_SENSOR_C2_CONFIGS], + indirect=True, +) +@idf_parametrize('target', ['esp32c2'], indirect=['target']) +def test_esp32c2_26mhz_nimble_proximity_sensor_prph_cent(dut: tuple[IdfDut, IdfDut]) -> None: + _run_nimble_proximity_sensor_prph_cent(dut) + + +PERIODIC_ADV_SYNC_APP_PATH = f'{str(CUR_DIR / "ble_periodic_adv")}|{str(CUR_DIR / "ble_periodic_sync")}' +NIMBLE_PERIODIC_ADV_SYNC_TARGETS = [ + 'esp32c3', + 'esp32c6', + 'esp32c5', + 'esp32h2', + 'esp32s3', + 'esp32c61', + 'esp32h21', + 'esp32h4', + 'esp32s31', +] + + +def _run_nimble_periodic_adv_sync_func(dut: tuple[IdfDut, IdfDut]) -> None: + adv_dut, sync_dut = dut[0], dut[1] + + adv_bt_mac = adv_dut.expect(r'Bluetooth MAC: ' + MAC_PATTERN, timeout=30).group(1).decode('utf8') + sync_bt_mac = sync_dut.expect(r'Bluetooth MAC: ' + MAC_PATTERN, timeout=30).group(1).decode('utf8') + assert adv_bt_mac.lower() != sync_bt_mac.lower(), ( + 'advertiser and synchronizer boards must have different Bluetooth MACs' + ) + + name = adv_dut.expect(r'DeviceName:(.+?)\,', timeout=30).group(1).decode('utf8') + peer_name = sync_dut.expect(r'DeviceName:(.+?)\,', timeout=30).group(1).decode('utf8') + assert peer_name == name, ( + 'advertiser and synchronizer must use the same CI device name from ' + 'esp_ble_periodic_get_example_name(); mismatch means sdkconfig.ci or CI ID is wrong' + ) + + adv_dut.expect_exact('NimBLE_BLE_PERIODIC_ADV: BLE Host Task Started', timeout=30) + sync_dut.expect_exact('NimBLE_BLE_PERIODIC_SYNC: BLE Host Task Started', timeout=30) + adv_dut.expect_exact('instance 0 started (periodic)', timeout=30) + + found = sync_dut.expect( + r'NimBLE_BLE_PERIODIC_SYNC: Found device: addr: ' + MAC_PATTERN + rf', name: {name}', + timeout=90, + ) + found_addr = found.group(1).decode('utf8') + assert found_addr.lower() == adv_bt_mac.lower(), ( + 'scan must report the advertiser board identity address, not another advertiser' + ) + + sync_dut.expect_exact('NimBLE_BLE_PERIODIC_SYNC: Create sync', timeout=60) + sync_dut.expect_exact('NimBLE_BLE_PERIODIC_SYNC: Periodic Sync Established', timeout=60) + + synced_addr = ( + sync_dut.expect(r'NimBLE_BLE_PERIODIC_SYNC: Adv Addr: ' + MAC_PATTERN, timeout=30).group(1).decode('utf8') + ) + assert synced_addr.lower() == adv_bt_mac.lower(), ( + 'periodic sync must lock to the advertiser board MAC, not another periodic advertiser' + ) + + sync_dut.expect_exact('Periodic adv report event:', timeout=60) + sync_dut.expect_exact('data_length : 16', timeout=30) + + adv_output = adv_dut.expect(pexpect.TIMEOUT, timeout=10) + sync_output = sync_dut.expect(pexpect.TIMEOUT, timeout=10) + assert 'rst:' not in str(adv_output) and 'boot:' not in str(adv_output) + assert 'rst:' not in str(sync_output) and 'boot:' not in str(sync_output) + assert 'Periodic sync lost' not in str(sync_output) + + +# Case 20: NimBLE periodic advertiser / synchronizer test +# EXAMPLE_CI_ID=38 +@pytest.mark.temp_skip_ci(targets=['esp32h4'], reason='lack of runner # TODO: IDFCI-11112') +@pytest.mark.temp_skip_ci(targets=['esp32h21'], reason='lack of runner') +@pytest.mark.two_duts +@pytest.mark.parametrize( + 'count, app_path, config, erase_nvs', + [ + ( + 2, + PERIODIC_ADV_SYNC_APP_PATH, + 'name', + 'y', + ), + ], + indirect=True, +) +@idf_parametrize('target', NIMBLE_PERIODIC_ADV_SYNC_TARGETS, indirect=['target']) +def test_nimble_periodic_adv_sync_func(app_path: str, dut: tuple[IdfDut, IdfDut]) -> None: + _run_nimble_periodic_adv_sync_func(dut) + + +# Case 21: NimBLE periodic advertiser / synchronizer for ESP32-C2 26MHz +# EXAMPLE_CI_ID=38 +@pytest.mark.two_duts +@pytest.mark.xtal_26mhz +@pytest.mark.parametrize( + 'count, target, baud, app_path, config, erase_nvs', + [ + ( + 2, + 'esp32c2|esp32c2', + '74880', + PERIODIC_ADV_SYNC_APP_PATH, + 'esp32c2_xtal26m', + 'y', + ), + ], + indirect=True, +) +def test_nimble_periodic_adv_sync_func_esp32c2_26mhz(app_path: str, dut: tuple[IdfDut, IdfDut]) -> None: + _run_nimble_periodic_adv_sync_func(dut) + + +BLECENT_BLEPRPH_APP_PATH = f'{str(CUR_DIR / "bleprph")}|{str(CUR_DIR / "blecent")}' +NIMBLE_BLECENT_BLEPRPH_TARGETS = [ + 'esp32', + 'esp32c3', + 'esp32c6', + 'esp32c5', + 'esp32h2', + 'esp32s3', + 'esp32c61', + 'esp32h4', + 'esp32s31', +] + + +def _run_nimble_blecent_bleprph_func(dut: tuple[IdfDut, IdfDut]) -> None: + peripheral, central = dut[0], dut[1] + + peripheral_addr = peripheral.expect(r'Bluetooth MAC: ' + MAC_PATTERN, timeout=30).group(1).decode('utf8') + central_addr = central.expect(r'Bluetooth MAC: ' + MAC_PATTERN, timeout=30).group(1).decode('utf8') + assert peripheral_addr.lower() != central_addr.lower(), ( + 'peripheral and central boards must have different Bluetooth MACs' + ) + + name = peripheral.expect(r'DeviceName:(.+?)\,', timeout=30).group(1).decode('utf8') + peer_name = central.expect(r'DeviceName:(.+?)\,', timeout=30).group(1).decode('utf8') + assert peer_name == name, ( + 'central and peripheral must use the same CI device name from the blecent/bleprph helpers; ' + 'mismatch means sdkconfig.ci or CI ID is wrong' + ) + + peripheral.expect_exact('NimBLE_BLE_PRPH: BLE Host Task Started', timeout=30) + central.expect_exact('NimBLE_BLE_CENT: BLE Host Task Started', timeout=30) + peripheral.expect_exact('NimBLE: Device Address:', timeout=30) + + found_addr = ( + central.expect( + rf'NimBLE_BLE_CENT: Found device: {MAC_PATTERN}, name: {name}', + timeout=60, + ) + .group(1) + .decode('utf8') + ) + assert found_addr.lower() == peripheral_addr.lower(), ( + 'scan must report the peripheral board MAC, not another advertiser with the same CI name' + ) + + connected_remote = ( + central.expect( + r'NimBLE_BLE_CENT: Connected, conn_handle \d+, remote ' + MAC_PATTERN, + timeout=30, + ) + .group(1) + .decode('utf8') + ) + assert connected_remote.lower() == peripheral_addr.lower(), ( + 'central must connect to the peripheral board MAC, not a colliding device in RF environment' + ) + peripheral_remote = ( + peripheral.expect( + r'NimBLE_BLE_PRPH: Connected, conn_handle \d+, remote ' + MAC_PATTERN, + timeout=30, + ) + .group(1) + .decode('utf8') + ) + assert peripheral_remote.lower() == central_addr.lower(), ( + 'peripheral must see the central board MAC as its connection peer' + ) + + central.expect_exact('NimBLE: Service discovery complete; status=0', timeout=60) + central.expect(r'NimBLE: Read complete; status=0 conn_handle=\d+', timeout=30) + central.expect(r'NimBLE: Write complete; status=\d+ conn_handle=\d+ attr_handle=\d+', timeout=30) + central.expect(r'NimBLE: Subscribe complete; status=0 conn_handle=\d+ attr_handle=\d+', timeout=30) + central.expect( + r'NimBLE: Subscribe to the custom subscribable characteristic complete; ' + r'status=0 conn_handle=\d+', + timeout=30, + ) + + peripheral.expect( + r'NimBLE: subscribe event; conn_handle=\d+ attr_handle=\d+ reason=\d+ prevn=\d+ curn=1', + timeout=30, + ) + peripheral.expect( + r'NimBLE: subscribe event; conn_handle=\d+ attr_handle=\d+ reason=\d+ prevn=\d+ curn=1', + timeout=30, + ) + peripheral.expect(r'NimBLE: Characteristic write; conn_handle=\d+ attr_handle=\d+', timeout=30) + peripheral.expect_exact('NimBLE: Notification/Indication scheduled for all subscribed peers.', timeout=30) + + central.expect( + r'NimBLE: Write to the custom subscribable characteristic complete; ' + r'status=0 conn_handle=\d+ attr_handle=\d+', + timeout=30, + ) + central.expect(r'NimBLE: received notification; conn_handle=\d+ attr_handle=\d+ attr_len=1', timeout=30) + peripheral.expect( + r'NimBLE: notify_tx event; conn_handle=\d+ attr_handle=\d+ status=0 is_indication=0', + timeout=30, + ) + central.expect( + r'NimBLE: Read complete for the subscribable characteristic; ' + r'status=0 conn_handle=\d+', + timeout=30, + ) + peripheral.expect(r'NimBLE: Characteristic read; conn_handle=\d+ attr_handle=\d+', timeout=30) + + out_central = central.expect(pexpect.TIMEOUT, timeout=10) + out_peripheral = peripheral.expect(pexpect.TIMEOUT, timeout=10) + assert 'rst:' not in str(out_central) and 'boot:' not in str(out_central) + assert 'rst:' not in str(out_peripheral) and 'boot:' not in str(out_peripheral) + assert 'disconnect' not in str(out_central).lower() + assert 'disconnect' not in str(out_peripheral).lower() + + +# Case 22: NimBLE bleprph / blecent test +# EXAMPLE_CI_ID=39 +@pytest.mark.temp_skip_ci(targets=['esp32h4'], reason='lack of runner # TODO: IDFCI-11112') +@pytest.mark.two_duts +@pytest.mark.parametrize( + 'count, app_path, config, erase_nvs', + [(2, BLECENT_BLEPRPH_APP_PATH, 'name', 'y')], + indirect=True, +) +@idf_parametrize('target', NIMBLE_BLECENT_BLEPRPH_TARGETS, indirect=['target']) +def test_nimble_blecent_bleprph_func(app_path: str, dut: tuple[IdfDut, IdfDut]) -> None: + _run_nimble_blecent_bleprph_func(dut) + + +# Case 23: NimBLE bleprph / blecent test for ESP32-C2 26MHz +# EXAMPLE_CI_ID=39 +@pytest.mark.two_duts +@pytest.mark.xtal_26mhz +@pytest.mark.parametrize( + 'count, target, baud, app_path, config, erase_nvs', + [(2, 'esp32c2|esp32c2', '74880', BLECENT_BLEPRPH_APP_PATH, 'bleprph_esp32c2_xtal26m', 'y')], + indirect=True, +) +def test_nimble_blecent_bleprph_func_esp32c2_26mhz(app_path: str, dut: tuple[IdfDut, IdfDut]) -> None: + _run_nimble_blecent_bleprph_func(dut) + + +def _run_nimble_multi_adv_func(dut: IdfDut) -> None: + dut.expect_exact('NimBLE_MULTI_ADV: BLE Host Task Started', timeout=30) + for instance in range(4): + dut.expect_exact(f'NimBLE_MULTI_ADV: Instance {instance} started', timeout=30) + dut.expect_exact('main_task: Returned from app_main()', timeout=30) + + # Instance 3 has a five-second duration and must restart after completion. + dut.expect_exact('NimBLE: advertise complete; reason=13', timeout=10) + dut.expect_exact('NimBLE_MULTI_ADV: Instance 3 started', timeout=30) + + output = dut.expect(pexpect.TIMEOUT, timeout=10) + assert 'rst:' not in str(output) and 'boot:' not in str(output) + assert 'assert failed' not in str(output).lower() + assert 'Resetting state' not in str(output) + + +NIMBLE_MULTI_ADV_TARGETS = [ + 'esp32c3', + 'esp32c5', + 'esp32c6', + 'esp32c61', + 'esp32h2', + 'esp32h21', + 'esp32h4', + 'esp32s3', + 'esp32s31', +] + + +# Case 24: NimBLE multi-adv single-DUT smoke test +@pytest.mark.temp_skip_ci(targets=['esp32h4'], reason='lack of runner # TODO: IDFCI-11112') +@pytest.mark.temp_skip_ci(targets=['esp32h21'], reason='lack of runner') +@pytest.mark.generic +@pytest.mark.parametrize( + 'count, app_path, config, erase_nvs', + [(1, str(CUR_DIR / 'ble_multi_adv'), 'name', 'y')], + indirect=True, +) +@idf_parametrize('target', NIMBLE_MULTI_ADV_TARGETS, indirect=['target']) +def test_nimble_multi_adv_func(dut: IdfDut) -> None: + _run_nimble_multi_adv_func(dut) + + +# Case 25: NimBLE multi-adv single-DUT smoke test for ESP32-C2 26MHz +@pytest.mark.generic +@pytest.mark.xtal_26mhz +@pytest.mark.parametrize( + 'count, target, baud, app_path, config, erase_nvs', + [(1, 'esp32c2', '74880', str(CUR_DIR / 'ble_multi_adv'), 'esp32c2_xtal26m', 'y')], + indirect=True, +) +def test_nimble_multi_adv_func_esp32c2_26mhz(dut: IdfDut) -> None: + _run_nimble_multi_adv_func(dut) + + +NIMBLE_GATT_THROUGHPUT_APP_PATH = ( + f'{str(CUR_DIR / "throughput_app" / "gatt" / "bleprph_throughput")}' + f'|{str(CUR_DIR / "throughput_app" / "gatt" / "blecent_throughput")}' +) +NIMBLE_GATT_THROUGHPUT_TARGETS = [ + 'esp32', + 'esp32c3', + 'esp32c5', + 'esp32c6', + 'esp32c61', + 'esp32h2', + 'esp32h21', + 'esp32h4', + 'esp32s3', + 'esp32s31', +] + + +def _run_nimble_gatt_throughput_func(dut: tuple[IdfDut, IdfDut], throughput_mode: str) -> None: + peripheral, central = dut + + peripheral_addr = peripheral.expect(r'Bluetooth MAC: ' + MAC_PATTERN, timeout=30).group(1).decode('utf8') + central_addr = central.expect(r'Bluetooth MAC: ' + MAC_PATTERN, timeout=30).group(1).decode('utf8') + assert peripheral_addr.lower() != central_addr.lower(), ( + 'peripheral and central boards must have different Bluetooth MACs' + ) + name = peripheral.expect(r'DeviceName:(.+?)\,', timeout=30).group(1).decode('utf8') + peer_name = central.expect(r'DeviceName:(.+?)\,', timeout=30).group(1).decode('utf8') + assert peer_name == name, ( + 'central and peripheral must use the same CI device name from get_example_name(); ' + 'mismatch means sdkconfig.ci or CI ID is wrong' + ) + + peripheral.expect_exact('bleprph_throughput: BLE Host Task Started', timeout=30) + central.expect_exact('blecent_throughput: BLE Host Task Started', timeout=30) + peripheral.expect_exact('bleprph_throughput: Device Address:', timeout=30) + + central.expect_exact('If yes then enter in this format: `Insert Yes`', timeout=30) + central.write('Insert No') + central.expect_exact('User entered: Insert No', timeout=10) + + found_addr = ( + central.expect( + r'blecent_throughput: Found device: addr: ' + MAC_PATTERN + rf', name: {name}', + timeout=60, + ) + .group(1) + .decode('utf8') + ) + assert found_addr.lower() == peripheral_addr.lower(), ( + 'scan must report the peripheral board MAC, not another advertiser with the same CI name' + ) + + central.expect_exact('blecent_throughput: Connection established', timeout=30) + peripheral.expect_exact('bleprph_throughput: connection established; status = 0', timeout=30) + connected_remote = ( + central.expect( + r'blecent_throughput: Connected, conn_handle \d+, remote ' + MAC_PATTERN, + timeout=30, + ) + .group(1) + .decode('utf8') + ) + assert connected_remote.lower() == peripheral_addr.lower(), ( + 'central must connect to the peripheral board MAC, not another device in the RF environment' + ) + peripheral_remote = ( + peripheral.expect( + r'bleprph_throughput: Connected, conn_handle \d+, remote ' + MAC_PATTERN, + timeout=30, + ) + .group(1) + .decode('utf8') + ) + assert peripheral_remote.lower() == central_addr.lower(), ( + 'peripheral must see the central board MAC as its connection peer' + ) + + central.expect( + r'blecent_throughput: mtu update event; conn_handle = \d+ cid = \d+ mtu = 512', + timeout=30, + ) + peripheral.expect( + r'bleprph_throughput: mtu update event; conn_handle = \d+ mtu = 512', + timeout=30, + ) + central.expect( + r'blecent_throughput: Service discovery complete; status=0 conn_handle=\d+', + timeout=60, + ) + central.expect_exact('blecent_throughput: Format for throughput demo:: throughput read 100', timeout=10) + central.write(f'throughput {throughput_mode} 10 0') + central.expect_exact(f'Throughput demo handler: throughput {throughput_mode} 10 0', timeout=10) + central.expect_exact('blecent_throughput: Requested connection parameter update', timeout=30) + + if throughput_mode == 'read': + result = central.expect( + r'blecent_throughput: Application Read throughput = (\d+) bps, Read op counter = (\d+)', + timeout=30, + ) + assert int(result.group(1)) > 0 and int(result.group(2)) > 0, ( + 'read throughput and completed read count must both be positive' + ) + central.expect_exact('blecent_throughput: Restoring WRITE-optimized conn params', timeout=10) + elif throughput_mode == 'write': + result = central.expect( + r'blecent_throughput: Application Write throughput = (\d+) bps, write count = (\d+),' + r'failure count = (\d+)', + timeout=30, + ) + write_count = int(result.group(2)) + assert int(result.group(1)) > 0 and write_count > 0, ( + 'write throughput and attempted write count must both be positive' + ) + assert int(result.group(3)) < write_count, 'the write test must complete at least one write successfully' + else: + central.expect_exact( + 'blecent_throughput: Subscribed to notifications. ' + 'Throughput number can be seen on peripheral terminal after 10 seconds', + timeout=30, + ) + peripheral.expect(r'bleprph_throughput: subscribe event; cur_notify=1; value handle;', timeout=30) + peripheral.expect_exact('bleprph_throughput: Notifications enabled, test time = 3600 sec', timeout=30) + central.expect_exact('blecent_throughput: Unsubscribed from notifications', timeout=30) + peripheral.expect_exact('bleprph_throughput: Notifications disabled', timeout=60) + result = peripheral.expect( + r'bleprph_throughput: Notify throughput = (\d+) bps, count = (\d+)', + timeout=30, + ) + assert int(result.group(1)) > 0 and int(result.group(2)) > 0, ( + 'notification throughput and sent notification count must both be positive' + ) + peripheral.expect(r'bleprph_throughput: Notification test complete \(\d+ sec elapsed\)', timeout=10) + + out_central = central.expect(pexpect.TIMEOUT, timeout=10) + out_peripheral = peripheral.expect(pexpect.TIMEOUT, timeout=10) + assert 'rst:' not in str(out_central) and 'boot:' not in str(out_central) + assert 'rst:' not in str(out_peripheral) and 'boot:' not in str(out_peripheral) + assert 'disconnect' not in str(out_central).lower() + assert 'disconnect' not in str(out_peripheral).lower() + + +# Case 26: NimBLE GATT throughput read/write/notify (EXAMPLE_CI_ID=40) +@pytest.mark.temp_skip_ci(targets=['esp32h4'], reason='lack of runner # TODO: IDFCI-11112') +@pytest.mark.temp_skip_ci(targets=['esp32h21'], reason='lack of runner') +@pytest.mark.temp_skip_ci(targets=['esp32s31'], reason='ble bugs # TODO: BLEQABR25-2509') +@pytest.mark.two_duts +@pytest.mark.parametrize('throughput_mode', ['read', 'write', 'notify']) +@pytest.mark.parametrize( + 'count, app_path, config, erase_nvs', + [(2, NIMBLE_GATT_THROUGHPUT_APP_PATH, 'name', 'y')], + indirect=True, +) +@idf_parametrize('target', NIMBLE_GATT_THROUGHPUT_TARGETS, indirect=['target']) +def test_nimble_gatt_throughput_func(throughput_mode: str, app_path: str, dut: tuple[IdfDut, IdfDut]) -> None: + _run_nimble_gatt_throughput_func(dut, throughput_mode) + + +# Case 27: NimBLE GATT throughput for ESP32-C2 26MHz (EXAMPLE_CI_ID=40) +@pytest.mark.two_duts +@pytest.mark.xtal_26mhz +@pytest.mark.parametrize('throughput_mode', ['read', 'write', 'notify']) +@pytest.mark.parametrize( + 'count, target, baud, app_path, config, erase_nvs', + [ + ( + 2, + 'esp32c2|esp32c2', + '74880', + NIMBLE_GATT_THROUGHPUT_APP_PATH, + 'esp32c2_xtal26m', + 'y', + ) + ], + indirect=True, +) +def test_nimble_gatt_throughput_func_esp32c2_26mhz( + throughput_mode: str, app_path: str, dut: tuple[IdfDut, IdfDut] +) -> None: + _run_nimble_gatt_throughput_func(dut, throughput_mode) + + +L2CAP_COC_APP_PATH = ( + f'{str(CUR_DIR / "ble_l2cap_coc" / "coc_bleprph")}|{str(CUR_DIR / "ble_l2cap_coc" / "coc_blecent")}' +) +NIMBLE_L2CAP_COC_TARGETS = [ + 'esp32', + 'esp32c3', + 'esp32c6', + 'esp32c5', + 'esp32h2', + 'esp32s3', + 'esp32c61', + 'esp32h4', + 'esp32s31', +] + + +def _run_nimble_l2cap_coc_func(dut: tuple[IdfDut, IdfDut]) -> None: + peripheral = dut[0] + central = dut[1] + + peripheral_addr = ( + peripheral.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') + ) + central_addr = ( + central.expect(r'Bluetooth MAC: (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', timeout=30).group(1).decode('utf8') + ) + name = peripheral.expect(r'DeviceName:(.+?)\,', timeout=30).group(1).decode('utf8') + peer_name = central.expect(r'DeviceName:(.+?)\,', timeout=30).group(1).decode('utf8') + assert peer_name == name, ( + 'central and peripheral must use the same CI device name from ' + 'esp_ble_l2cap_coc_get_example_name(); mismatch means sdkconfig.ci or CI ID is wrong' + ) + + peripheral.expect_exact('NimBLE_BLE_PRPH_L2CAP_COC: BLE Host Task Started', timeout=30) + central.expect_exact('NimBLE_BLE_CENT_L2CAP_COC: BLE Host Task Started', timeout=30) + + found_addr = ( + central.expect( + rf'Found device: (([0-9a-fA-F]{{2}}:){{5}}[0-9a-fA-F]{{2}}), name: {name}', + timeout=60, + ) + .group(1) + .decode('utf8') + ) + assert found_addr.lower() == peripheral_addr.lower(), ( + 'scan must report the peripheral board MAC, not another advertiser with the same CI name' + ) + + connected_remote = ( + central.expect( + r'Connected, conn_handle \d+, remote (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', + timeout=30, + ) + .group(1) + .decode('utf8') + ) + assert connected_remote.lower() == peripheral_addr.lower(), ( + 'central must connect to the peripheral board MAC, not a colliding device in RF environment' + ) + peripheral_remote = ( + peripheral.expect( + r'Connected, conn_handle \d+, remote (([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})', + timeout=30, + ) + .group(1) + .decode('utf8') + ) + assert peripheral_remote.lower() == central_addr.lower(), 'peripheral must see central board MAC as connection peer' + + central.expect_exact('LE COC connected, conn:', timeout=60) + peripheral.expect_exact('LE COC connected, conn:', timeout=30) + central.expect_exact('Data sent successfully', timeout=30) + peripheral.expect_exact('Data received :', timeout=30) + + out_central = central.expect(pexpect.TIMEOUT, timeout=10) + out_peripheral = peripheral.expect(pexpect.TIMEOUT, timeout=10) + assert 'rst:' not in str(out_central) and 'boot:' not in str(out_central) + assert 'rst:' not in str(out_peripheral) and 'boot:' not in str(out_peripheral) + assert 'disconnect' not in str(out_central).lower() + assert 'disconnect' not in str(out_peripheral).lower() + + +# Case 28: NimBLE L2CAP COC peripheral/central test +# EXAMPLE_CI_ID=41 +@pytest.mark.temp_skip_ci(targets=['esp32h4'], reason='lack of runner # TODO: IDFCI-11112') +@pytest.mark.two_duts +@pytest.mark.parametrize( + 'count, app_path, config, erase_nvs', + [ + ( + 2, + L2CAP_COC_APP_PATH, + 'name', + 'y', + ), + ], + indirect=True, +) +@idf_parametrize('target', NIMBLE_L2CAP_COC_TARGETS, indirect=['target']) +def test_nimble_l2cap_coc_func(app_path: str, dut: tuple[IdfDut, IdfDut]) -> None: + _run_nimble_l2cap_coc_func(dut) + + +# Case 29: NimBLE L2CAP COC test for ESP32C2 26MHz +# EXAMPLE_CI_ID=41 +@pytest.mark.two_duts +@pytest.mark.xtal_26mhz +@pytest.mark.parametrize( + 'count, target, baud, app_path, config, erase_nvs', + [ + ( + 2, + 'esp32c2|esp32c2', + '74880', + L2CAP_COC_APP_PATH, + 'esp32c2_xtal26m', + 'y', + ), + ], + indirect=True, +) +def test_nimble_l2cap_coc_func_esp32c2_26mhz(app_path: str, dut: tuple[IdfDut, IdfDut]) -> None: + _run_nimble_l2cap_coc_func(dut) + + +NIMBLE_L2CAP_COC_TP_APP_PATH = ( + f'{str(CUR_DIR / "throughput_app" / "l2cap_coc" / "l2cap_coc_prph")}' + f'|{str(CUR_DIR / "throughput_app" / "l2cap_coc" / "l2cap_coc_cent")}' +) +NIMBLE_L2CAP_COC_TP_TARGETS = [ + 'esp32', + 'esp32c3', + 'esp32c5', + 'esp32c6', + 'esp32c61', + 'esp32h2', + 'esp32h21', + 'esp32h4', + 'esp32s3', + 'esp32s31', +] + + +def _run_nimble_l2cap_coc_throughput_func(dut: tuple[IdfDut, IdfDut]) -> None: + peripheral, central = dut + + peripheral_addr = peripheral.expect(r'Bluetooth MAC: ' + MAC_PATTERN, timeout=30).group(1).decode('utf8') + central_addr = central.expect(r'Bluetooth MAC: ' + MAC_PATTERN, timeout=30).group(1).decode('utf8') + assert peripheral_addr.lower() != central_addr.lower(), ( + 'peripheral and central boards must have different Bluetooth MACs' + ) + name = peripheral.expect(r'DeviceName:(.+?)\,', timeout=30).group(1).decode('utf8') + peer_name = central.expect(r'DeviceName:(.+?)\,', timeout=30).group(1).decode('utf8') + assert peer_name == name, ( + 'central and peripheral must use the same CI device name from ' + 'esp_ble_l2cap_coc_tp_get_example_name(); mismatch means sdkconfig.ci or CI ID is wrong' + ) + + peripheral.expect_exact('l2cap_coc_prph: BLE Host Task started', timeout=30) + central.expect_exact('l2cap_coc_cent: BLE Host Task started', timeout=30) + peripheral.expect(r'l2cap_coc_prph: Device Address: ' + MAC_PATTERN, timeout=30) + central.expect(r'l2cap_coc_cent: Device Address: ' + MAC_PATTERN, timeout=30) + + found_addr = ( + central.expect( + r'l2cap_coc_cent: Found device: ' + MAC_PATTERN + rf', name: {name}', + timeout=60, + ) + .group(1) + .decode('utf8') + ) + assert found_addr.lower() == peripheral_addr.lower(), ( + 'scan must report the peripheral board MAC, not another advertiser with the same CI name' + ) + + connected_remote = ( + central.expect( + r'l2cap_coc_cent: Connected, conn_handle \d+, remote ' + MAC_PATTERN, + timeout=30, + ) + .group(1) + .decode('utf8') + ) + assert connected_remote.lower() == peripheral_addr.lower(), ( + 'central must connect to the peripheral board MAC, not a colliding device in RF environment' + ) + peripheral_remote = ( + peripheral.expect( + r'l2cap_coc_prph: Connected, conn_handle \d+, remote ' + MAC_PATTERN, + timeout=30, + ) + .group(1) + .decode('utf8') + ) + assert peripheral_remote.lower() == central_addr.lower(), ( + 'peripheral must see the central board MAC as its connection peer' + ) + + central.expect_exact('l2cap_coc_cent: L2CAP COC connected, chan=', timeout=60) + peripheral.expect_exact('l2cap_coc_prph: L2CAP COC connected, chan=', timeout=30) + # The banner contains a non-ASCII em dash, which pexpect cannot encode in expect_exact. + central.expect( + r'l2cap_coc_cent: L2CAP COC Throughput .+ TX side \(central sends to peripheral\)', + timeout=30, + ) + phy_count = central.expect(r'l2cap_coc_cent: Number of enabled PHYs: (\d+)', timeout=30) + assert int(phy_count.group(1)) > 0, 'at least one EXAMPLE_TEST_PHY_* must be enabled for the throughput test' + # Classic ESP32 has no BLE 5.0 PHY update; the example applies 1M without logging PHY updated. + if central.target != 'esp32': + central.expect(r'l2cap_coc_cent: PHY updated: tx=\d+ rx=\d+ status=0', timeout=30) + central.expect(r'l2cap_coc_cent: \[.+ PHY\] Sending for \d+ s', timeout=60) + + rx_result = peripheral.expect( + r'l2cap_coc_prph: \| RX : (\d+)\s+kbps \|', + timeout=60, + ) + assert int(rx_result.group(1)) > 0, 'peripheral RX throughput must be positive while central is sending' + + central.expect(r'l2cap_coc_cent: \| PHY : .+\|', timeout=60) + tx_result = central.expect( + r'l2cap_coc_cent: \| TX : (\d+)\s+kbps', + timeout=30, + ) + assert int(tx_result.group(1)) > 0, 'central TX throughput must be positive after the measurement interval' + bytes_result = central.expect( + r'l2cap_coc_cent: \| Bytes : (\d+)', + timeout=10, + ) + assert int(bytes_result.group(1)) > 0, 'central must report a positive number of bytes sent' + + out_central = central.expect(pexpect.TIMEOUT, timeout=10) + out_peripheral = peripheral.expect(pexpect.TIMEOUT, timeout=10) + assert 'rst:' not in str(out_central) and 'boot:' not in str(out_central) + assert 'rst:' not in str(out_peripheral) and 'boot:' not in str(out_peripheral) + assert 'disconnect' not in str(out_central).lower() + assert 'disconnect' not in str(out_peripheral).lower() + + +# Case 30: NimBLE L2CAP COC throughput (EXAMPLE_CI_ID=42) +@pytest.mark.temp_skip_ci(targets=['esp32h4'], reason='lack of runner # TODO: IDFCI-11112') +@pytest.mark.temp_skip_ci(targets=['esp32h21'], reason='lack of runner') +@pytest.mark.two_duts +@pytest.mark.parametrize( + 'count, app_path, config, erase_nvs', + [(2, NIMBLE_L2CAP_COC_TP_APP_PATH, 'name', 'y')], + indirect=True, +) +@idf_parametrize('target', NIMBLE_L2CAP_COC_TP_TARGETS, indirect=['target']) +def test_nimble_l2cap_coc_throughput_func(app_path: str, dut: tuple[IdfDut, IdfDut]) -> None: + _run_nimble_l2cap_coc_throughput_func(dut) + + +# Case 31: NimBLE L2CAP COC throughput for ESP32-C2 26MHz (EXAMPLE_CI_ID=42) +@pytest.mark.two_duts +@pytest.mark.xtal_26mhz +@pytest.mark.temp_skip_ci(targets=['esp32c2'], reason='ble bug # TODO: BLEQABR25-2507') +@pytest.mark.parametrize( + 'count, target, baud, app_path, config, erase_nvs', + [ + ( + 2, + 'esp32c2|esp32c2', + '74880', + NIMBLE_L2CAP_COC_TP_APP_PATH, + 'esp32c2_xtal26m', + 'y', + ) + ], + indirect=True, +) +def test_nimble_l2cap_coc_throughput_func_esp32c2_26mhz(app_path: str, dut: tuple[IdfDut, IdfDut]) -> None: + _run_nimble_l2cap_coc_throughput_func(dut) diff --git a/examples/bluetooth/nimble/throughput_app/gatt/blecent_throughput/main/Kconfig.projbuild b/examples/bluetooth/nimble/throughput_app/gatt/blecent_throughput/main/Kconfig.projbuild index 6750fc74f5d..b0f9b35519a 100644 --- a/examples/bluetooth/nimble/throughput_app/gatt/blecent_throughput/main/Kconfig.projbuild +++ b/examples/bluetooth/nimble/throughput_app/gatt/blecent_throughput/main/Kconfig.projbuild @@ -1,5 +1,13 @@ menu "Example Configuration" + config EXAMPLE_CI_ID + int "example id for CI test" + default 0 + + config EXAMPLE_CI_PIPELINE_ID + int "Project CI pipeline ID for CI test" + default 0 + config EXAMPLE_PEER_ADDR string "Peer Address" default "ADDR_ANY" diff --git a/examples/bluetooth/nimble/throughput_app/gatt/blecent_throughput/main/main.c b/examples/bluetooth/nimble/throughput_app/gatt/blecent_throughput/main/main.c index 5761056de7d..13dcecf653a 100644 --- a/examples/bluetooth/nimble/throughput_app/gatt/blecent_throughput/main/main.c +++ b/examples/bluetooth/nimble/throughput_app/gatt/blecent_throughput/main/main.c @@ -56,6 +56,22 @@ static const char *tag = "blecent_throughput"; static int blecent_gap_event(struct ble_gap_event *event, void *arg); +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID +static char remote_device_name[32]; + +static char *esp_ble_throughput_get_example_name(void) +{ + static char example_name[32]; + + memset(example_name, 0, sizeof(example_name)); + snprintf(example_name, sizeof(example_name), "BE%02X_%05X_%02X", + CONFIG_EXAMPLE_CI_ID & 0xFF, + CONFIG_EXAMPLE_CI_PIPELINE_ID & 0xFFFFF, + CONFIG_IDF_FIRMWARE_CHIP_ID & 0xFF); + return example_name; +} +#endif + static int mbuf_len_total; static int failure_count; static TaskHandle_t throughput_task_handle = NULL; @@ -749,6 +765,12 @@ blecent_scan(void) disc_params.filter_policy = 0; disc_params.limited = 0; +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + /* Full scan improves discovery reliability in multi-board CI environments. */ + disc_params.itvl = BLE_GAP_SCAN_ITVL_MS(50); + disc_params.window = BLE_GAP_SCAN_ITVL_MS(50); +#endif + rc = ble_gap_disc(own_addr_type, BLE_HS_FOREVER, &disc_params, blecent_gap_event, NULL); if (rc != 0) { @@ -769,7 +791,9 @@ ext_blecent_should_connect(const struct ble_gap_ext_disc_desc *disc) int offset = 0; int ad_struct_len = 0; uint8_t parsed_addr[6]; +#if !(CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID) uint8_t phy_uuid_found = 0; +#endif if (!(disc->props & BLE_HCI_ADV_CONN_MASK)) { return 0; @@ -783,6 +807,35 @@ ext_blecent_should_connect(const struct ble_gap_ext_disc_desc *disc) } } +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + /* Match on the CI device name only, so that boards belonging to other + * pipelines or examples in the same RF environment are ignored. */ + do { + if (offset + 1 >= (int)disc->length_data) { + break; + } + ad_struct_len = disc->data[offset]; + + if (!ad_struct_len || offset + ad_struct_len + 1 > (int)disc->length_data) { + break; + } + + if (disc->data[offset + 1] == BLE_HS_ADV_TYPE_COMP_NAME || + disc->data[offset + 1] == BLE_HS_ADV_TYPE_INCOMP_NAME) { + int name_len = ad_struct_len - 1; + if (name_len == (int)strlen(remote_device_name) && + memcmp(&disc->data[offset + 2], remote_device_name, name_len) == 0) { + return 1; + } + return 0; + } + + offset += ad_struct_len + 1; + + } while (offset < (int)disc->length_data); + + return 0; +#else /* The device has to advertise support LE PHY UUID (0xABF2). */ do { @@ -822,6 +875,7 @@ ext_blecent_should_connect(const struct ble_gap_ext_disc_desc *disc) } while (offset < (int)disc->length_data); return phy_uuid_found; +#endif } #else /** @@ -834,7 +888,9 @@ blecent_should_connect(const struct ble_gap_disc_desc *disc) { struct ble_hs_adv_fields fields; int rc; +#if !(CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID) int i; +#endif uint8_t test_addr[6]; rc = ble_hs_adv_parse_fields(&fields, disc->data, disc->length_data); if (rc != 0) { @@ -850,6 +906,16 @@ blecent_should_connect(const struct ble_gap_disc_desc *disc) } } +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + /* Match on the CI device name only, so that boards belonging to other + * pipelines or examples in the same RF environment are ignored. */ + if (fields.name != NULL && + fields.name_len == strlen(remote_device_name) && + memcmp(fields.name, remote_device_name, fields.name_len) == 0) { + return 1; + } + return 0; +#else ESP_LOGD(tag, "connect; fields.num_uuids128 =%d", fields.num_uuids128); for (i = 0; i < fields.num_uuids128; i++) { if ((memcmp(&fields.uuids128[i], THRPT_UUID_DECLARE(THRPT_SVC), @@ -873,6 +939,7 @@ blecent_should_connect(const struct ble_gap_disc_desc *disc) } } return 0; +#endif } #endif @@ -904,6 +971,10 @@ blecent_connect_if_interesting(void *disc) memcpy(&conn_addr, &disc_desc->addr, sizeof(conn_addr)); #endif +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + ESP_LOGI(tag, "Found device: addr: %s, name: %s", addr_str(conn_addr.val), remote_device_name); +#endif + #if !(MYNEWT_VAL(BLE_HOST_ALLOW_CONNECT_WITH_SCAN)) /* Scanning must be stopped before a connection can be initiated. */ rc = ble_gap_disc_cancel(); @@ -1003,6 +1074,11 @@ blecent_gap_event(struct ble_gap_event *event, void *arg) assert(rc == 0); print_conn_desc(&desc); +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + ESP_LOGI(tag, "Connected, conn_handle %d, remote %s", + event->connect.conn_handle, addr_str(desc.peer_id_addr.val)); +#endif + rc = ble_gap_update_params(event->connect.conn_handle, &conn_params); if (rc != 0) { ESP_LOGE(tag, "Failed to update params; rc = %d", rc); @@ -1208,6 +1284,13 @@ app_main(void) return; } +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + strncpy(remote_device_name, esp_ble_throughput_get_example_name(), sizeof(remote_device_name) - 1); + remote_device_name[sizeof(remote_device_name) - 1] = '\0'; + ESP_LOGI(tag, "DeviceName:%s, CIID:%02X, PipelineID:%05X, ChipID:%02X", + remote_device_name, CONFIG_EXAMPLE_CI_ID, CONFIG_EXAMPLE_CI_PIPELINE_ID, CONFIG_IDF_FIRMWARE_CHIP_ID); +#endif + /* Configure the host. */ ble_hs_cfg.reset_cb = blecent_on_reset; ble_hs_cfg.sync_cb = blecent_on_sync; diff --git a/examples/bluetooth/nimble/throughput_app/gatt/blecent_throughput/sdkconfig.ci.esp32c2_xtal26m b/examples/bluetooth/nimble/throughput_app/gatt/blecent_throughput/sdkconfig.ci.esp32c2_xtal26m new file mode 100644 index 00000000000..28fbbd760f0 --- /dev/null +++ b/examples/bluetooth/nimble/throughput_app/gatt/blecent_throughput/sdkconfig.ci.esp32c2_xtal26m @@ -0,0 +1,4 @@ +CONFIG_EXAMPLE_CI_ID=40 +CONFIG_IDF_TARGET="esp32c2" +CONFIG_XTAL_FREQ_26=y +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} diff --git a/examples/bluetooth/nimble/throughput_app/gatt/blecent_throughput/sdkconfig.ci.name b/examples/bluetooth/nimble/throughput_app/gatt/blecent_throughput/sdkconfig.ci.name new file mode 100644 index 00000000000..dc996c1a00a --- /dev/null +++ b/examples/bluetooth/nimble/throughput_app/gatt/blecent_throughput/sdkconfig.ci.name @@ -0,0 +1,2 @@ +CONFIG_EXAMPLE_CI_ID=40 +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} diff --git a/examples/bluetooth/nimble/throughput_app/gatt/bleprph_throughput/main/Kconfig.projbuild b/examples/bluetooth/nimble/throughput_app/gatt/bleprph_throughput/main/Kconfig.projbuild index 8e5ab9f250a..bc43206e71f 100644 --- a/examples/bluetooth/nimble/throughput_app/gatt/bleprph_throughput/main/Kconfig.projbuild +++ b/examples/bluetooth/nimble/throughput_app/gatt/bleprph_throughput/main/Kconfig.projbuild @@ -1,5 +1,13 @@ menu "Example Configuration" + config EXAMPLE_CI_ID + int "example id for CI test" + default 0 + + config EXAMPLE_CI_PIPELINE_ID + int "Project CI pipeline ID for CI test" + default 0 + config EXAMPLE_EXTENDED_ADV bool depends on SOC_BLE_50_SUPPORTED && BT_NIMBLE_50_FEATURE_SUPPORT diff --git a/examples/bluetooth/nimble/throughput_app/gatt/bleprph_throughput/main/main.c b/examples/bluetooth/nimble/throughput_app/gatt/bleprph_throughput/main/main.c index ba8f5d32874..a68fee989c1 100644 --- a/examples/bluetooth/nimble/throughput_app/gatt/bleprph_throughput/main/main.c +++ b/examples/bluetooth/nimble/throughput_app/gatt/bleprph_throughput/main/main.c @@ -26,10 +26,14 @@ static uint8_t ext_adv_pattern[] = { 0x0c, BLE_HS_ADV_TYPE_COMP_NAME, 'n', 'i', 'm', 'b', 'l', 'e', '_', 'p', 'r', 'p', 'h' }; +/* Offset of the complete-name AD structure inside ext_adv_pattern. Keep in sync + * with the pattern above; everything before it is flags plus service UUIDs. */ +#define EXT_ADV_PATTERN_NAME_OFFSET 11 + static uint8_t s_current_phy; #endif -static const char *device_name = "nimble_prph"; +static char device_name[32] = "nimble_prph"; #define NOTIFY_THROUGHPUT_PAYLOAD 495 /* Exactly aligns with 2 LL packets */ #define MIN_REQUIRED_MBUF 10 /* Reserve mbufs for incoming ATT packets */ @@ -50,6 +54,20 @@ static uint8_t gatts_addr_type; static int gatts_gap_event(struct ble_gap_event *event, void *arg); +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID +static char *esp_ble_throughput_get_example_name(void) +{ + static char example_name[32]; + + memset(example_name, 0, sizeof(example_name)); + snprintf(example_name, sizeof(example_name), "BE%02X_%05X_%02X", + CONFIG_EXAMPLE_CI_ID & 0xFF, + CONFIG_EXAMPLE_CI_PIPELINE_ID & 0xFFFFF, + CONFIG_IDF_FIRMWARE_CHIP_ID & 0xFF); + return example_name; +} +#endif + #if CONFIG_EXAMPLE_EXTENDED_ADV void set_default_le_phy(uint8_t tx_phys_mask, uint8_t rx_phys_mask) { @@ -160,7 +178,23 @@ ext_bleprph_advertise(void) /* Set current phy; get mbuf for scan rsp data; fill mbuf with scan rsp data */ params.primary_phy = BLE_HCI_LE_PHY_1M_PREF_MASK ; params.secondary_phy = BLE_HCI_LE_PHY_2M_PREF_MASK ; +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + /* Keep flags and service UUIDs, but advertise the CI-unique name so the + * paired central only connects to its own board. */ + uint8_t ci_adv_data[BLE_HS_ADV_MAX_SZ]; + uint8_t name_len = strlen(device_name); + uint8_t ci_adv_len = EXT_ADV_PATTERN_NAME_OFFSET; + + memcpy(ci_adv_data, ext_adv_pattern, ci_adv_len); + ci_adv_data[ci_adv_len++] = name_len + 1; + ci_adv_data[ci_adv_len++] = BLE_HS_ADV_TYPE_COMP_NAME; + memcpy(&ci_adv_data[ci_adv_len], device_name, name_len); + ci_adv_len += name_len; + + data = ext_get_data(ci_adv_data, ci_adv_len); +#else data = ext_get_data(ext_adv_pattern, sizeof(ext_adv_pattern)); +#endif if (!data) { return; } @@ -379,6 +413,16 @@ gatts_gap_event(struct ble_gap_event *event, void *arg) ESP_LOGE(tag, "Set packet length failed"); } +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + if (event->connect.status == 0 && + ble_gap_conn_find(event->connect.conn_handle, &desc) == 0) { + const uint8_t *peer = desc.peer_id_addr.val; + ESP_LOGI(tag, "Connected, conn_handle %d, remote %02x:%02x:%02x:%02x:%02x:%02x", + event->connect.conn_handle, + peer[5], peer[4], peer[3], peer[2], peer[1], peer[0]); + } +#endif + conn_handle = event->connect.conn_handle; break; @@ -561,6 +605,13 @@ void app_main(void) rc = gatt_svr_init(); assert(rc == 0); +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + strncpy(device_name, esp_ble_throughput_get_example_name(), sizeof(device_name) - 1); + device_name[sizeof(device_name) - 1] = '\0'; + ESP_LOGI(tag, "DeviceName:%s, CIID:%02X, PipelineID:%05X, ChipID:%02X", + device_name, CONFIG_EXAMPLE_CI_ID, CONFIG_EXAMPLE_CI_PIPELINE_ID, CONFIG_IDF_FIRMWARE_CHIP_ID); +#endif + #if CONFIG_BT_NIMBLE_GAP_SERVICE /* Set the default device name */ rc = ble_svc_gap_device_name_set(device_name); diff --git a/examples/bluetooth/nimble/throughput_app/gatt/bleprph_throughput/sdkconfig.ci.esp32c2_xtal26m b/examples/bluetooth/nimble/throughput_app/gatt/bleprph_throughput/sdkconfig.ci.esp32c2_xtal26m new file mode 100644 index 00000000000..28fbbd760f0 --- /dev/null +++ b/examples/bluetooth/nimble/throughput_app/gatt/bleprph_throughput/sdkconfig.ci.esp32c2_xtal26m @@ -0,0 +1,4 @@ +CONFIG_EXAMPLE_CI_ID=40 +CONFIG_IDF_TARGET="esp32c2" +CONFIG_XTAL_FREQ_26=y +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} diff --git a/examples/bluetooth/nimble/throughput_app/gatt/bleprph_throughput/sdkconfig.ci.name b/examples/bluetooth/nimble/throughput_app/gatt/bleprph_throughput/sdkconfig.ci.name new file mode 100644 index 00000000000..dc996c1a00a --- /dev/null +++ b/examples/bluetooth/nimble/throughput_app/gatt/bleprph_throughput/sdkconfig.ci.name @@ -0,0 +1,2 @@ +CONFIG_EXAMPLE_CI_ID=40 +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} diff --git a/examples/bluetooth/nimble/throughput_app/l2cap_coc/l2cap_coc_cent/main/Kconfig.projbuild b/examples/bluetooth/nimble/throughput_app/l2cap_coc/l2cap_coc_cent/main/Kconfig.projbuild index 5632e2c99d0..11195e520e0 100644 --- a/examples/bluetooth/nimble/throughput_app/l2cap_coc/l2cap_coc_cent/main/Kconfig.projbuild +++ b/examples/bluetooth/nimble/throughput_app/l2cap_coc/l2cap_coc_cent/main/Kconfig.projbuild @@ -64,4 +64,16 @@ menu "L2CAP COC Throughput Configuration" range 1 3600 depends on EXAMPLE_TEST_PHY_CODED_S8 + config EXAMPLE_CI_ID + int "example id for CI test" + default 0 + help + This config the example id for CI test. Only for internal used. + + config EXAMPLE_CI_PIPELINE_ID + int "The pipeline id for CI test" + default 0 + help + This config the pipeline id for CI test. Only for internal used. + endmenu diff --git a/examples/bluetooth/nimble/throughput_app/l2cap_coc/l2cap_coc_cent/main/main.c b/examples/bluetooth/nimble/throughput_app/l2cap_coc/l2cap_coc_cent/main/main.c index 93887b58a5b..87a2a28c419 100644 --- a/examples/bluetooth/nimble/throughput_app/l2cap_coc/l2cap_coc_cent/main/main.c +++ b/examples/bluetooth/nimble/throughput_app/l2cap_coc/l2cap_coc_cent/main/main.c @@ -6,6 +6,7 @@ #include #include +#include #include #include "esp_log.h" #include "nvs_flash.h" @@ -22,6 +23,22 @@ static const char *TAG = "l2cap_coc_cent"; +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID +static char remote_device_name[32]; + +static char *esp_ble_l2cap_coc_tp_get_example_name(void) +{ + static char example_name[32]; + + memset(example_name, 0, sizeof(example_name)); + snprintf(example_name, sizeof(example_name), "BE%02X_%05X_%02X", + CONFIG_EXAMPLE_CI_ID & 0xFF, + CONFIG_EXAMPLE_CI_PIPELINE_ID & 0xFFFFF, + CONFIG_IDF_FIRMWARE_CHIP_ID & 0xFF); + return example_name; +} +#endif + #define L2CAP_COC_PSM 0x0080 /* valid dynamic LE L2CAP CoC PSM (0x0080-0x00FF) */ #define L2CAP_COC_MTU CONFIG_EXAMPLE_L2CAP_COC_MTU #define COC_BUF_COUNT (6 * MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM)) @@ -162,6 +179,11 @@ static void cent_scan(void) ESP_LOGE(TAG, "Error inferring addr type; rc=%d", rc); return; } +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + /* Full scan improves discovery reliability in multi-board CI environments. */ + disc_params.itvl = BLE_GAP_SCAN_ITVL_MS(50); + disc_params.window = BLE_GAP_SCAN_WIN_MS(50); +#endif rc = ble_gap_disc(own_addr_type, BLE_HS_FOREVER, &disc_params, cent_gap_event, NULL); if (rc != 0) { @@ -180,12 +202,21 @@ static int cent_should_connect(const struct ble_gap_disc_desc *disc) if (rc != 0) { return 0; } +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + if (fields.name != NULL && + fields.name_len == strlen(remote_device_name) && + memcmp(fields.name, remote_device_name, fields.name_len) == 0) { + return 1; + } + return 0; +#else for (int i = 0; i < fields.num_uuids16; i++) { if (ble_uuid_u16(&fields.uuids16[i].u) == L2CAP_COC_UUID) { return 1; } } return 0; +#endif } static void cent_connect_if_interesting(const struct ble_gap_disc_desc *disc) @@ -204,6 +235,12 @@ static void cent_connect_if_interesting(const struct ble_gap_disc_desc *disc) cent_scan(); return; } +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + ESP_LOGI(TAG, "Found device: %02x:%02x:%02x:%02x:%02x:%02x, name: %s", + disc->addr.val[5], disc->addr.val[4], disc->addr.val[3], + disc->addr.val[2], disc->addr.val[1], disc->addr.val[0], + remote_device_name); +#endif ESP_LOGI(TAG, "Connecting to %02x:%02x:%02x:%02x:%02x:%02x (addr_type=%d)", disc->addr.val[5], disc->addr.val[4], disc->addr.val[3], disc->addr.val[2], disc->addr.val[1], disc->addr.val[0], @@ -226,6 +263,13 @@ static void cent_connect_if_interesting_ext(const struct ble_gap_ext_disc_desc * if (ble_hs_adv_parse_fields(&fields, disc->data, disc->length_data) != 0) { return; } +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + if (fields.name == NULL || + fields.name_len != strlen(remote_device_name) || + memcmp(fields.name, remote_device_name, fields.name_len) != 0) { + return; + } +#else int found = 0; for (int i = 0; i < fields.num_uuids16; i++) { if (ble_uuid_u16(&fields.uuids16[i].u) == L2CAP_COC_UUID) { @@ -236,6 +280,7 @@ static void cent_connect_if_interesting_ext(const struct ble_gap_ext_disc_desc * if (!found) { return; } +#endif int rc = ble_gap_disc_cancel(); if (rc != 0) { return; @@ -247,6 +292,12 @@ static void cent_connect_if_interesting_ext(const struct ble_gap_ext_disc_desc * cent_scan(); return; } +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + ESP_LOGI(TAG, "Found device: %02x:%02x:%02x:%02x:%02x:%02x, name: %s", + disc->addr.val[5], disc->addr.val[4], disc->addr.val[3], + disc->addr.val[2], disc->addr.val[1], disc->addr.val[0], + remote_device_name); +#endif ESP_LOGI(TAG, "Connecting to %02x:%02x:%02x:%02x:%02x:%02x (addr_type=%d)", disc->addr.val[5], disc->addr.val[4], disc->addr.val[3], disc->addr.val[2], disc->addr.val[1], disc->addr.val[0], @@ -597,6 +648,13 @@ static int cent_gap_event(struct ble_gap_event *event, void *arg) desc.peer_id_addr.val[5], desc.peer_id_addr.val[4], desc.peer_id_addr.val[3], desc.peer_id_addr.val[2], desc.peer_id_addr.val[1], desc.peer_id_addr.val[0]); +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + ESP_LOGI(TAG, "Connected, conn_handle %d, remote %02x:%02x:%02x:%02x:%02x:%02x", + event->connect.conn_handle, + desc.peer_ota_addr.val[5], desc.peer_ota_addr.val[4], + desc.peer_ota_addr.val[3], desc.peer_ota_addr.val[2], + desc.peer_ota_addr.val[1], desc.peer_ota_addr.val[0]); +#endif } conn_handle = event->connect.conn_handle; @@ -729,6 +787,14 @@ void app_main(void) ble_hs_cfg.sync_cb = cent_on_sync; ble_hs_cfg.store_status_cb = ble_store_util_status_rr; +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + strncpy(remote_device_name, esp_ble_l2cap_coc_tp_get_example_name(), sizeof(remote_device_name) - 1); + remote_device_name[sizeof(remote_device_name) - 1] = '\0'; + ESP_LOGI(TAG, "DeviceName:%s, CIID:%02X, PipelineID:%05X, ChipID:%02X", + remote_device_name, CONFIG_EXAMPLE_CI_ID, CONFIG_EXAMPLE_CI_PIPELINE_ID, + CONFIG_IDF_FIRMWARE_CHIP_ID); +#endif + #if CONFIG_BT_NIMBLE_GAP_SERVICE int rc = ble_svc_gap_device_name_set("l2cap-coc-cent"); assert(rc == 0); diff --git a/examples/bluetooth/nimble/throughput_app/l2cap_coc/l2cap_coc_cent/sdkconfig.ci.esp32c2_xtal26m b/examples/bluetooth/nimble/throughput_app/l2cap_coc/l2cap_coc_cent/sdkconfig.ci.esp32c2_xtal26m new file mode 100644 index 00000000000..0ec2b4d23e3 --- /dev/null +++ b/examples/bluetooth/nimble/throughput_app/l2cap_coc/l2cap_coc_cent/sdkconfig.ci.esp32c2_xtal26m @@ -0,0 +1,6 @@ +CONFIG_EXAMPLE_CI_ID=42 +CONFIG_IDF_TARGET="esp32c2" +CONFIG_XTAL_FREQ_26=y +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} +CONFIG_EXAMPLE_TEST_DURATION_1M=3 +CONFIG_EXAMPLE_TEST_DURATION_2M=3 diff --git a/examples/bluetooth/nimble/throughput_app/l2cap_coc/l2cap_coc_cent/sdkconfig.ci.name b/examples/bluetooth/nimble/throughput_app/l2cap_coc/l2cap_coc_cent/sdkconfig.ci.name new file mode 100644 index 00000000000..7f2e5e0a145 --- /dev/null +++ b/examples/bluetooth/nimble/throughput_app/l2cap_coc/l2cap_coc_cent/sdkconfig.ci.name @@ -0,0 +1,4 @@ +CONFIG_EXAMPLE_CI_ID=42 +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} +CONFIG_EXAMPLE_TEST_DURATION_1M=3 +CONFIG_EXAMPLE_TEST_DURATION_2M=3 diff --git a/examples/bluetooth/nimble/throughput_app/l2cap_coc/l2cap_coc_prph/main/Kconfig.projbuild b/examples/bluetooth/nimble/throughput_app/l2cap_coc/l2cap_coc_prph/main/Kconfig.projbuild index ee49e5894fd..d6d5ec7773d 100644 --- a/examples/bluetooth/nimble/throughput_app/l2cap_coc/l2cap_coc_prph/main/Kconfig.projbuild +++ b/examples/bluetooth/nimble/throughput_app/l2cap_coc/l2cap_coc_prph/main/Kconfig.projbuild @@ -20,4 +20,16 @@ menu "L2CAP COC Throughput Configuration" help Enable BLE 5.0 extended advertising. + config EXAMPLE_CI_ID + int "example id for CI test" + default 0 + help + This config the example id for CI test. Only for internal used. + + config EXAMPLE_CI_PIPELINE_ID + int "The pipeline id for CI test" + default 0 + help + This config the pipeline id for CI test. Only for internal used. + endmenu diff --git a/examples/bluetooth/nimble/throughput_app/l2cap_coc/l2cap_coc_prph/main/main.c b/examples/bluetooth/nimble/throughput_app/l2cap_coc/l2cap_coc_prph/main/main.c index 27452b7ff68..7496a7f417e 100644 --- a/examples/bluetooth/nimble/throughput_app/l2cap_coc/l2cap_coc_prph/main/main.c +++ b/examples/bluetooth/nimble/throughput_app/l2cap_coc/l2cap_coc_prph/main/main.c @@ -6,6 +6,7 @@ #include #include +#include #include #include "esp_log.h" #include "nvs_flash.h" @@ -19,6 +20,21 @@ #include "services/gap/ble_svc_gap.h" static const char *TAG = "l2cap_coc_prph"; +static char device_name[32] = "l2cap-coc-prph"; + +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID +static char *esp_ble_l2cap_coc_tp_get_example_name(void) +{ + static char example_name[32]; + + memset(example_name, 0, sizeof(example_name)); + snprintf(example_name, sizeof(example_name), "BE%02X_%05X_%02X", + CONFIG_EXAMPLE_CI_ID & 0xFF, + CONFIG_EXAMPLE_CI_PIPELINE_ID & 0xFFFFF, + CONFIG_IDF_FIRMWARE_CHIP_ID & 0xFF); + return example_name; +} +#endif #define L2CAP_COC_PSM 0x0080 /* valid dynamic LE L2CAP CoC PSM (0x0080-0x00FF) */ #define L2CAP_COC_MTU CONFIG_EXAMPLE_L2CAP_COC_MTU @@ -127,12 +143,14 @@ static void prph_reset_rx_stats(int64_t start_time) } #if CONFIG_EXAMPLE_EXTENDED_ADV +#if !(CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID) static uint8_t ext_adv_pattern[] = { 0x02, BLE_HS_ADV_TYPE_FLAGS, 0x06, 0x03, BLE_HS_ADV_TYPE_COMP_UUIDS16, 0x12, 0x18, 0x11, BLE_HS_ADV_TYPE_COMP_NAME, 'l','2','c','a','p','-','c','o','c','-','p','r','p','h','-','e', }; +#endif static void prph_advertise(void) { @@ -140,6 +158,11 @@ static void prph_advertise(void) struct os_mbuf *data; uint8_t instance = 0; int rc; +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + uint8_t ci_adv_data[32]; + uint8_t ci_adv_len; + uint8_t name_len; +#endif memset(¶ms, 0, sizeof(params)); params.connectable = 1; @@ -157,12 +180,28 @@ static void prph_advertise(void) return; } +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + name_len = strlen(device_name); + memset(ci_adv_data, 0, sizeof(ci_adv_data)); + ci_adv_data[0] = name_len + 1; + ci_adv_data[1] = BLE_HS_ADV_TYPE_COMP_NAME; + memcpy(&ci_adv_data[2], device_name, name_len); + ci_adv_len = 2 + name_len; + + data = os_msys_get_pkthdr(ci_adv_len, 0); + if (!data) { + ESP_LOGE(TAG, "ext_adv: failed to alloc adv data mbuf"); + return; + } + rc = os_mbuf_append(data, ci_adv_data, ci_adv_len); +#else data = os_msys_get_pkthdr(sizeof(ext_adv_pattern), 0); if (!data) { ESP_LOGE(TAG, "ext_adv: failed to alloc adv data mbuf"); return; } rc = os_mbuf_append(data, ext_adv_pattern, sizeof(ext_adv_pattern)); +#endif if (rc != 0) { ESP_LOGE(TAG, "ext_adv: mbuf_append failed; rc=%d", rc); os_mbuf_free_chain(data); @@ -193,12 +232,10 @@ static void prph_advertise(void) fields.flags = BLE_HS_ADV_F_DISC_GEN | BLE_HS_ADV_F_BREDR_UNSUP; fields.tx_pwr_lvl_is_present = 1; fields.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO; -#if CONFIG_BT_NIMBLE_GAP_SERVICE - const char *name = ble_svc_gap_device_name(); - fields.name = (uint8_t *)name; - fields.name_len = strlen(name); + fields.name = (uint8_t *)device_name; + fields.name_len = strlen(device_name); fields.name_is_complete = 1; -#endif +#if !(CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID) /* Must be static: ble_gap_adv_set_fields copies the pointer, not the data. * A stack compound literal becomes dangling after prph_advertise returns, * causing corruption when BLE_NIMBLE_ENABLE_CONN_REATTEMPT re-uses the pointer. */ @@ -206,6 +243,7 @@ static void prph_advertise(void) fields.uuids16 = adv_uuids16; fields.num_uuids16 = 1; fields.uuids16_is_complete = 1; +#endif rc = ble_gap_adv_set_fields(&fields); if (rc != 0) { @@ -390,6 +428,18 @@ static int prph_gap_event(struct ble_gap_event *event, void *arg) return 0; } ESP_LOGI(TAG, "Connected; handle=%d", event->connect.conn_handle); +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + { + struct ble_gap_conn_desc desc; + if (ble_gap_conn_find(event->connect.conn_handle, &desc) == 0) { + ESP_LOGI(TAG, "Connected, conn_handle %d, remote %02x:%02x:%02x:%02x:%02x:%02x", + event->connect.conn_handle, + desc.peer_ota_addr.val[5], desc.peer_ota_addr.val[4], + desc.peer_ota_addr.val[3], desc.peer_ota_addr.val[2], + desc.peer_ota_addr.val[1], desc.peer_ota_addr.val[0]); + } + } +#endif conn_handle = event->connect.conn_handle; return 0; @@ -495,8 +545,16 @@ void app_main(void) ble_hs_cfg.sync_cb = prph_on_sync; ble_hs_cfg.store_status_cb = ble_store_util_status_rr; +#if CONFIG_EXAMPLE_CI_ID && CONFIG_EXAMPLE_CI_PIPELINE_ID + strncpy(device_name, esp_ble_l2cap_coc_tp_get_example_name(), sizeof(device_name) - 1); + device_name[sizeof(device_name) - 1] = '\0'; + ESP_LOGI(TAG, "DeviceName:%s, CIID:%02X, PipelineID:%05X, ChipID:%02X", + device_name, CONFIG_EXAMPLE_CI_ID, CONFIG_EXAMPLE_CI_PIPELINE_ID, + CONFIG_IDF_FIRMWARE_CHIP_ID); +#endif + #if CONFIG_BT_NIMBLE_GAP_SERVICE - int rc = ble_svc_gap_device_name_set("l2cap-coc-prph"); + int rc = ble_svc_gap_device_name_set(device_name); assert(rc == 0); #endif diff --git a/examples/bluetooth/nimble/throughput_app/l2cap_coc/l2cap_coc_prph/sdkconfig.ci.esp32c2_xtal26m b/examples/bluetooth/nimble/throughput_app/l2cap_coc/l2cap_coc_prph/sdkconfig.ci.esp32c2_xtal26m new file mode 100644 index 00000000000..3525e5f0356 --- /dev/null +++ b/examples/bluetooth/nimble/throughput_app/l2cap_coc/l2cap_coc_prph/sdkconfig.ci.esp32c2_xtal26m @@ -0,0 +1,4 @@ +CONFIG_EXAMPLE_CI_ID=42 +CONFIG_IDF_TARGET="esp32c2" +CONFIG_XTAL_FREQ_26=y +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID} diff --git a/examples/bluetooth/nimble/throughput_app/l2cap_coc/l2cap_coc_prph/sdkconfig.ci.name b/examples/bluetooth/nimble/throughput_app/l2cap_coc/l2cap_coc_prph/sdkconfig.ci.name new file mode 100644 index 00000000000..bc1516f78a5 --- /dev/null +++ b/examples/bluetooth/nimble/throughput_app/l2cap_coc/l2cap_coc_prph/sdkconfig.ci.name @@ -0,0 +1,2 @@ +CONFIG_EXAMPLE_CI_ID=42 +CONFIG_EXAMPLE_CI_PIPELINE_ID=${CI_PIPELINE_ID}