NimBLE: Add optional mbedTLS support to NimBLE (backport)

- NimBLE: Additional menuconfig option to enable mbedTLS instead of Tinycrypt from
  NimBLE, changes `component.mk` & `CMakeLists.txt` for the same.
- Addition of NimBLE stack size configuration and misc changes.
- mbedTLS: Addition of `CMAC` and `ECP_RESTARTABLE` to mbedTLS menuconfig option and
  `esp_config.h`.
- Example: Minor changes to `app_mesh.c` application.
This commit is contained in:
Prasad Alatkar 2019-09-23 21:37:40 +08:00 committed by Jiang Jiang Jian
parent 7f9626d378
commit daa65b6f91
13 changed files with 398 additions and 234 deletions

View File

@ -377,9 +377,13 @@ if(CONFIG_BT_ENABLED)
host/nimble/nimble/nimble/host/store/ram/include host/nimble/nimble/nimble/host/store/ram/include
host/nimble/nimble/nimble/host/store/config/include host/nimble/nimble/nimble/host/store/config/include
host/nimble/nimble/porting/npl/freertos/include host/nimble/nimble/porting/npl/freertos/include
host/nimble/nimble/ext/tinycrypt/include
host/nimble/esp-hci/include) host/nimble/esp-hci/include)
if(NOT CONFIG_BT_NIMBLE_CRYPTO_STACK_MBEDTLS)
list(APPEND include_dirs
host/nimble/nimble/ext/tinycrypt/include)
list(APPEND srcs "host/nimble/nimble/ext/tinycrypt/src/utils.c" list(APPEND srcs "host/nimble/nimble/ext/tinycrypt/src/utils.c"
"host/nimble/nimble/ext/tinycrypt/src/sha256.c" "host/nimble/nimble/ext/tinycrypt/src/sha256.c"
"host/nimble/nimble/ext/tinycrypt/src/ecc.c" "host/nimble/nimble/ext/tinycrypt/src/ecc.c"
@ -394,8 +398,10 @@ if(CONFIG_BT_ENABLED)
"host/nimble/nimble/ext/tinycrypt/src/hmac_prng.c" "host/nimble/nimble/ext/tinycrypt/src/hmac_prng.c"
"host/nimble/nimble/ext/tinycrypt/src/ecc_platform_specific.c" "host/nimble/nimble/ext/tinycrypt/src/ecc_platform_specific.c"
"host/nimble/nimble/ext/tinycrypt/src/hmac.c" "host/nimble/nimble/ext/tinycrypt/src/hmac.c"
"host/nimble/nimble/ext/tinycrypt/src/cbc_mode.c" "host/nimble/nimble/ext/tinycrypt/src/cbc_mode.c")
"host/nimble/nimble/nimble/host/util/src/addr.c" endif()
list(APPEND srcs "host/nimble/nimble/nimble/host/util/src/addr.c"
"host/nimble/nimble/nimble/host/services/gatt/src/ble_svc_gatt.c" "host/nimble/nimble/nimble/host/services/gatt/src/ble_svc_gatt.c"
"host/nimble/nimble/nimble/host/services/tps/src/ble_svc_tps.c" "host/nimble/nimble/nimble/host/services/tps/src/ble_svc_tps.c"
"host/nimble/nimble/nimble/host/services/ias/src/ble_svc_ias.c" "host/nimble/nimble/nimble/host/services/ias/src/ble_svc_ias.c"

View File

@ -148,11 +148,12 @@ ifdef CONFIG_BLE_MESH
esp_ble_mesh/mesh_models/common \ esp_ble_mesh/mesh_models/common \
esp_ble_mesh/mesh_models/client \ esp_ble_mesh/mesh_models/client \
esp_ble_mesh/api/core \ esp_ble_mesh/api/core \
esp_ble_mesh/api/models esp_ble_mesh/api/models
endif endif
ifdef CONFIG_BT_NIMBLE_ENABLED ifdef CONFIG_BT_NIMBLE_ENABLED
COMPONENT_ADD_INCLUDEDIRS += host/nimble/nimble/nimble/include \ COMPONENT_ADD_INCLUDEDIRS += host/nimble/nimble/nimble/include \
host/nimble/nimble/nimble/host/include \ host/nimble/nimble/nimble/host/include \
host/nimble/nimble/porting/nimble/include \ host/nimble/nimble/porting/nimble/include \
@ -167,14 +168,16 @@ COMPONENT_ADD_INCLUDEDIRS += host/nimble/nimble/nimble/include
host/nimble/nimble/nimble/host/util/include \ host/nimble/nimble/nimble/host/util/include \
host/nimble/nimble/nimble/host/store/ram/include \ host/nimble/nimble/nimble/host/store/ram/include \
host/nimble/nimble/nimble/host/store/config/include \ host/nimble/nimble/nimble/host/store/config/include \
host/nimble/nimble/ext/tinycrypt/include \
host/nimble/esp-hci/include \ host/nimble/esp-hci/include \
host/nimble/port/include host/nimble/port/include
ifndef CONFIG_BT_NIMBLE_CRYPTO_STACK_MBEDTLS
COMPONENT_ADD_INCLUDEDIRS += host/nimble/nimble/ext/tinycrypt/include
endif
COMPONENT_SRCDIRS += host/nimble/nimble/nimble/host/src \ COMPONENT_SRCDIRS += host/nimble/nimble/nimble/host/src \
host/nimble/nimble/porting/nimble/src \ host/nimble/nimble/porting/nimble/src \
host/nimble/nimble/porting/npl/freertos/src \ host/nimble/nimble/porting/npl/freertos/src \
host/nimble/nimble/ext/tinycrypt/src \
host/nimble/nimble/nimble/host/services/ans/src \ host/nimble/nimble/nimble/host/services/ans/src \
host/nimble/nimble/nimble/host/services/bas/src \ host/nimble/nimble/nimble/host/services/bas/src \
host/nimble/nimble/nimble/host/services/gap/src \ host/nimble/nimble/nimble/host/services/gap/src \
@ -187,6 +190,10 @@ COMPONENT_SRCDIRS += host/nimble/nimble/nimble/host/src
host/nimble/nimble/nimble/host/store/config/src \ host/nimble/nimble/nimble/host/store/config/src \
host/nimble/esp-hci/src host/nimble/esp-hci/src
ifndef CONFIG_BT_NIMBLE_CRYPTO_STACK_MBEDTLS
COMPONENT_SRCDIRS += host/nimble/nimble/ext/tinycrypt/src
endif
COMPONENT_OBJEXCLUDE += host/nimble/nimble/nimble/host/store/config/src/ble_store_config_conf.o COMPONENT_OBJEXCLUDE += host/nimble/nimble/nimble/host/store/config/src/ble_store_config_conf.o
ifdef CONFIG_BT_NIMBLE_MESH ifdef CONFIG_BT_NIMBLE_MESH

View File

@ -50,6 +50,13 @@ config BT_NIMBLE_PINNED_TO_CORE
default 1 if BT_NIMBLE_PINNED_TO_CORE_1 default 1 if BT_NIMBLE_PINNED_TO_CORE_1
default 0 default 0
config BT_NIMBLE_TASK_STACK_SIZE
int "NimBLE Host task stack size"
depends on BT_NIMBLE_ENABLED
default 4096
help
This configures stack size of NimBLE host task
config BT_NIMBLE_ROLE_CENTRAL config BT_NIMBLE_ROLE_CENTRAL
bool "Enable BLE Central role" bool "Enable BLE Central role"
depends on BT_NIMBLE_ENABLED depends on BT_NIMBLE_ENABLED
@ -92,11 +99,11 @@ config BT_NIMBLE_SM_SC
Enable security manager secure connections Enable security manager secure connections
config BT_NIMBLE_DEBUG config BT_NIMBLE_DEBUG
bool "Enable host debugging" bool "Enable extra runtime asserts and host debugging"
default n default n
depends on BT_NIMBLE_ENABLED depends on BT_NIMBLE_ENABLED
help help
This enables extra runtime assertions This enables extra runtime asserts and host debugging
config BT_NIMBLE_SVC_GAP_DEVICE_NAME config BT_NIMBLE_SVC_GAP_DEVICE_NAME
string "BLE GAP default device name" string "BLE GAP default device name"
@ -250,3 +257,12 @@ config BT_NIMBLE_MESH_DEVICE_NAME
help help
This value defines Bluetooth Mesh device/node name This value defines Bluetooth Mesh device/node name
config BT_NIMBLE_CRYPTO_STACK_MBEDTLS
bool "Override TinyCrypt with mbedTLS for crypto computations"
default y
depends on BT_NIMBLE_ENABLED
select MBEDTLS_ECP_RESTARTABLE
select MBEDTLS_CMAC_C
help
Enable this option to choose mbedTLS instead of TinyCrypt for crypto
computations.

@ -1 +1 @@
Subproject commit 7600a6f60308c77fec755a024d51ab2fb7d11553 Subproject commit 6c91a9a153c421231b686d30c822e53fea7510c0

View File

@ -567,6 +567,10 @@
#define MYNEWT_VAL_BLE_SM_THEIR_KEY_DIST (0) #define MYNEWT_VAL_BLE_SM_THEIR_KEY_DIST (0)
#endif #endif
#ifndef MYNEWT_VAL_BLE_CRYPTO_STACK_MBEDTLS
#define MYNEWT_VAL_BLE_CRYPTO_STACK_MBEDTLS (CONFIG_BT_NIMBLE_CRYPTO_STACK_MBEDTLS)
#endif
#ifndef MYNEWT_VAL_BLE_STORE_MAX_BONDS #ifndef MYNEWT_VAL_BLE_STORE_MAX_BONDS
#define MYNEWT_VAL_BLE_STORE_MAX_BONDS CONFIG_BT_NIMBLE_MAX_BONDS #define MYNEWT_VAL_BLE_STORE_MAX_BONDS CONFIG_BT_NIMBLE_MAX_BONDS
#endif #endif

View File

@ -116,6 +116,19 @@ menu "mbedTLS"
default 3 if MBEDTLS_DEBUG_LEVEL_DEBUG default 3 if MBEDTLS_DEBUG_LEVEL_DEBUG
default 4 if MBEDTLS_DEBUG_LEVEL_VERBOSE default 4 if MBEDTLS_DEBUG_LEVEL_VERBOSE
config MBEDTLS_ECP_RESTARTABLE
bool "Enable mbedTLS ecp restartable"
default n
help
Enable "non-blocking" ECC operations that can return early and be resumed.
config MBEDTLS_CMAC_C
bool "Enable CMAC mode for block ciphers"
default n
help
Enable the CMAC (Cipher-based Message Authentication Code) mode for
block ciphers.
config MBEDTLS_HARDWARE_AES config MBEDTLS_HARDWARE_AES
bool "Enable hardware AES acceleration" bool "Enable hardware AES acceleration"
default y default y

@ -1 +1 @@
Subproject commit 97959e77912524bd8db7cbb2e00fc9f6189f7a82 Subproject commit f5f2e5926cd294ae7cb579ff6a12ad9303caeb6e

View File

@ -218,7 +218,7 @@
/** /**
* \def MBEDTLS_REMOVE_ARC4_CIPHERSUITES & MBEDTLS_ARC4_C * \def MBEDTLS_REMOVE_ARC4_CIPHERSUITES & MBEDTLS_ARC4_C
* *
* MBEDTLS_ARC4_C * MBEDTLS_ARC4_C
* Enable the ARCFOUR stream cipher. * Enable the ARCFOUR stream cipher.
* *
@ -253,6 +253,47 @@
#define MBEDTLS_REMOVE_ARC4_CIPHERSUITES #define MBEDTLS_REMOVE_ARC4_CIPHERSUITES
#endif #endif
/**
* \def MBEDTLS_ECP_RESTARTABLE
*
* Enable "non-blocking" ECC operations that can return early and be resumed.
*
* This allows various functions to pause by returning
* #MBEDTLS_ERR_ECP_IN_PROGRESS (or, for functions in the SSL module,
* #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) and then be called later again in
* order to further progress and eventually complete their operation. This is
* controlled through mbedtls_ecp_set_max_ops() which limits the maximum
* number of ECC operations a function may perform before pausing; see
* mbedtls_ecp_set_max_ops() for more information.
*
* This is useful in non-threaded environments if you want to avoid blocking
* for too long on ECC (and, hence, X.509 or SSL/TLS) operations.
*
* Uncomment this macro to enable restartable ECC computations.
*
* \note This option only works with the default software implementation of
* elliptic curve functionality. It is incompatible with
* MBEDTLS_ECP_ALT, MBEDTLS_ECDH_XXX_ALT and MBEDTLS_ECDSA_XXX_ALT.
*/
#ifdef CONFIG_MBEDTLS_ECP_RESTARTABLE
#define MBEDTLS_ECP_RESTARTABLE
#endif
/**
* \def MBEDTLS_CMAC_C
*
* Enable the CMAC (Cipher-based Message Authentication Code) mode for block
* ciphers.
*
* Module: library/cmac.c
*
* Requires: MBEDTLS_AES_C or MBEDTLS_DES_C
*
*/
#ifdef CONFIG_MBEDTLS_CMAC_C
#define MBEDTLS_CMAC_C
#endif
/** /**
* \def MBEDTLS_ECP_DP_SECP192R1_ENABLED * \def MBEDTLS_ECP_DP_SECP192R1_ENABLED
* *

View File

@ -64,6 +64,8 @@ def test_example_app_ble_central(env, extra_data):
adv_type = 'peripheral' adv_type = 'peripheral'
adv_uuid = '1811' adv_uuid = '1811'
subprocess.check_output(['rm','-rf','/var/lib/bluetooth/*'])
subprocess.check_output(['hciconfig','hci0','reset'])
# Acquire DUT # Acquire DUT
dut = env.get_dut("blecent", "examples/bluetooth/nimble/blecent") dut = env.get_dut("blecent", "examples/bluetooth/nimble/blecent")
@ -75,8 +77,8 @@ def test_example_app_ble_central(env, extra_data):
# Upload binary and start testing # Upload binary and start testing
Utility.console_log("Starting blecent example test app") Utility.console_log("Starting blecent example test app")
dut.start_app() dut.start_app()
dut.reset()
subprocess.check_output(['rm','-rf','/var/lib/bluetooth/*'])
device_addr = ':'.join(re.findall('..', '%012x' % uuid.getnode())) device_addr = ':'.join(re.findall('..', '%012x' % uuid.getnode()))
# Get BLE client module # Get BLE client module

View File

@ -18,7 +18,9 @@ from __future__ import print_function
import os import os
import sys import sys
import re import re
from threading import Thread import threading
import traceback
import Queue
import subprocess import subprocess
try: try:
@ -51,7 +53,7 @@ import Utility
# > export TEST_FW_PATH=~/esp/esp-idf/tools/tiny-test-fw # > export TEST_FW_PATH=~/esp/esp-idf/tools/tiny-test-fw
def blehr_client_task(dut_addr, dut): def blehr_client_task(hr_obj, dut_addr):
interface = 'hci0' interface = 'hci0'
ble_devname = 'blehr_sensor_1.0' ble_devname = 'blehr_sensor_1.0'
hr_srv_uuid = '180d' hr_srv_uuid = '180d'
@ -70,20 +72,18 @@ def blehr_client_task(dut_addr, dut):
# Connect BLE Device # Connect BLE Device
is_connected = ble_client_obj.connect() is_connected = ble_client_obj.connect()
if not is_connected: if not is_connected:
Utility.console_log("Connection to device ", ble_devname, "failed !!")
# Call disconnect to perform cleanup operations before exiting application # Call disconnect to perform cleanup operations before exiting application
ble_client_obj.disconnect() ble_client_obj.disconnect()
return raise RuntimeError("Connection to device " + str(ble_devname) + " failed !!")
# Read Services # Read Services
services_ret = ble_client_obj.get_services() services_ret = ble_client_obj.get_services()
if services_ret: if services_ret:
print("\nServices\n") Utility.console_log("\nServices\n")
print(services_ret) Utility.console_log(str(services_ret))
else: else:
print("Failure: Read Services failed")
ble_client_obj.disconnect() ble_client_obj.disconnect()
return raise RuntimeError("Failure: Read Services failed")
''' '''
Blehr application run: Blehr application run:
@ -93,14 +93,27 @@ def blehr_client_task(dut_addr, dut):
''' '''
blehr_ret = ble_client_obj.hr_update_simulation(hr_srv_uuid, hr_char_uuid) blehr_ret = ble_client_obj.hr_update_simulation(hr_srv_uuid, hr_char_uuid)
if blehr_ret: if blehr_ret:
print("Success: blehr example test passed") Utility.console_log("Success: blehr example test passed")
else: else:
print("Failure: blehr example test failed") raise RuntimeError("Failure: blehr example test failed")
# Call disconnect to perform cleanup operations before exiting application # Call disconnect to perform cleanup operations before exiting application
ble_client_obj.disconnect() ble_client_obj.disconnect()
class BleHRThread(threading.Thread):
def __init__(self, dut_addr, exceptions_queue):
threading.Thread.__init__(self)
self.dut_addr = dut_addr
self.exceptions_queue = exceptions_queue
def run(self):
try:
blehr_client_task(self, self.dut_addr)
except Exception:
self.exceptions_queue.put(traceback.format_exc(), block=False)
@IDF.idf_example_test(env_tag="Example_WIFI_BT") @IDF.idf_example_test(env_tag="Example_WIFI_BT")
def test_example_app_ble_hr(env, extra_data): def test_example_app_ble_hr(env, extra_data):
""" """
@ -111,38 +124,47 @@ def test_example_app_ble_hr(env, extra_data):
4. Updated value is retrieved 4. Updated value is retrieved
5. Stop Notifications 5. Stop Notifications
""" """
try: subprocess.check_output(['rm','-rf','/var/lib/bluetooth/*'])
# Acquire DUT subprocess.check_output(['hciconfig','hci0','reset'])
dut = env.get_dut("blehr", "examples/bluetooth/nimble/blehr")
# Get binary file # Acquire DUT
binary_file = os.path.join(dut.app.binary_path, "blehr.bin") dut = env.get_dut("blehr", "examples/bluetooth/nimble/blehr")
bin_size = os.path.getsize(binary_file)
IDF.log_performance("blehr_bin_size", "{}KB".format(bin_size // 1024))
IDF.check_performance("blehr_bin_size", bin_size // 1024)
# Upload binary and start testing # Get binary file
Utility.console_log("Starting blehr simple example test app") binary_file = os.path.join(dut.app.binary_path, "blehr.bin")
dut.start_app() bin_size = os.path.getsize(binary_file)
IDF.log_performance("blehr_bin_size", "{}KB".format(bin_size // 1024))
IDF.check_performance("blehr_bin_size", bin_size // 1024)
subprocess.check_output(['rm','-rf','/var/lib/bluetooth/*']) # Upload binary and start testing
Utility.console_log("Starting blehr simple example test app")
dut.start_app()
dut.reset()
# Get device address from dut # Get device address from dut
dut_addr = dut.expect(re.compile(r"Device Address: ([a-fA-F0-9:]+)"), timeout=30)[0] dut_addr = dut.expect(re.compile(r"Device Address: ([a-fA-F0-9:]+)"), timeout=30)[0]
exceptions_queue = Queue.Queue()
# Starting a py-client in a separate thread
blehr_thread_obj = BleHRThread(dut_addr, exceptions_queue)
blehr_thread_obj.start()
blehr_thread_obj.join()
# Starting a py-client in a separate thread exception_msg = None
thread1 = Thread(target=blehr_client_task, args=(dut_addr,dut,)) while True:
thread1.start() try:
thread1.join() exception_msg = exceptions_queue.get(block=False)
except Queue.Empty:
break
else:
Utility.console_log("\n" + exception_msg)
# Check dut responses if exception_msg:
dut.expect("subscribe event; cur_notify=1", timeout=30) raise Exception("Thread did not run successfully")
dut.expect("GATT procedure initiated: notify;", timeout=30)
dut.expect("subscribe event; cur_notify=0", timeout=30)
dut.expect("disconnect;", timeout=30)
except Exception as e: # Check dut responses
sys.exit(e) dut.expect("subscribe event; cur_notify=1", timeout=30)
dut.expect("subscribe event; cur_notify=0", timeout=30)
dut.expect("disconnect;", timeout=30)
if __name__ == '__main__': if __name__ == '__main__':

View File

@ -32,7 +32,7 @@
#include "mesh/mesh.h" #include "mesh/mesh.h"
static const char *tag = "NimBLE_MESH"; static const char *tag = "NimBLE_MESH";
void ble_store_ram_init(void); void ble_store_config_init(void);
#define BT_DBG_ENABLED (MYNEWT_VAL(BLE_MESH_DEBUG)) #define BT_DBG_ENABLED (MYNEWT_VAL(BLE_MESH_DEBUG))
@ -418,6 +418,7 @@ void blemesh_host_task(void *param)
health_pub_init(); health_pub_init();
nimble_port_run(); nimble_port_run();
nimble_port_freertos_deinit();
} }
void app_main() void app_main()
@ -438,7 +439,7 @@ void app_main()
bt_mesh_register_gatt(); bt_mesh_register_gatt();
/* XXX Need to have template for store */ /* XXX Need to have template for store */
ble_store_ram_init(); ble_store_config_init();
nimble_port_freertos_init(blemesh_host_task); nimble_port_freertos_init(blemesh_host_task);
} }

View File

@ -18,7 +18,9 @@ from __future__ import print_function
import os import os
import sys import sys
import re import re
from threading import Thread import Queue
import traceback
import threading
import subprocess import subprocess
try: try:
@ -50,7 +52,7 @@ import Utility
# > export TEST_FW_PATH=~/esp/esp-idf/tools/tiny-test-fw # > export TEST_FW_PATH=~/esp/esp-idf/tools/tiny-test-fw
def bleprph_client_task(dut_addr, dut): def bleprph_client_task(prph_obj, dut, dut_addr):
interface = 'hci0' interface = 'hci0'
ble_devname = 'nimble-bleprph' ble_devname = 'nimble-bleprph'
srv_uuid = '2f12' srv_uuid = '2f12'
@ -68,10 +70,9 @@ def bleprph_client_task(dut_addr, dut):
# Connect BLE Device # Connect BLE Device
is_connected = ble_client_obj.connect() is_connected = ble_client_obj.connect()
if not is_connected: if not is_connected:
Utility.console_log("Connection to device ", ble_devname, "failed !!")
# Call disconnect to perform cleanup operations before exiting application # Call disconnect to perform cleanup operations before exiting application
ble_client_obj.disconnect() ble_client_obj.disconnect()
return raise RuntimeError("Connection to device " + ble_devname + " failed !!")
# Check dut responses # Check dut responses
dut.expect("GAP procedure initiated: advertise;", timeout=30) dut.expect("GAP procedure initiated: advertise;", timeout=30)
@ -79,12 +80,11 @@ def bleprph_client_task(dut_addr, dut):
# Read Services # Read Services
services_ret = ble_client_obj.get_services(srv_uuid) services_ret = ble_client_obj.get_services(srv_uuid)
if services_ret: if services_ret:
print("\nServices\n") Utility.console_log("\nServices\n")
print(services_ret) Utility.console_log(str(services_ret))
else: else:
print("Failure: Read Services failed")
ble_client_obj.disconnect() ble_client_obj.disconnect()
return raise RuntimeError("Failure: Read Services failed")
# Read Characteristics # Read Characteristics
chars_ret = {} chars_ret = {}
@ -92,14 +92,13 @@ def bleprph_client_task(dut_addr, dut):
if chars_ret: if chars_ret:
Utility.console_log("\nCharacteristics retrieved") Utility.console_log("\nCharacteristics retrieved")
for path, props in chars_ret.items(): for path, props in chars_ret.items():
print("\n\tCharacteristic: ", path) Utility.console_log("\n\tCharacteristic: " + str(path))
print("\tCharacteristic UUID: ", props[2]) Utility.console_log("\tCharacteristic UUID: " + str(props[2]))
print("\tValue: ", props[0]) Utility.console_log("\tValue: " + str(props[0]))
print("\tProperties: : ", props[1]) Utility.console_log("\tProperties: : " + str(props[1]))
else: else:
print("Failure: Read Characteristics failed")
ble_client_obj.disconnect() ble_client_obj.disconnect()
return raise RuntimeError("Failure: Read Characteristics failed")
''' '''
Write Characteristics Write Characteristics
@ -110,19 +109,32 @@ def bleprph_client_task(dut_addr, dut):
if chars_ret_on_write: if chars_ret_on_write:
Utility.console_log("\nCharacteristics after write operation") Utility.console_log("\nCharacteristics after write operation")
for path, props in chars_ret_on_write.items(): for path, props in chars_ret_on_write.items():
print("\n\tCharacteristic:", path) Utility.console_log("\n\tCharacteristic:" + str(path))
print("\tCharacteristic UUID: ", props[2]) Utility.console_log("\tCharacteristic UUID: " + str(props[2]))
print("\tValue:", props[0]) Utility.console_log("\tValue:" + str(props[0]))
print("\tProperties: : ", props[1]) Utility.console_log("\tProperties: : " + str(props[1]))
else: else:
print("Failure: Write Characteristics failed")
ble_client_obj.disconnect() ble_client_obj.disconnect()
return raise RuntimeError("Failure: Write Characteristics failed")
# Call disconnect to perform cleanup operations before exiting application # Call disconnect to perform cleanup operations before exiting application
ble_client_obj.disconnect() ble_client_obj.disconnect()
class BlePrphThread(threading.Thread):
def __init__(self, dut, dut_addr, exceptions_queue):
threading.Thread.__init__(self)
self.dut = dut
self.dut_addr = dut_addr
self.exceptions_queue = exceptions_queue
def run(self):
try:
bleprph_client_task(self, self.dut, self.dut_addr)
except Exception:
self.exceptions_queue.put(traceback.format_exc(), block=False)
@IDF.idf_example_test(env_tag="Example_WIFI_BT") @IDF.idf_example_test(env_tag="Example_WIFI_BT")
def test_example_app_ble_peripheral(env, extra_data): def test_example_app_ble_peripheral(env, extra_data):
""" """
@ -133,36 +145,47 @@ def test_example_app_ble_peripheral(env, extra_data):
4. Read Characteristics 4. Read Characteristics
5. Write Characteristics 5. Write Characteristics
""" """
try: subprocess.check_output(['rm','-rf','/var/lib/bluetooth/*'])
subprocess.check_output(['hciconfig','hci0','reset'])
# Acquire DUT # Acquire DUT
dut = env.get_dut("bleprph", "examples/bluetooth/nimble/bleprph") dut = env.get_dut("bleprph", "examples/bluetooth/nimble/bleprph")
# Get binary file # Get binary file
binary_file = os.path.join(dut.app.binary_path, "bleprph.bin") binary_file = os.path.join(dut.app.binary_path, "bleprph.bin")
bin_size = os.path.getsize(binary_file) bin_size = os.path.getsize(binary_file)
IDF.log_performance("bleprph_bin_size", "{}KB".format(bin_size // 1024)) IDF.log_performance("bleprph_bin_size", "{}KB".format(bin_size // 1024))
IDF.check_performance("bleprph_bin_size", bin_size // 1024) IDF.check_performance("bleprph_bin_size", bin_size // 1024)
# Upload binary and start testing # Upload binary and start testing
Utility.console_log("Starting bleprph simple example test app") Utility.console_log("Starting bleprph simple example test app")
dut.start_app() dut.start_app()
dut.reset()
subprocess.check_output(['rm','-rf','/var/lib/bluetooth/*']) # Get device address from dut
dut_addr = dut.expect(re.compile(r"Device Address: ([a-fA-F0-9:]+)"), timeout=30)[0]
# Get device address from dut exceptions_queue = Queue.Queue()
dut_addr = dut.expect(re.compile(r"Device Address: ([a-fA-F0-9:]+)"), timeout=30)[0] # Starting a py-client in a separate thread
bleprph_thread_obj = BlePrphThread(dut, dut_addr, exceptions_queue)
bleprph_thread_obj.start()
bleprph_thread_obj.join()
# Starting a py-client in a separate thread exception_msg = None
thread1 = Thread(target=bleprph_client_task, args=(dut_addr,dut,)) while True:
thread1.start() try:
thread1.join() exception_msg = exceptions_queue.get(block=False)
except Queue.Empty:
break
else:
Utility.console_log("\n" + exception_msg)
# Check dut responses if exception_msg:
dut.expect("connection established; status=0", timeout=30) raise Exception("Thread did not run successfully")
dut.expect("disconnect;", timeout=30)
except Exception as e: # Check dut responses
sys.exit(e) dut.expect("connection established; status=0", timeout=30)
dut.expect("disconnect;", timeout=30)
if __name__ == '__main__': if __name__ == '__main__':

View File

@ -20,6 +20,7 @@
from __future__ import print_function from __future__ import print_function
import sys import sys
import time import time
import traceback
try: try:
from future.moves.itertools import zip_longest from future.moves.itertools import zip_longest
@ -39,11 +40,11 @@ import lib_gap
srv_added_old_cnt = 0 srv_added_old_cnt = 0
srv_added_new_cnt = 0 srv_added_new_cnt = 0
verify_signal_check = 0
blecent_retry_check_cnt = 0 blecent_retry_check_cnt = 0
verify_service_cnt = 0 verify_service_cnt = 0
verify_readchars_cnt = 0 verify_readchars_cnt = 0
blecent_adv_uuid = '1811' blecent_adv_uuid = '1811'
iface_added = False
gatt_app_obj_check = False gatt_app_obj_check = False
gatt_app_reg_check = False gatt_app_reg_check = False
adv_data_check = False adv_data_check = False
@ -54,6 +55,7 @@ subscribe_req_check = False
ble_hr_chrc = False ble_hr_chrc = False
DISCOVERY_START = False DISCOVERY_START = False
SIGNAL_CAUGHT = False
TEST_CHECKS_PASS = False TEST_CHECKS_PASS = False
ADV_STOP = False ADV_STOP = False
@ -89,26 +91,42 @@ dbus.mainloop.glib.threads_init()
event_loop = GLib.MainLoop() event_loop = GLib.MainLoop()
def verify_signal_is_caught():
global verify_signal_check
verify_signal_check += 1
if (not SIGNAL_CAUGHT and verify_signal_check == 15) or (SIGNAL_CAUGHT):
if event_loop.is_running():
event_loop.quit()
return False # polling for checks will stop
return True # polling will continue
def set_props_status(props): def set_props_status(props):
""" """
Set Adapter status if it is powered on or off Set Adapter status if it is powered on or off
""" """
global ADAPTER_ON, SERVICES_RESOLVED, GATT_OBJ_REMOVED, GATT_APP_REGISTERED, \ global ADAPTER_ON, SERVICES_RESOLVED, GATT_OBJ_REMOVED, GATT_APP_REGISTERED, \
ADV_REGISTERED, ADV_ACTIVE_INSTANCE, DEVICE_CONNECTED, CHRC_VALUE, CHRC_VALUE_CNT ADV_REGISTERED, ADV_ACTIVE_INSTANCE, DEVICE_CONNECTED, CHRC_VALUE, CHRC_VALUE_CNT, \
SIGNAL_CAUGHT
is_service_uuid = False is_service_uuid = False
# Signal caught for change in Adapter Powered property # Signal caught for change in Adapter Powered property
if 'Powered' in props: if 'Powered' in props:
if props['Powered'] == 1: if props['Powered'] == 1:
SIGNAL_CAUGHT = True
ADAPTER_ON = True ADAPTER_ON = True
else: else:
SIGNAL_CAUGHT = True
ADAPTER_ON = False ADAPTER_ON = False
event_loop.quit() if 'ServicesResolved' in props:
elif 'ServicesResolved' in props:
if props['ServicesResolved'] == 1: if props['ServicesResolved'] == 1:
SIGNAL_CAUGHT = True
SERVICES_RESOLVED = True SERVICES_RESOLVED = True
else: else:
SIGNAL_CAUGHT = True
SERVICES_RESOLVED = False SERVICES_RESOLVED = False
elif 'UUIDs' in props: if 'UUIDs' in props:
# Signal caught for add/remove GATT data having service uuid # Signal caught for add/remove GATT data having service uuid
for uuid in props['UUIDs']: for uuid in props['UUIDs']:
if blecent_adv_uuid in uuid: if blecent_adv_uuid in uuid:
@ -118,7 +136,7 @@ def set_props_status(props):
# and for unregistering GATT application # and for unregistering GATT application
GATT_APP_REGISTERED = False GATT_APP_REGISTERED = False
lib_gatt.GATT_APP_OBJ = False lib_gatt.GATT_APP_OBJ = False
elif 'ActiveInstances' in props: if 'ActiveInstances' in props:
# Signal caught for Advertising - add/remove Instances property # Signal caught for Advertising - add/remove Instances property
if props['ActiveInstances'] == 1: if props['ActiveInstances'] == 1:
ADV_ACTIVE_INSTANCE = True ADV_ACTIVE_INSTANCE = True
@ -126,20 +144,24 @@ def set_props_status(props):
ADV_ACTIVE_INSTANCE = False ADV_ACTIVE_INSTANCE = False
ADV_REGISTERED = False ADV_REGISTERED = False
lib_gap.ADV_OBJ = False lib_gap.ADV_OBJ = False
elif 'Connected' in props: if 'Connected' in props:
# Signal caught for device connect/disconnect # Signal caught for device connect/disconnect
if props['Connected'] is True: if props['Connected'] == 1:
SIGNAL_CAUGHT = True
DEVICE_CONNECTED = True DEVICE_CONNECTED = True
event_loop.quit()
else: else:
SIGNAL_CAUGHT = True
DEVICE_CONNECTED = False DEVICE_CONNECTED = False
elif 'Value' in props: if 'Value' in props:
# Signal caught for change in chars value # Signal caught for change in chars value
if ble_hr_chrc: if ble_hr_chrc:
CHRC_VALUE_CNT += 1 CHRC_VALUE_CNT += 1
print(props['Value']) print(props['Value'])
if CHRC_VALUE_CNT == 10: if CHRC_VALUE_CNT == 10:
event_loop.quit() SIGNAL_CAUGHT = True
return False
return False
def props_change_handler(iface, changed_props, invalidated): def props_change_handler(iface, changed_props, invalidated):
@ -194,6 +216,9 @@ class BLE_Bluez_Client:
Discover Bluetooth Adapter Discover Bluetooth Adapter
Power On Bluetooth Adapter Power On Bluetooth Adapter
''' '''
global verify_signal_check, SIGNAL_CAUGHT, ADAPTER_ON
verify_signal_check = 0
ADAPTER_ON = False
try: try:
print("discovering adapter...") print("discovering adapter...")
for path, interfaces in self.ble_objs.items(): for path, interfaces in self.ble_objs.items():
@ -209,45 +234,45 @@ class BLE_Bluez_Client:
break break
if self.adapter is None: if self.adapter is None:
raise RuntimeError("\nError: bluetooth adapter not found") raise Exception("Bluetooth adapter not found")
if self.props_iface_obj is None: if self.props_iface_obj is None:
raise RuntimeError("\nError: properties interface not found") raise Exception("Properties interface not found")
print("bluetooth adapter discovered") print("bluetooth adapter discovered")
self.props_iface_obj.connect_to_signal('PropertiesChanged', props_change_handler)
# Check if adapter is already powered on # Check if adapter is already powered on
if ADAPTER_ON: if ADAPTER_ON:
print("bluetooth adapter is already on") print("Adapter already powered on")
return True return True
# Power On Adapter # Power On Adapter
print("powering on adapter...") print("powering on adapter...")
self.props_iface_obj.connect_to_signal('PropertiesChanged', props_change_handler)
self.props_iface_obj.Set(ADAPTER_IFACE, "Powered", dbus.Boolean(1)) self.props_iface_obj.Set(ADAPTER_IFACE, "Powered", dbus.Boolean(1))
SIGNAL_CAUGHT = False
GLib.timeout_add_seconds(5, verify_signal_is_caught)
event_loop.run() event_loop.run()
if ADAPTER_ON: if ADAPTER_ON:
print("bluetooth adapter powered on") print("bluetooth adapter powered on")
return True return True
else: else:
print("Failure: bluetooth adapter not powered on") raise Exception("Failure: bluetooth adapter not powered on")
return False
except Exception as e: except Exception:
print(e) print(traceback.format_exc())
sys.exit(1) return False
def connect(self): def connect(self):
''' '''
Connect to the device discovered Connect to the device discovered
Retry 10 times to discover and connect to device Retry 10 times to discover and connect to device
''' '''
global DISCOVERY_START global DISCOVERY_START, SIGNAL_CAUGHT, DEVICE_CONNECTED, verify_signal_check
device_found = False device_found = False
DEVICE_CONNECTED = False
try: try:
self.adapter.StartDiscovery() self.adapter.StartDiscovery()
print("\nStarted Discovery") print("\nStarted Discovery")
@ -255,6 +280,7 @@ class BLE_Bluez_Client:
DISCOVERY_START = True DISCOVERY_START = True
for retry_cnt in range(10,0,-1): for retry_cnt in range(10,0,-1):
verify_signal_check = 0
try: try:
if self.device is None: if self.device is None:
print("\nConnecting to device...") print("\nConnecting to device...")
@ -263,9 +289,15 @@ class BLE_Bluez_Client:
device_found = self.get_device() device_found = self.get_device()
if device_found: if device_found:
self.device.Connect(dbus_interface=DEVICE_IFACE) self.device.Connect(dbus_interface=DEVICE_IFACE)
event_loop.quit() time.sleep(15)
print("\nConnected to device") SIGNAL_CAUGHT = False
return True GLib.timeout_add_seconds(5, verify_signal_is_caught)
event_loop.run()
if DEVICE_CONNECTED:
print("\nConnected to device")
return True
else:
raise Exception
except Exception as e: except Exception as e:
print(e) print(e)
print("\nRetries left", retry_cnt - 1) print("\nRetries left", retry_cnt - 1)
@ -274,8 +306,8 @@ class BLE_Bluez_Client:
# Device not found # Device not found
return False return False
except Exception as e: except Exception:
print(e) print(traceback.format_exc())
self.device = None self.device = None
return False return False
@ -299,8 +331,7 @@ class BLE_Bluez_Client:
break break
if dev_path is None: if dev_path is None:
print("\nBLE device not found") raise Exception("\nBLE device not found")
return False
device_props_iface_obj = dbus.Interface(self.bus.get_object(BLUEZ_SERVICE_NAME, dev_path), DBUS_PROP_IFACE) device_props_iface_obj = dbus.Interface(self.bus.get_object(BLUEZ_SERVICE_NAME, dev_path), DBUS_PROP_IFACE)
device_props_iface_obj.connect_to_signal('PropertiesChanged', props_change_handler) device_props_iface_obj.connect_to_signal('PropertiesChanged', props_change_handler)
@ -321,16 +352,7 @@ class BLE_Bluez_Client:
if path not in self.services: if path not in self.services:
self.services.append(path) self.services.append(path)
def verify_get_services(self): def verify_service_uuid_found(self, service_uuid):
global SERVICE_SCAN_FAIL, verify_service_cnt
verify_service_cnt += 1
if iface_added and self.services and SERVICES_RESOLVED:
event_loop.quit()
if verify_service_cnt == 10:
event_loop.quit()
def verify_service_uuid_found(self):
''' '''
Verify service uuid found Verify service uuid found
''' '''
@ -340,40 +362,45 @@ class BLE_Bluez_Client:
if srv_uuid_found: if srv_uuid_found:
SERVICE_UUID_FOUND = True SERVICE_UUID_FOUND = True
def get_services(self, srv_uuid=None): def get_services(self, service_uuid=None):
''' '''
Retrieve Services found in the device connected Retrieve Services found in the device connected
''' '''
global service_uuid, iface_added, SERVICE_UUID_FOUND global SIGNAL_CAUGHT, SERVICE_UUID_FOUND, SERVICES_RESOLVED, verify_signal_check
service_uuid = srv_uuid verify_signal_check = 0
iface_added = False
SERVICE_UUID_FOUND = False SERVICE_UUID_FOUND = False
SERVICES_RESOLVED = False
SIGNAL_CAUGHT = False
try: try:
om_iface_obj = dbus.Interface(self.bus.get_object(BLUEZ_SERVICE_NAME, "/"), DBUS_OM_IFACE) om_iface_obj = dbus.Interface(self.bus.get_object(BLUEZ_SERVICE_NAME, "/"), DBUS_OM_IFACE)
self.ble_objs = om_iface_obj.GetManagedObjects() self.ble_objs = om_iface_obj.GetManagedObjects()
for path, interfaces in self.ble_objs.items(): for path, interfaces in self.ble_objs.items():
self.srvc_iface_added_handler(path, interfaces) self.srvc_iface_added_handler(path, interfaces)
# If services not found, then they may not have been added yet on dbus # If services not found, then they may not have been added yet on dbus
if not self.services: if not self.services:
iface_added = True GLib.timeout_add_seconds(5, verify_signal_is_caught)
GLib.timeout_add_seconds(2, self.verify_get_services)
om_iface_obj.connect_to_signal('InterfacesAdded', self.srvc_iface_added_handler) om_iface_obj.connect_to_signal('InterfacesAdded', self.srvc_iface_added_handler)
event_loop.run() event_loop.run()
if not SERVICES_RESOLVED:
raise Exception("Services not found...")
if service_uuid: if service_uuid:
self.verify_service_uuid_found() self.verify_service_uuid_found(service_uuid)
if not SERVICE_UUID_FOUND: if not SERVICE_UUID_FOUND:
raise Exception("Service with uuid: %s not found !!!" % service_uuid) raise Exception("Service with uuid: %s not found..." % service_uuid)
# Services found
return self.srv_uuid return self.srv_uuid
except Exception as e: except Exception:
print("Error: ", e) print(traceback.format_exc())
return False return False
def chrc_iface_added_handler(self, path, interfaces): def chrc_iface_added_handler(self, path, interfaces):
''' '''
Add services found as lib_ble_client obj Add services found as lib_ble_client obj
''' '''
global chrc, chrc_discovered global chrc, chrc_discovered, SIGNAL_CAUGHT
chrc_val = None chrc_val = None
if self.device and path.startswith(self.device.object_path): if self.device and path.startswith(self.device.object_path):
@ -386,22 +413,17 @@ class BLE_Bluez_Client:
chrc_val = chrc.ReadValue({}, dbus_interface=GATT_CHRC_IFACE) chrc_val = chrc.ReadValue({}, dbus_interface=GATT_CHRC_IFACE)
uuid = chrc_props['UUID'] uuid = chrc_props['UUID']
self.chars[path] = chrc_val, chrc_flags, uuid self.chars[path] = chrc_val, chrc_flags, uuid
SIGNAL_CAUGHT = True
def verify_get_chars(self):
global verify_readchars_cnt
verify_readchars_cnt += 1
if iface_added and self.chars:
event_loop.quit()
if verify_readchars_cnt == 10:
event_loop.quit()
def read_chars(self): def read_chars(self):
''' '''
Read characteristics found in the device connected Read characteristics found in the device connected
''' '''
global iface_added, chrc_discovered global iface_added, chrc_discovered, SIGNAL_CAUGHT, verify_signal_check
verify_signal_check = 0
chrc_discovered = False chrc_discovered = False
iface_added = False iface_added = False
SIGNAL_CAUGHT = False
try: try:
om_iface_obj = dbus.Interface(self.bus.get_object(BLUEZ_SERVICE_NAME, "/"), DBUS_OM_IFACE) om_iface_obj = dbus.Interface(self.bus.get_object(BLUEZ_SERVICE_NAME, "/"), DBUS_OM_IFACE)
@ -410,14 +432,15 @@ class BLE_Bluez_Client:
self.chrc_iface_added_handler(path, interfaces) self.chrc_iface_added_handler(path, interfaces)
# If chars not found, then they have not been added yet to interface # If chars not found, then they have not been added yet to interface
time.sleep(15)
if not self.chars: if not self.chars:
iface_added = True iface_added = True
GLib.timeout_add_seconds(2, self.verify_get_chars) GLib.timeout_add_seconds(5, verify_signal_is_caught)
om_iface_obj.connect_to_signal('InterfacesAdded', self.chars_iface_added_handler) om_iface_obj.connect_to_signal('InterfacesAdded', self.chars_iface_added_handler)
event_loop.run() event_loop.run()
return self.chars return self.chars
except Exception as e: except Exception:
print("Error: ", e) print(traceback.format_exc())
return False return False
def write_chars(self, write_val): def write_chars(self, write_val):
@ -443,12 +466,11 @@ class BLE_Bluez_Client:
return False return False
self.chars[path] = chrc_val, props[1], props[2] # update value self.chars[path] = chrc_val, props[1], props[2] # update value
if not char_write_props: if not char_write_props:
print("Failure: Cannot perform write operation. Characteristic does not have write permission.") raise Exception("Failure: Cannot perform write operation. Characteristic does not have write permission.")
return False
return self.chars return self.chars
except Exception as e: except Exception:
print(e) print(traceback.format_exc())
return False return False
def hr_update_simulation(self, hr_srv_uuid, hr_char_uuid): def hr_update_simulation(self, hr_srv_uuid, hr_char_uuid):
@ -457,7 +479,7 @@ class BLE_Bluez_Client:
Retrieve updated value Retrieve updated value
Stop Notifications Stop Notifications
''' '''
global ble_hr_chrc global ble_hr_chrc, verify_signal_check, SIGNAL_CAUGHT, CHRC_VALUE_CNT
srv_path = None srv_path = None
chrc = None chrc = None
@ -465,6 +487,7 @@ class BLE_Bluez_Client:
chrc_path = None chrc_path = None
chars_ret = None chars_ret = None
ble_hr_chrc = True ble_hr_chrc = True
CHRC_VALUE_CNT = 0
try: try:
# Get HR Measurement characteristic # Get HR Measurement characteristic
@ -475,8 +498,7 @@ class BLE_Bluez_Client:
break break
if srv_path is None: if srv_path is None:
print("Failure: HR UUID:", hr_srv_uuid, "not found") raise Exception("Failure: HR UUID:", hr_srv_uuid, "not found")
return False
chars_ret = self.read_chars() chars_ret = self.read_chars()
@ -487,8 +509,8 @@ class BLE_Bluez_Client:
if hr_char_uuid in props[2]: # uuid if hr_char_uuid in props[2]: # uuid
break break
if chrc is None: if chrc is None:
print("Failure: Characteristics for service: ", srv_path, "not found") raise Exception("Failure: Characteristics for service: ", srv_path, "not found")
return False
# Subscribe to notifications # Subscribe to notifications
print("\nSubscribe to notifications: On") print("\nSubscribe to notifications: On")
chrc.StartNotify(dbus_interface=GATT_CHRC_IFACE) chrc.StartNotify(dbus_interface=GATT_CHRC_IFACE)
@ -496,6 +518,9 @@ class BLE_Bluez_Client:
chrc_props_iface_obj = dbus.Interface(self.bus.get_object(BLUEZ_SERVICE_NAME, chrc_path), DBUS_PROP_IFACE) chrc_props_iface_obj = dbus.Interface(self.bus.get_object(BLUEZ_SERVICE_NAME, chrc_path), DBUS_PROP_IFACE)
chrc_props_iface_obj.connect_to_signal('PropertiesChanged', props_change_handler) chrc_props_iface_obj.connect_to_signal('PropertiesChanged', props_change_handler)
SIGNAL_CAUGHT = False
verify_signal_check = 0
GLib.timeout_add_seconds(5, verify_signal_is_caught)
event_loop.run() event_loop.run()
chrc.StopNotify(dbus_interface=GATT_CHRC_IFACE) chrc.StopNotify(dbus_interface=GATT_CHRC_IFACE)
time.sleep(2) time.sleep(2)
@ -504,8 +529,8 @@ class BLE_Bluez_Client:
ble_hr_chrc = False ble_hr_chrc = False
return True return True
except Exception as e: except Exception:
print(e) print(traceback.format_exc())
return False return False
def create_gatt_app(self): def create_gatt_app(self):
@ -513,10 +538,12 @@ class BLE_Bluez_Client:
Create GATT data Create GATT data
Register GATT Application Register GATT Application
''' '''
global gatt_app_obj, gatt_manager_iface_obj global gatt_app_obj, gatt_manager_iface_obj, GATT_APP_REGISTERED
gatt_app_obj = None gatt_app_obj = None
gatt_manager_iface_obj = None gatt_manager_iface_obj = None
GATT_APP_REGISTERED = False
lib_gatt.GATT_APP_OBJ = False
try: try:
gatt_app_obj = lib_gatt.Application(self.bus, self.adapter_path[0]) gatt_app_obj = lib_gatt.Application(self.bus, self.adapter_path[0])
@ -526,8 +553,8 @@ class BLE_Bluez_Client:
reply_handler=self.gatt_app_handler, reply_handler=self.gatt_app_handler,
error_handler=self.gatt_app_error_handler) error_handler=self.gatt_app_error_handler)
return True return True
except Exception as e: except Exception:
print(e) print(traceback.format_exc())
return False return False
def gatt_app_handler(self): def gatt_app_handler(self):
@ -550,25 +577,28 @@ class BLE_Bluez_Client:
Register Advertisement Register Advertisement
Start Advertising Start Advertising
''' '''
global le_adv_obj, le_adv_manager_iface_obj global le_adv_obj, le_adv_manager_iface_obj, ADV_ACTIVE_INSTANCE, ADV_REGISTERED
le_adv_obj = None le_adv_obj = None
le_adv_manager_iface_obj = None le_adv_manager_iface_obj = None
le_adv_iface_path = None le_adv_iface_path = None
ADV_ACTIVE_INSTANCE = False
ADV_REGISTERED = False
lib_gap.ADV_OBJ = False
try: try:
print("Advertising started") print("Advertising started")
gatt_app_ret = self.create_gatt_app() gatt_app_ret = self.create_gatt_app()
if not gatt_app_ret: if not gatt_app_ret:
return False raise Exception
for path,interface in self.ble_objs.items(): for path,interface in self.ble_objs.items():
if LE_ADVERTISING_MANAGER_IFACE in interface: if LE_ADVERTISING_MANAGER_IFACE in interface:
le_adv_iface_path = path le_adv_iface_path = path
if le_adv_iface_path is None: if le_adv_iface_path is None:
print('\n Cannot start advertising. LEAdvertisingManager1 Interface not found') raise Exception('\n Cannot start advertising. LEAdvertisingManager1 Interface not found')
return False
le_adv_obj = lib_gap.Advertisement(self.bus, adv_iface_index, adv_type, adv_uuid, adv_host_name) le_adv_obj = lib_gap.Advertisement(self.bus, adv_iface_index, adv_type, adv_uuid, adv_host_name)
le_adv_manager_iface_obj = dbus.Interface(self.bus.get_object(BLUEZ_SERVICE_NAME, le_adv_iface_path), LE_ADVERTISING_MANAGER_IFACE) le_adv_manager_iface_obj = dbus.Interface(self.bus.get_object(BLUEZ_SERVICE_NAME, le_adv_iface_path), LE_ADVERTISING_MANAGER_IFACE)
@ -583,11 +613,10 @@ class BLE_Bluez_Client:
if TEST_CHECKS_PASS: if TEST_CHECKS_PASS:
return True return True
else: else:
return False raise Exception
except Exception as e: except Exception:
print("in Exception") print(traceback.format_exc())
print(e)
return False return False
def adv_handler(self): def adv_handler(self):
@ -646,39 +675,41 @@ class BLE_Bluez_Client:
TEST_CHECKS_PASS = False TEST_CHECKS_PASS = False
if subscribe_req_check: if subscribe_req_check:
lib_gatt.alert_status_char_obj.StopNotify() lib_gatt.alert_status_char_obj.StopNotify()
event_loop.quit() else:
return False # polling for checks will stop # Check for success
if not gatt_app_obj_check and lib_gatt.GATT_APP_OBJ:
print("GATT Data created")
gatt_app_obj_check = True
if not gatt_app_reg_check and GATT_APP_REGISTERED:
print("GATT Application registered")
gatt_app_reg_check = True
if not adv_data_check and lib_gap.ADV_OBJ:
print("Advertising data created")
adv_data_check = True
if not adv_reg_check and ADV_REGISTERED and ADV_ACTIVE_INSTANCE:
print("Advertisement registered")
adv_reg_check = True
if not read_req_check and lib_gatt.CHAR_READ:
read_req_check = True
if not write_req_check and lib_gatt.CHAR_WRITE:
write_req_check = True
if not subscribe_req_check and lib_gatt.CHAR_SUBSCRIBE:
subscribe_req_check = True
# Check for success
if not gatt_app_obj_check and lib_gatt.GATT_APP_OBJ:
print("GATT Data created")
gatt_app_obj_check = True
if not gatt_app_reg_check and GATT_APP_REGISTERED:
print("GATT Application registered")
gatt_app_reg_check = True
if not adv_data_check and lib_gap.ADV_OBJ:
print("Advertising data created")
adv_data_check = True
if not adv_reg_check and ADV_REGISTERED and ADV_ACTIVE_INSTANCE:
print("Advertisement registered")
adv_reg_check = True
if not read_req_check and lib_gatt.CHAR_READ:
read_req_check = True
if not write_req_check and lib_gatt.CHAR_WRITE:
write_req_check = True
if not subscribe_req_check and lib_gatt.CHAR_SUBSCRIBE:
subscribe_req_check = True
# Increment retry count
blecent_retry_check_cnt += 1
if read_req_check and write_req_check and subscribe_req_check: if read_req_check and write_req_check and subscribe_req_check:
# all checks passed # all checks passed
# Blecent Test passed # Blecent Test passed
TEST_CHECKS_PASS = True TEST_CHECKS_PASS = True
lib_gatt.alert_status_char_obj.StopNotify() lib_gatt.alert_status_char_obj.StopNotify()
event_loop.quit()
if (blecent_retry_check_cnt == 10 or TEST_CHECKS_PASS):
if event_loop.is_running():
event_loop.quit()
return False # polling for checks will stop return False # polling for checks will stop
# Increment retry count
blecent_retry_check_cnt += 1
# Default return True - polling for checks will continue # Default return True - polling for checks will continue
return True return True
@ -709,29 +740,29 @@ class BLE_Bluez_Client:
# Blecent Test failed # Blecent Test failed
ADV_STOP = False ADV_STOP = False
event_loop.quit() else:
return False # polling for checks will stop # Check for success
if not gatt_app_obj_check and not lib_gatt.GATT_APP_OBJ:
print("GATT Data removed")
gatt_app_obj_check = True
if not gatt_app_reg_check and not GATT_APP_REGISTERED:
print("GATT Application unregistered")
gatt_app_reg_check = True
if not adv_data_check and not adv_reg_check and not (ADV_REGISTERED or ADV_ACTIVE_INSTANCE or lib_gap.ADV_OBJ):
print("Advertising data removed")
print("Advertisement unregistered")
adv_data_check = True
adv_reg_check = True
# all checks passed
ADV_STOP = True
# Check for success if (blecent_retry_check_cnt == 10 or ADV_STOP):
if not gatt_app_obj_check and not lib_gatt.GATT_APP_OBJ: if event_loop.is_running():
print("GATT Data removed") event_loop.quit()
gatt_app_obj_check = True return False # polling for checks will stop
if not gatt_app_reg_check and not GATT_APP_REGISTERED:
print("GATT Application unregistered")
gatt_app_reg_check = True
if not adv_data_check and not adv_reg_check and not (ADV_REGISTERED or ADV_ACTIVE_INSTANCE or lib_gap.ADV_OBJ):
print("Advertising data removed")
print("Advertisement unregistered")
adv_data_check = True
adv_reg_check = True
# Increment retry count # Increment retry count
blecent_retry_check_cnt += 1 blecent_retry_check_cnt += 1
if adv_reg_check:
# all checks passed
ADV_STOP = True
event_loop.quit()
return False # polling for checks will stop
# Default return True - polling for checks will continue # Default return True - polling for checks will continue
return True return True
@ -747,11 +778,14 @@ class BLE_Bluez_Client:
Adapter is powered off Adapter is powered off
''' '''
try: try:
global blecent_retry_check_cnt, DISCOVERY_START global blecent_retry_check_cnt, DISCOVERY_START, verify_signal_check, SIGNAL_CAUGHT
blecent_retry_check_cnt = 0 blecent_retry_check_cnt = 0
verify_signal_check = 0
print("\nexiting from test...") print("\nexiting from test...")
self.props_iface_obj.connect_to_signal('PropertiesChanged', props_change_handler)
if ADV_REGISTERED: if ADV_REGISTERED:
# Unregister Advertisement # Unregister Advertisement
le_adv_manager_iface_obj.UnregisterAdvertisement(le_adv_obj.get_path()) le_adv_manager_iface_obj.UnregisterAdvertisement(le_adv_obj.get_path())
@ -766,7 +800,7 @@ class BLE_Bluez_Client:
# Remove GATT data # Remove GATT data
dbus.service.Object.remove_from_connection(gatt_app_obj) dbus.service.Object.remove_from_connection(gatt_app_obj)
GLib.timeout_add_seconds(2, self.verify_blecent_disconnect) GLib.timeout_add_seconds(5, self.verify_blecent_disconnect)
event_loop.run() event_loop.run()
if ADV_STOP: if ADV_STOP:
@ -784,9 +818,10 @@ class BLE_Bluez_Client:
if DISCOVERY_START: if DISCOVERY_START:
self.adapter.StopDiscovery() self.adapter.StopDiscovery()
DISCOVERY_START = False DISCOVERY_START = False
time.sleep(15)
# Power off Adapter SIGNAL_CAUGHT = False
self.props_iface_obj.Set(ADAPTER_IFACE, "Powered", dbus.Boolean(0)) GLib.timeout_add_seconds(5, verify_signal_is_caught)
event_loop.run() event_loop.run()
if not DEVICE_CONNECTED: if not DEVICE_CONNECTED:
@ -794,12 +829,6 @@ class BLE_Bluez_Client:
else: else:
print("Warning: device could not be disconnected") print("Warning: device could not be disconnected")
print("powering off adapter...") except Exception:
if not ADAPTER_ON: print(traceback.format_exc())
print("bluetooth adapter powered off")
else:
print("\nWarning: Bluetooth adapter not powered off")
except Exception as e:
print(e)
return False return False