diff --git "a/docs/API_reference/zh/QuecPython\347\261\273\345\272\223/README.md" "b/docs/API_reference/zh/QuecPython\347\261\273\345\272\223/README.md"
index 9ea8865d7222711c18be7d86252565e15038926f..93cb48befa413deb1581c7d47bd0c281e645b8a8 100644
--- "a/docs/API_reference/zh/QuecPython\347\261\273\345\272\223/README.md"
+++ "b/docs/API_reference/zh/QuecPython\347\261\273\345\272\223/README.md"
@@ -28,5 +28,7 @@
- [quecgnss - 内置GNSS相关功能](./quecgnss.md)
- [gnss - GNSS相关功能](./gnss.md)
- [securedata - 安全数据区相关功能](./securedata.md)
+- [ble- 低功耗蓝牙相关功能](./ble.md)
+- [bt- 经典蓝牙相关功能](./bt.md)
diff --git "a/docs/API_reference/zh/QuecPython\347\261\273\345\272\223/app_fota.md" "b/docs/API_reference/zh/QuecPython\347\261\273\345\272\223/app_fota.md"
index e1bb5cdf95cc84aa7294bdb221d16739b01f8db4..e2ca42dc23a381b98788320a5b3ec50412d05779 100644
--- "a/docs/API_reference/zh/QuecPython\347\261\273\345\272\223/app_fota.md"
+++ "b/docs/API_reference/zh/QuecPython\347\261\273\345\272\223/app_fota.md"
@@ -69,7 +69,7 @@ fota.bulk_download(info=[])
**返回值描述**:
-- 返回下载失败的列表,类型为list。
+- 下载失败时返回下载失败的列表,类型为list。下载成功时返回空。
**示例**:
diff --git "a/docs/API_reference/zh/QuecPython\347\261\273\345\272\223/ble.md" "b/docs/API_reference/zh/QuecPython\347\261\273\345\272\223/ble.md"
new file mode 100644
index 0000000000000000000000000000000000000000..9104a6430acd074bc1778d13c922d4bd2d5028c0
--- /dev/null
+++ "b/docs/API_reference/zh/QuecPython\347\261\273\345\272\223/ble.md"
@@ -0,0 +1,2328 @@
+# ble-低功耗蓝牙相关功能
+
+`ble`模块用于提供BLE GATT Server (从机)与 Client (主机)功能,基于BLE 4.2协议。
+
+**示例**:
+
+```python
+#BLE Server
+
+import ble
+import utime
+
+
+BLE_GATT_SYS_SERVICE = 0 # 0-删除系统默认的GAP和GATT服务 1-保留系统默认的GAP和GATT服务
+BLE_SERVER_HANDLE = 0
+_BLE_NAME = "Quectel_ble"
+
+
+event_dict = {
+ 'BLE_START_STATUS_IND': 0, # ble start
+ 'BLE_STOP_STATUS_IND': 1, # ble stop
+ 'BLE_CONNECT_IND': 16, # ble connect
+ 'BLE_DISCONNECT_IND': 17, # ble disconnect
+ 'BLE_UPDATE_CONN_PARAM_IND': 18, # ble update connection parameter
+ 'BLE_SCAN_REPORT_IND': 19, # ble gatt client scan and report other devices
+ 'BLE_GATT_MTU': 20, # ble connection mtu
+ 'BLE_GATT_RECV_WRITE_IND': 21, # when ble client write characteristic value or descriptor,server get the notice
+ 'BLE_GATT_RECV_READ_IND': 22, # when ble client read characteristic value or descriptor,server get the notice
+ 'BLE_GATT_RECV_NOTIFICATION_IND': 23, # client receive notification
+ 'BLE_GATT_RECV_INDICATION_IND': 24, # client receive indication
+ 'BLE_GATT_SEND_END': 25, # server send notification,and receive send end notice
+}
+
+class EVENT(dict):
+ def __getattr__(self, item):
+ return self[item]
+
+ def __setattr__(self, key, value):
+ raise ValueError("{} is read-only.".format(key))
+
+
+event = EVENT(event_dict)
+
+
+def ble_callback(args):
+ global BLE_GATT_SYS_SERVICE
+ global BLE_SERVER_HANDLE
+ event_id = args[0]
+ status = args[1]
+ print('[ble_callback]: event_id={}, status={}'.format(event_id, status))
+
+ if event_id == event.BLE_START_STATUS_IND: # ble start
+ if status == 0:
+ print('[callback] BLE start success.')
+ mac = ble.getPublicAddr()
+ if mac != -1 and len(mac) == 6:
+ addr = '{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}'.format(mac[5], mac[4], mac[3], mac[2], mac[1], mac[0])
+ print('BLE public addr : {}'.format(addr))
+ ret = ble_gatt_set_name()
+ if ret != 0:
+ ble_gatt_close()
+ return
+ ret = ble_gatt_set_param()
+ if ret != 0:
+ ble_gatt_close()
+ return
+ ret = ble_gatt_set_data()
+ if ret != 0:
+ ble_gatt_close()
+ return
+ ret = ble_gatt_set_rsp_data()
+ if ret != 0:
+ ble_gatt_close()
+ return
+ ret = ble_gatt_add_service()
+ if ret != 0:
+ ble_gatt_close()
+ return
+ ret = ble_gatt_add_characteristic()
+ if ret != 0:
+ ble_gatt_close()
+ return
+ ret = ble_gatt_add_characteristic_value()
+ if ret != 0:
+ ble_gatt_close()
+ return
+ ret = ble_gatt_add_characteristic_desc()
+ if ret != 0:
+ ble_gatt_close()
+ return
+ ret = ble_gatt_add_service_complete()
+ if ret != 0:
+ ble_gatt_close()
+ return
+ if BLE_GATT_SYS_SERVICE == 0:
+ BLE_SERVER_HANDLE = 1
+ else:
+ BLE_SERVER_HANDLE = 16
+ ret = ble_adv_start()
+ if ret != 0:
+ ble_gatt_close()
+ return
+ else:
+ print('[callback] BLE start failed.')
+ elif event_id == event.BLE_STOP_STATUS_IND: # ble stop
+ if status == 0:
+ print('[callback] ble stop successful.')
+ ble_status = ble.getStatus()
+ print('ble status is {}'.format(ble_status))
+ ble_gatt_server_release()
+ else:
+ print('[callback] ble stop failed.')
+ elif event_id == event.BLE_CONNECT_IND: # ble connect
+ if status == 0:
+ print('[callback] ble connect successful.')
+ connect_id = args[2]
+ addr = args[3]
+ addr_str = '{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}'.format(addr[0], addr[1], addr[2], addr[3], addr[4], addr[5])
+ print('[callback] connect_id = {}, addr = {}'.format(connect_id, addr_str))
+
+ ret = ble_gatt_send_notification()
+ if ret == 0:
+ print('[callback] ble_gatt_send_notification successful.')
+ else:
+ print('[callback] ble_gatt_send_notification failed.')
+ ble_gatt_close()
+ return
+ else:
+ print('[callback] ble connect failed.')
+ elif event_id == event.BLE_DISCONNECT_IND: # ble disconnect
+ if status == 0:
+ print('[callback] ble disconnect successful.')
+ connect_id = args[2]
+ addr = args[3]
+ addr_str = '{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}'.format(addr[0], addr[1], addr[2], addr[3], addr[4], addr[5])
+ ble_gatt_close()
+ print('[callback] connect_id = {}, addr = {}'.format(connect_id, addr_str))
+ else:
+ print('[callback] ble disconnect failed.')
+ ble_gatt_close()
+ return
+ elif event_id == event.BLE_UPDATE_CONN_PARAM_IND: # ble update connection parameter
+ if status == 0:
+ print('[callback] ble update parameter successful.')
+ connect_id = args[2]
+ max_interval = args[3]
+ min_interval = args[4]
+ latency = args[5]
+ timeout = args[6]
+ print('[callback] connect_id={},max_interval={},min_interval={},latency={},timeout={}'.format(connect_id, max_interval, min_interval, latency, timeout))
+ else:
+ print('[callback] ble update parameter failed.')
+ ble_gatt_close()
+ return
+ elif event_id == event.BLE_GATT_MTU: # ble connection mtu
+ if status == 0:
+ print('[callback] ble connect mtu successful.')
+ handle = args[2]
+ ble_mtu = args[3]
+ print('[callback] handle = {:#06x}, ble_mtu = {}'.format(handle, ble_mtu))
+ else:
+ print('[callback] ble connect mtu failed.')
+ ble_gatt_close()
+ return
+ elif event_id == event.BLE_GATT_RECV_WRITE_IND:
+ if status == 0:
+ print('[callback] ble recv successful.')
+ data_len = args[2]
+ data = args[3] # 这是一个bytearray
+ attr_handle = args[4]
+ short_uuid = args[5]
+ long_uuid = args[6] # 这是一个bytearray
+ print('len={}, data:{}'.format(data_len, data))
+ print('attr_handle = {:#06x}'.format(attr_handle))
+ print('short uuid = {:#06x}'.format(short_uuid))
+ print('long uuid = {}'.format(long_uuid))
+ else:
+ print('[callback] ble recv failed.')
+ ble_gatt_close()
+ return
+ elif event_id == event.BLE_GATT_RECV_READ_IND:
+ if status == 0:
+ print('[callback] ble recv read successful.')
+ data_len = args[2]
+ data = args[3] # 这是一个bytearray
+ attr_handle = args[4]
+ short_uuid = args[5]
+ long_uuid = args[6] # 这是一个bytearray
+ print('len={}, data:{}'.format(data_len, data))
+ print('attr_handle = {:#06x}'.format(attr_handle))
+ print('short uuid = {:#06x}'.format(short_uuid))
+ print('long uuid = {}'.format(long_uuid))
+ else:
+ print('[callback] ble recv read failed.')
+ ble_gatt_close()
+ return
+ elif event_id == event.BLE_GATT_SEND_END:
+ if status == 0:
+ print('[callback] ble send data successful.')
+ else:
+ print('[callback] ble send data failed.')
+ else:
+ print('unknown event id.')
+
+
+def ble_gatt_server_init(cb):
+ ret = ble.serverInit(cb)
+ if ret != 0:
+ print('ble_gatt_server_init failed.')
+ return -1
+ print('ble_gatt_server_init success.')
+ return 0
+
+
+def ble_gatt_server_release():
+ ret = ble.serverRelease()
+ if ret != 0:
+ print('ble_gatt_server_release failed.')
+ return -1
+ print('ble_gatt_server_release success.')
+ return 0
+
+
+def ble_gatt_open():
+ ret = ble.gattStart()
+ if ret != 0:
+ print('ble_gatt_open failed.')
+ return -1
+ print('ble_gatt_open success.')
+ return 0
+
+
+def ble_gatt_close():
+ ret = ble.gattStop()
+ if ret != 0:
+ print('ble_gatt_close failed.')
+ return -1
+ print('ble_gatt_close success.')
+ return 0
+
+
+def ble_gatt_set_name():
+ code = 0 # utf8
+ name = _BLE_NAME
+ ret = ble.setLocalName(code, name)
+ if ret != 0:
+ print('ble_gatt_set_name failed.')
+ return -1
+ print('ble_gatt_set_name success.')
+ return 0
+
+
+def ble_gatt_set_param():
+ min_adv = 0x300
+ max_adv = 0x320
+ adv_type = 0 # 可连接的非定向广播,默认选择
+ addr_type = 0 # 公共地址
+ channel = 0x07
+ filter_strategy = 0 # 处理所有设备的扫描和连接请求
+ discov_mode = 2
+ no_br_edr = 1
+ enable_adv = 1
+ ret = ble.setAdvParam(min_adv, max_adv, adv_type, addr_type, channel, filter_strategy, discov_mode, no_br_edr, enable_adv)
+ if ret != 0:
+ print('ble_gatt_set_param failed.')
+ return -1
+ print('ble_gatt_set_param success.')
+ return 0
+
+
+def ble_gatt_set_data():
+ adv_data = [0x02, 0x01, 0x05]
+ ble_name = _BLE_NAME
+ length = len(ble_name) + 1
+ adv_data.append(length)
+ adv_data.append(0x09)
+ name_encode = ble_name.encode('UTF-8')
+ for i in range(0, len(name_encode)):
+ adv_data.append(name_encode[i])
+ print('set adv_data:{}'.format(adv_data))
+ data = bytearray(adv_data)
+ ret = ble.setAdvData(data)
+ if ret != 0:
+ print('ble_gatt_set_data failed.')
+ return -1
+ print('ble_gatt_set_data success.')
+ return 0
+
+
+def ble_gatt_set_rsp_data():
+ adv_data = []
+ ble_name = _BLE_NAME
+ length = len(ble_name) + 1
+ adv_data.append(length)
+ adv_data.append(0x09)
+ name_encode = ble_name.encode('UTF-8')
+ for i in range(0, len(name_encode)):
+ adv_data.append(name_encode[i])
+ print('set adv_rsp_data:{}'.format(adv_data))
+ data = bytearray(adv_data)
+ ret = ble.setAdvRspData(data)
+ if ret != 0:
+ print('ble_gatt_set_rsp_data failed.')
+ return -1
+ print('ble_gatt_set_rsp_data success.')
+ return 0
+
+
+def ble_gatt_add_service():
+ primary = 1
+ server_id = 0x01
+ uuid_type = 1 # 短UUID
+ uuid_s = 0x180F
+ uuid_l = bytearray([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])
+ ret = ble.addService(primary, server_id, uuid_type, uuid_s, uuid_l)
+ if ret != 0:
+ print('ble_gatt_add_service failed.')
+ return -1
+ print('ble_gatt_add_service success.')
+ return 0
+
+
+def ble_gatt_add_characteristic():
+ server_id = 0x01
+ chara_id = 0x01
+ chara_prop = 0x02 | 0x10 | 0x20 # 0x02-可读 0x10-通知 0x20-指示
+ uuid_type = 1 # 短UUID
+ uuid_s = 0x2A19
+ uuid_l = bytearray([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])
+ ret = ble.addChara(server_id, chara_id, chara_prop, uuid_type, uuid_s, uuid_l)
+ if ret != 0:
+ print('ble_gatt_add_characteristic failed.')
+ return -1
+ print('ble_gatt_add_characteristic success.')
+ return 0
+
+
+def ble_gatt_add_characteristic_value():
+ data = []
+ server_id = 0x01
+ chara_id = 0x01
+ permission = 0x0001 | 0x0002
+ uuid_type = 1 # 短UUID
+ uuid_s = 0x2A19
+ uuid_l = bytearray([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])
+ for i in range(0, 244):
+ data.append(0x00)
+ value = bytearray(data)
+ ret = ble.addCharaValue(server_id, chara_id, permission, uuid_type, uuid_s, uuid_l, value)
+ if ret != 0:
+ print('ble_gatt_add_characteristic_value failed.')
+ return -1
+ print('ble_gatt_add_characteristic_value success.')
+ return 0
+
+
+def ble_gatt_add_characteristic_desc():
+ data = [0x00, 0x00]
+ server_id = 0x01
+ chara_id = 0x01
+ permission = 0x0001 | 0x0002
+ uuid_type = 1 # 短UUID
+ uuid_s = 0x2902
+ uuid_l = bytearray([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])
+ value = bytearray(data)
+ ret = ble.addCharaDesc(server_id, chara_id, permission, uuid_type, uuid_s, uuid_l, value)
+ if ret != 0:
+ print('ble_gatt_add_characteristic_desc failed.')
+ return -1
+ print('ble_gatt_add_characteristic_desc success.')
+ return 0
+
+
+def ble_gatt_send_notification():
+ global BLE_SERVER_HANDLE
+ data = [0x39, 0x39, 0x39, 0x39, 0x39] # 测试数据
+ conn_id = 0
+ attr_handle = BLE_SERVER_HANDLE + 2
+ value = bytearray(data)
+ ret = ble.sendNotification(conn_id, attr_handle, value)
+ if ret != 0:
+ print('ble_gatt_send_notification failed.')
+ return -1
+ print('ble_gatt_send_notification success.')
+ return 0
+
+
+def ble_gatt_add_service_complete():
+ global BLE_GATT_SYS_SERVICE
+ ret = ble.addOrClearService(1, BLE_GATT_SYS_SERVICE)
+ if ret != 0:
+ print('ble_gatt_add_service_complete failed.')
+ return -1
+ print('ble_gatt_add_service_complete success.')
+ return 0
+
+
+def ble_gatt_clear_service_complete():
+ global BLE_GATT_SYS_SERVICE
+ ret = ble.addOrClearService(0, BLE_GATT_SYS_SERVICE)
+ if ret != 0:
+ print('ble_gatt_clear_service_complete failed.')
+ return -1
+ print('ble_gatt_clear_service_complete success.')
+ return 0
+
+
+def ble_adv_start():
+ ret = ble.advStart()
+ if ret != 0:
+ print('ble_adv_start failed.')
+ return -1
+ print('ble_adv_start success.')
+ return 0
+
+
+def ble_adv_stop():
+ ret = ble.advStop()
+ if ret != 0:
+ print('ble_adv_stop failed.')
+ return -1
+ print('ble_adv_stop success.')
+ return 0
+
+
+def main():
+ ret = ble_gatt_server_init(ble_callback)
+ if ret == 0:
+ ret = ble_gatt_open()
+ if ret != 0:
+ return -1
+ else:
+ return -1
+ count = 0
+ while True:
+ utime.sleep(1)
+ count += 1
+ if count % 5 == 0:
+ print('##### BLE running, count = {}......'.format(count))
+ if count > 120:
+ count = 0
+ print('!!!!! stop BLE now !!!!!')
+ ble_gatt_close()
+ return 0
+
+
+if __name__ == '__main__':
+ main()
+
+```
+
+```python
+#BLE Client
+
+import ble
+import utime
+import _thread
+import checkNet
+from queue import Queue
+
+PROJECT_NAME = "QuecPython_BLE_Client_Example"
+PROJECT_VERSION = "1.0.0"
+checknet = checkNet.CheckNetwork(PROJECT_NAME, PROJECT_VERSION)
+
+event_dict = {
+ 'BLE_START_STATUS_IND': 0, # ble start
+ 'BLE_STOP_STATUS_IND': 1, # ble stop
+ 'BLE_CONNECT_IND': 16, # ble connect
+ 'BLE_DISCONNECT_IND': 17, # ble disconnect
+ 'BLE_UPDATE_CONN_PARAM_IND': 18, # ble update connection parameter
+ 'BLE_SCAN_REPORT_IND': 19, # ble gatt client scan and report other devices
+ 'BLE_GATT_MTU': 20, # ble connection mtu
+ 'BLE_GATT_RECV_NOTIFICATION_IND': 23, # client receive notification
+ 'BLE_GATT_RECV_INDICATION_IND': 24, # client receive indication
+ 'BLE_GATT_START_DISCOVER_SERVICE_IND': 26, # start discover service
+ 'BLE_GATT_DISCOVER_SERVICE_IND': 27, # discover service
+ 'BLE_GATT_DISCOVER_CHARACTERISTIC_DATA_IND': 28, # discover characteristic
+ 'BLE_GATT_DISCOVER_CHARA_DESC_IND': 29, # discover characteristic descriptor
+ 'BLE_GATT_CHARA_WRITE_WITH_RSP_IND': 30, # write characteristic value with response
+ 'BLE_GATT_CHARA_WRITE_WITHOUT_RSP_IND': 31, # write characteristic value without response
+ 'BLE_GATT_CHARA_READ_IND': 32, # read characteristic value by handle
+ 'BLE_GATT_CHARA_READ_BY_UUID_IND': 33, # read characteristic value by uuid
+ 'BLE_GATT_CHARA_MULTI_READ_IND': 34, # read multiple characteristic value
+ 'BLE_GATT_DESC_WRITE_WITH_RSP_IND': 35, # write characteristic descriptor
+ 'BLE_GATT_DESC_READ_IND': 36, # read characteristic descriptor
+ 'BLE_GATT_ATT_ERROR_IND': 37, # attribute error
+}
+
+gatt_status_dict = {
+ 'BLE_GATT_IDLE' : 0,
+ 'BLE_GATT_DISCOVER_SERVICE': 1,
+ 'BLE_GATT_DISCOVER_INCLUDES': 2,
+ 'BLE_GATT_DISCOVER_CHARACTERISTIC': 3,
+ 'BLE_GATT_WRITE_CHARA_VALUE': 4,
+ 'BLE_GATT_WRITE_CHARA_DESC': 5,
+ 'BLE_GATT_READ_CHARA_VALUE': 6,
+ 'BLE_GATT_READ_CHARA_DESC': 7,
+}
+
+class EVENT(dict):
+ def __getattr__(self, item):
+ return self[item]
+
+ def __setattr__(self, key, value):
+ raise ValueError("{} is read-only.".format(key))
+
+
+class BleClient(object):
+ def __init__(self):
+ self.ble_server_name = 'Quectel_ble' #目标设备ble名称
+ self.connect_id = 0
+ self.connect_addr = 0
+ self.gatt_statue = 0
+ self.discover_service_mode = 0 # 0-discover all service, 1-discover service by uuid
+
+ self.scan_param = {
+ 'scan_mode' : 1, # 积极扫描
+ 'interval' : 0x100,
+ 'scan_window' : 0x50,
+ 'filter_policy' : 0,
+ 'local_addr_type' : 0,
+ }
+
+ self.scan_report_info = {
+ 'event_type' : 0,
+ 'name' : '',
+ 'addr_type' : 0,
+ 'addr' : 0, # 初始化时,用0表示无效值,实际存放bytearray
+ 'rssi' : 0,
+ 'data_len' : 0,
+ 'raw_data' : 0,
+ }
+
+ self.target_service = {
+ 'start_handle' : 0,
+ 'end_handle' : 0,
+ 'uuid_type' : 1, # 短uuid
+ 'short_uuid' : 0x180F, # 电池电量服务
+ 'long_uuid' : bytearray([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])
+ }
+
+ self.characteristic_list = []
+ self.descriptor_list = []
+ self.characteristic_count = 0 # ql_ble_gatt_chara_count
+ self.chara_descriptor_count = 0 # ql_ble_gatt_chara_desc_count
+ self.characteristic_index = 0 # ql_ble_gatt_chara_desc_index
+ self.current_chara_index = 0 # ql_ble_gatt_cur_chara
+ self.current_desc_index = 0 # ql_ble_gatt_chara_cur_desc
+ self.ble_short_uuid_pair_len = 7
+ self.ble_long_uuid_pair_len = 21
+
+ ret = ble.clientInit(self.ble_client_callback)
+ if ret != 0:
+ print('ble client initialize failed.')
+ raise ValueError("BLE Client Init failed.")
+ else:
+ print('ble client initialize successful.')
+ print('')
+
+ @staticmethod
+ def gatt_open():
+ ret = ble.gattStart()
+ if ret != 0:
+ print('ble open failed.')
+ else:
+ print('ble open successful.')
+ print('')
+ return ret
+
+ @staticmethod
+ def gatt_close():
+ ret = ble.gattStop()
+ if ret != 0:
+ print('ble close failed.')
+ else:
+ print('ble close successful.')
+ print('')
+ return ret
+
+ @staticmethod
+ def gatt_get_status():
+ return ble.getStatus()
+
+ @staticmethod
+ def release():
+ ret = ble.clientRelease()
+ if ret != 0:
+ print('ble client release failed.')
+ else:
+ print('ble client release successful.')
+ print('')
+ return ret
+
+ def set_scan_param(self):
+ scan_mode = self.scan_param['scan_mode']
+ interval = self.scan_param['interval']
+ scan_time = self.scan_param['scan_window']
+ filter_policy = self.scan_param['filter_policy']
+ local_addr_type = self.scan_param['local_addr_type']
+ ret = ble.setScanParam(scan_mode, interval, scan_time, filter_policy, local_addr_type)
+ if ret != 0:
+ print('ble client set scan-parameters failed.')
+ else:
+ print('ble client set scan-parameters successful.')
+ print('')
+ return ret
+
+ @staticmethod
+ def start_scan():
+ ret = ble.scanStart()
+ if ret != 0:
+ print('ble client scan failed.')
+ else:
+ print('ble client scan successful.')
+ print('')
+ return ret
+
+ @staticmethod
+ def stop_scan():
+ ret = ble.scanStop()
+ if ret != 0:
+ print('ble client failed to stop scanning.')
+ else:
+ print('ble client scan stopped successfully.')
+ print('')
+ return ret
+
+ def connect(self):
+ print('start to connect.....')
+ addr_type = self.scan_report_info['addr_type']
+ addr = self.scan_report_info['addr']
+ if addr != 0 and len(addr) == 6:
+ addr_str = '{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}'.format(addr[0], addr[1], addr[2], addr[3], addr[4], addr[5])
+ print('addr_type : {}, addr : {}'.format(addr_type, addr_str))
+ ret = ble.connect(addr_type, addr)
+ if ret != 0:
+ print('ble client connect failed.')
+ else:
+ print('ble client connect successful.')
+ print('')
+ return ret
+
+ def cancel_connect(self):
+ ret = ble.cancelConnect(self.scan_report_info['addr'])
+ if ret != 0:
+ print('ble client cancel connect failed.')
+ else:
+ print('ble client cancel connect successful.')
+ print('')
+ return ret
+
+ def disconnect(self):
+ ret = ble.disconnect(self.connect_id)
+ if ret != 0:
+ print('ble client disconnect failed.')
+ else:
+ print('ble client disconnect successful.')
+ print('')
+ return ret
+
+ def discover_all_service(self):
+ ret = ble.discoverAllService(self.connect_id)
+ if ret != 0:
+ print('ble client discover all service failed.')
+ else:
+ print('ble client discover all service successful.')
+ print('')
+ return ret
+
+ def discover_service_by_uuid(self):
+ connect_id = self.connect_id
+ uuid_type = self.target_service['uuid_type']
+ short_uuid = self.target_service['short_uuid']
+ long_uuid = self.target_service['long_uuid']
+ ret = ble.discoverByUUID(connect_id, uuid_type, short_uuid, long_uuid)
+ if ret != 0:
+ print('ble client discover service by uuid failed.')
+ else:
+ print('ble client discover service by uuid successful.')
+ print('')
+ return ret
+
+ def discover_all_includes(self):
+ connect_id = self.connect_id
+ start_handle = self.target_service['start_handle']
+ end_handle = self.target_service['end_handle']
+ ret = ble.discoverAllIncludes(connect_id, start_handle, end_handle)
+ if ret != 0:
+ print('ble client discover all includes failed.')
+ else:
+ print('ble client discover all includes successful.')
+ print('')
+ return ret
+
+ def discover_all_characteristic(self):
+ connect_id = self.connect_id
+ start_handle = self.target_service['start_handle']
+ end_handle = self.target_service['end_handle']
+ ret = ble.discoverAllChara(connect_id, start_handle, end_handle)
+ if ret != 0:
+ print('ble client discover all characteristic failed.')
+ else:
+ print('ble client discover all characteristic successful.')
+ print('')
+ return ret
+
+ def discover_all_characteristic_descriptor(self):
+ connect_id = self.connect_id
+ index = self.characteristic_index
+ start_handle = self.characteristic_list[index]['value_handle'] + 1
+
+ if self.characteristic_index == (self.characteristic_count - 1):
+ end_handle = self.target_service['end_handle']
+ print('[1]start_handle = {:#06x}, end_handle = {:#06x}'.format(start_handle - 1, end_handle))
+ ret = ble.discoverAllCharaDesc(connect_id, start_handle, end_handle)
+ else:
+ end_handle = self.characteristic_list[index+1]['handle'] - 1
+ print('[2]start_handle = {:#06x}, end_handle = {:#06x}'.format(start_handle - 1, end_handle))
+ ret = ble.discoverAllCharaDesc(connect_id, start_handle, end_handle)
+ self.characteristic_index += 1
+ if ret != 0:
+ print('ble client discover all characteristic descriptor failed.')
+ else:
+ print('ble client discover all characteristic descriptor successful.')
+ print('')
+ return ret
+
+ def read_characteristic_by_uuid(self):
+ connect_id = self.connect_id
+ index = self.current_chara_index # 根据需要改变该值
+ start_handle = self.characteristic_list[index]['handle']
+ end_handle = self.characteristic_list[index]['value_handle']
+ uuid_type = 1
+ short_uuid = self.characteristic_list[index]['short_uuid']
+ long_uuid = bytearray([0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00])
+
+ ret = ble.readCharaByUUID(connect_id, start_handle, end_handle, uuid_type, short_uuid, long_uuid)
+ if ret != 0:
+ print('ble client read characteristic by uuid failed.')
+ else:
+ print('ble client read characteristic by uuid successful.')
+ print('')
+ return ret
+
+ def read_characteristic_by_handle(self):
+ connect_id = self.connect_id
+ index = self.current_chara_index # 根据需要改变该值
+ handle = self.characteristic_list[index]['value_handle']
+ offset = 0
+ is_long = 0
+
+ ret = ble.readCharaByHandle(connect_id, handle, offset, is_long)
+ if ret != 0:
+ print('ble client read characteristic by handle failed.')
+ else:
+ print('ble client read characteristic by handle successful.')
+ print('')
+ return ret
+
+ def read_characteristic_descriptor(self):
+ connect_id = self.connect_id
+ index = self.current_desc_index # 根据需要改变该值
+ handle = self.descriptor_list[index]['handle']
+ print('handle = {:#06x}'.format(handle))
+ is_long = 0
+ ret = ble.readCharaDesc(connect_id, handle, is_long)
+ if ret != 0:
+ print('ble client read characteristic descriptor failed.')
+ else:
+ print('ble client read characteristic descriptor successful.')
+ print('')
+ return ret
+
+ def write_characteristic(self):
+ connect_id = self.connect_id
+ index = self.current_chara_index # 根据需要改变该值
+ handle = self.characteristic_list[index]['value_handle']
+ offset = 0
+ is_long = 0
+ data = bytearray([0x40, 0x00])
+ print('value_handle = {:#06x}, uuid = {:#06x}'.format(handle, self.characteristic_list[index]['short_uuid']))
+ ret = ble.writeChara(connect_id, handle, offset, is_long, data)
+ if ret != 0:
+ print('ble client write characteristic failed.')
+ else:
+ print('ble client read characteristic successful.')
+ print('')
+ return ret
+
+ def write_characteristic_no_rsp(self):
+ connect_id = self.connect_id
+ index = self.current_chara_index # 根据需要改变该值
+ handle = self.characteristic_list[index]['value_handle']
+ data = bytearray([0x20, 0x00])
+ print('value_handle = {:#06x}, uuid = {:#06x}'.format(handle, self.characteristic_list[index]['short_uuid']))
+ ret = ble.writeCharaNoRsp(connect_id, handle, data)
+ if ret != 0:
+ print('ble client write characteristic no rsp failed.')
+ else:
+ print('ble client read characteristic no rsp successful.')
+ print('')
+ return ret
+
+ def write_characteristic_descriptor(self):
+ connect_id = self.connect_id
+ index = self.current_desc_index # 根据需要改变该值
+ handle = self.descriptor_list[index]['handle']
+ data = bytearray([0x01, 0x02])
+ print('handle = {:#06x}'.format(handle))
+
+ ret = ble.writeCharaDesc(connect_id, handle, data)
+ if ret != 0:
+ print('ble client write characteristic descriptor failed.')
+ else:
+ print('ble client read characteristic descriptor successful.')
+ print('')
+ return ret
+
+ @staticmethod
+ def ble_client_callback(args):
+ global msg_queue
+ msg_queue.put(args)
+
+
+def ble_gatt_client_event_handler():
+ global msg_queue
+ old_time = 0
+
+ while True:
+ cur_time = utime.localtime()
+ timestamp = "{:02d}:{:02d}:{:02d}".format(cur_time[3], cur_time[4], cur_time[5])
+ if cur_time[5] != old_time and cur_time[5] % 5 == 0:
+ old_time = cur_time[5]
+ print('[{}]event handler running.....'.format(timestamp))
+ print('')
+ msg = msg_queue.get() # 没有消息时会阻塞在这
+ # print('msg : {}'.format(msg))
+ event_id = msg[0]
+ status = msg[1]
+
+ if event_id == event.BLE_START_STATUS_IND:
+ print('')
+ print('event_id : BLE_START_STATUS_IND, status = {}'.format(status))
+ if status == 0:
+ print('BLE start successful.')
+ ble_status = ble_client.gatt_get_status()
+ if ble_status == 0:
+ print('BLE Status : stopped.')
+ break
+ elif ble_status == 1:
+ print('BLE Status : started.')
+ else:
+ print('get ble status error.')
+ ble_client.gatt_close()
+ break
+
+ ret = ble_client.set_scan_param()
+ if ret != 0:
+ ble_client.gatt_close()
+ break
+ ret = ble_client.start_scan()
+ if ret != 0:
+ ble_client.gatt_close()
+ break
+ else:
+ print('BLE start failed.')
+ break
+ elif event_id == event.BLE_STOP_STATUS_IND:
+ print('')
+ print('event_id : BLE_STOP_STATUS_IND, status = {}'.format(status))
+ if status == 0:
+ print('ble stop successful.')
+ else:
+ print('ble stop failed.')
+ break
+ elif event_id == event.BLE_CONNECT_IND:
+ print('')
+ print('event_id : BLE_CONNECT_IND, status = {}'.format(status))
+ if status == 0:
+ ble_client.connect_id = msg[2]
+ ble_client.connect_addr = msg[3]
+ addr = ble_client.connect_addr
+ addr_str = '{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}'.format(addr[0], addr[1], addr[2], addr[3], addr[4], addr[5])
+ print('connect_id : {:#x}, connect_addr : {}'.format(ble_client.connect_id, addr_str))
+ else:
+ print('ble connect failed.')
+ break
+ elif event_id == event.BLE_DISCONNECT_IND:
+ print('')
+ print('event_id : BLE_DISCONNECT_IND, status = {}'.format(status))
+ if status == 0:
+ ble_client.connect_id = msg[2]
+ ble_client.connect_addr = msg[3]
+ addr = ble_client.connect_addr
+ addr_str = '{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}'.format(addr[0], addr[1], addr[2], addr[3], addr[4], addr[5])
+ print('connect_id : {:#x}, connect_addr : {}'.format(ble_client.connect_id, addr_str))
+ else:
+ print('ble disconnect failed.')
+ ble_client.gatt_close()
+ break
+ elif event_id == event.BLE_UPDATE_CONN_PARAM_IND:
+ print('')
+ print('event_id : BLE_UPDATE_CONN_PARAM_IND, status = {}'.format(status))
+ if status == 0:
+ connect_id = msg[2]
+ max_interval = msg[3]
+ min_interval = msg[4]
+ latency = msg[5]
+ timeout = msg[6]
+ print('connect_id={},max_interval={},min_interval={},latency={},timeout={}'.format(connect_id,max_interval,min_interval,latency,timeout))
+ else:
+ print('ble update parameter failed.')
+ ble_client.gatt_close()
+ break
+ elif event_id == event.BLE_SCAN_REPORT_IND:
+ if status == 0:
+ # print(' ble scan successful.')
+
+ ble_client.scan_report_info['event_type'] = msg[2]
+ ble_client.scan_report_info['name'] = msg[3]
+ ble_client.scan_report_info['addr_type'] = msg[4]
+ ble_client.scan_report_info['addr'] = msg[5]
+ ble_client.scan_report_info['rssi'] = msg[6]
+ ble_client.scan_report_info['data_len'] = msg[7]
+ ble_client.scan_report_info['raw_data'] = msg[8]
+
+ device_name = ble_client.scan_report_info['name']
+ addr = ble_client.scan_report_info['addr']
+ rssi = ble_client.scan_report_info['rssi']
+ addr_type = ble_client.scan_report_info['addr_type']
+ addr_str = '{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}'.format(addr[0], addr[1], addr[2], addr[3], addr[4], addr[5])
+ if device_name != '' and rssi != 0:
+ print('name: {}, addr: {}, rssi: {}, addr_type: {}'.format(device_name, addr_str, rssi, addr_type))
+ print('raw_data: {}'.format(ble_client.scan_report_info['raw_data']))
+
+ if device_name == ble_client.ble_server_name: # 扫描到目标设备后就停止扫描
+ ret = ble_client.stop_scan()
+ if ret != 0:
+ ble_client.gatt_close()
+ break
+
+ ret = ble_client.connect()
+ if ret != 0:
+ ble_client.gatt_close()
+ break
+ else:
+ print('ble scan failed.')
+ ret = ble_client.stop_scan()
+ if ret != 0:
+ ble_client.gatt_close()
+ break
+ elif event_id == event.BLE_GATT_MTU:
+ print('')
+ print('event_id : BLE_GATT_MTU, status = {}'.format(status))
+ if status == 0:
+ handle = msg[2]
+ ble_mtu = msg[3]
+ print('handle = {:#06x}, ble_mtu = {}'.format(handle, ble_mtu))
+ else:
+ print('ble connect mtu failed.')
+ ble_client.gatt_close()
+ break
+ elif event_id == event.BLE_GATT_RECV_NOTIFICATION_IND:
+ print('')
+ print('event_id : BLE_GATT_RECV_NOTIFICATION_IND, status = {}'.format(status))
+ if status == 0:
+ data_len = msg[2]
+ data = msg[3]
+ print('len={}, data:{}'.format(data_len, data))
+ handle = (data[1] << 8) | data[0]
+ print('handle = {:#06x}'.format(handle))
+ else:
+ print('ble receive notification failed.')
+ break
+ elif event_id == event.BLE_GATT_RECV_INDICATION_IND:
+ print('')
+ print('event_id : BLE_GATT_RECV_INDICATION_IND, status = {}'.format(status))
+ if status == 0:
+ data_len = msg[2]
+ data = msg[3]
+ print('len={}, data:{}'.format(data_len, data))
+ else:
+ print('ble receive indication failed.')
+ break
+ elif event_id == event.BLE_GATT_START_DISCOVER_SERVICE_IND:
+ print('')
+ print('event_id : BLE_GATT_START_DISCOVER_SERVICE_IND, status = {}'.format(status))
+ if status == 0:
+ ble_client.characteristic_count = 0
+ ble_client.chara_descriptor_count = 0
+ ble_client.characteristic_index = 0
+ ble_client.gatt_statue = gatt_status.BLE_GATT_DISCOVER_SERVICE
+
+ if ble_client.discover_service_mode == 0:
+ print('execute the function discover_all_service.')
+ ret = ble_client.discover_all_service()
+ else:
+ print('execute the function discover_service_by_uuid.')
+ ret = ble_client.discover_service_by_uuid()
+ if ret != 0:
+ print('Execution result: Failed.')
+ ble_client.gatt_close()
+ break
+ else:
+ print('ble start discover service failed.')
+ ble_client.gatt_close()
+ break
+ elif event_id == event.BLE_GATT_DISCOVER_SERVICE_IND:
+ print('')
+ print('event_id : BLE_GATT_DISCOVER_SERVICE_IND, status = {}'.format(status))
+ if status == 0:
+ start_handle = msg[2]
+ end_handle = msg[3]
+ short_uuid = msg[4]
+ print('start_handle = {:#06x}, end_handle = {:#06x}, short_uuid = {:#06x}'.format(start_handle, end_handle, short_uuid))
+ if ble_client.discover_service_mode == 0: # discover service all
+ if ble_client.target_service['short_uuid'] == short_uuid: # 查找到所有服务后,按指定uuid查找特征值
+ ble_client.target_service['start_handle'] = start_handle
+ ble_client.target_service['end_handle'] = end_handle
+ ble_client.gatt_statue = gatt_status.BLE_GATT_DISCOVER_CHARACTERISTIC
+ print('execute the function discover_all_characteristic.')
+ ret = ble_client.discover_all_characteristic()
+ if ret != 0:
+ print('Execution result: Failed.')
+ ble_client.gatt_close()
+ break
+ else:
+ ble_client.target_service['start_handle'] = start_handle
+ ble_client.target_service['end_handle'] = end_handle
+ ble_client.gatt_statue = gatt_status.BLE_GATT_DISCOVER_CHARACTERISTIC
+ print('execute the function discover_all_characteristic.')
+ ret = ble_client.discover_all_characteristic()
+ if ret != 0:
+ print('Execution result: Failed.')
+ ble_client.gatt_close()
+ break
+ else:
+ print('ble discover service failed.')
+ ble_client.gatt_close()
+ break
+ elif event_id == event.BLE_GATT_DISCOVER_CHARACTERISTIC_DATA_IND:
+ print('')
+ print('event_id : BLE_GATT_DISCOVER_CHARACTERISTIC_DATA_IND, status = {}'.format(status))
+ if status == 0:
+ data_len = msg[2]
+ data = msg[3]
+ pair_len = data[0]
+ print('pair_len={}, len={}, data:{}'.format(pair_len, data_len, data))
+ if data_len > 0:
+ if ble_client.gatt_statue == gatt_status.BLE_GATT_DISCOVER_CHARACTERISTIC:
+ i = 0
+ while i < (data_len - 1) / pair_len:
+ chara_dict = {
+ 'handle': (data[i * pair_len + 2] << 8) | data[i * pair_len + 1],
+ 'properties': data[i * pair_len + 3],
+ 'value_handle': (data[i * pair_len + 5] << 8) | data[i * pair_len + 4],
+ 'uuid_type': 0,
+ 'short_uuid': 0x0000,
+ 'long_uuid': bytearray([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])
+ }
+ print('handle={:#06x}, properties={:#x}, value_handle={:#06x}'.format(chara_dict['handle'], chara_dict['properties'], chara_dict['value_handle']))
+ if pair_len == ble_client.ble_short_uuid_pair_len:
+ chara_dict['uuid_type'] = 1
+ chara_dict['short_uuid'] = (data[i * pair_len + 7] << 8) | data[i * pair_len + 6]
+ print('short_uuid:{:#06x}'.format(chara_dict['short_uuid']))
+ elif pair_len == ble_client.ble_long_uuid_pair_len:
+ start_index = i * pair_len + 6
+ end_index = start_index + 16
+ chara_dict['uuid_type'] = 0
+ chara_dict['long_uuid'] = data[start_index : end_index]
+ print('long_uuid:{}'.format(chara_dict['long_uuid']))
+ i += 1
+ if ble_client.characteristic_count < 5:
+ ble_client.characteristic_list.append(chara_dict)
+ ble_client.characteristic_count = len(ble_client.characteristic_list)
+ print('characteristic_list len = {}'.format(ble_client.characteristic_count))
+ elif ble_client.gatt_statue == gatt_status.BLE_GATT_READ_CHARA_VALUE:
+ print('data_len = {}'.format(data_len))
+ print('pay_load = {:02x},{:02x},{:02x},{:02x}'.format(data[0], data[1], data[2], data[3]))
+ else:
+ print('ble discover characteristic failed.')
+ ble_client.gatt_close()
+ break
+ elif event_id == event.BLE_GATT_DISCOVER_CHARA_DESC_IND:
+ print('')
+ print('event_id : BLE_GATT_DISCOVER_CHARA_DESC_IND, status = {}'.format(status))
+ if status == 0:
+ data_len = msg[2]
+ data = msg[3]
+ fmt = data[0]
+ print('fmt={}, len={}, data:{}'.format(fmt, data_len, data))
+ if data_len > 0:
+ i = 0
+ if fmt == 1: # 16 bit uuid
+ while i < (data_len - 1) / 4:
+ descriptor_dict = {
+ 'handle': (data[i * 4 + 2] << 8) | data[i * 4 + 1],
+ 'short_uuid': (data[i * 4 + 4] << 8) | data[i * 4 + 3],
+ }
+ print('handle={:#06x}, uuid={:#06x}'.format(descriptor_dict['handle'], descriptor_dict['short_uuid']))
+ i += 1
+ if ble_client.chara_descriptor_count < 5:
+ ble_client.descriptor_list.append(descriptor_dict)
+ ble_client.chara_descriptor_count = len(ble_client.descriptor_list)
+ print('descriptor_list len = {}'.format(ble_client.chara_descriptor_count))
+ if ble_client.characteristic_index == ble_client.characteristic_count:
+ print('execute the function read_characteristic_by_uuid.')
+ # ble_client.gatt_statue = gatt_status.BLE_GATT_WRITE_CHARA_VALUE
+ # ret = ble_client.write_characteristic()
+ # ret = ble_client.write_characteristic_no_rsp()
+
+ ble_client.gatt_statue = gatt_status.BLE_GATT_READ_CHARA_VALUE
+ ret = ble_client.read_characteristic_by_uuid()
+ # ret = ble_client.read_characteristic_by_handle()
+
+ # ble_client.gatt_statue = gatt_status.BLE_GATT_READ_CHARA_DESC
+ # ret = ble_client.read_characteristic_descriptor()
+
+ # ble_client.gatt_statue = gatt_status.BLE_GATT_WRITE_CHARA_DESC
+ # ret = ble_client.write_characteristic_descriptor()
+ else:
+ print('execute the function discover_all_characteristic_descriptor.')
+ ret = ble_client.discover_all_characteristic_descriptor()
+ if ret != 0:
+ print('Execution result: Failed.')
+ ble_client.gatt_close()
+ break
+ else:
+ print('ble discover characteristic descriptor failed.')
+ ble_client.gatt_close()
+ break
+ elif event_id == event.BLE_GATT_CHARA_WRITE_WITH_RSP_IND:
+ print('')
+ print('event_id : BLE_GATT_CHARA_WRITE_WITH_RSP_IND, status = {}'.format(status))
+ if status == 0:
+ if ble_client.gatt_statue == gatt_status.BLE_GATT_WRITE_CHARA_VALUE:
+ pass
+ elif ble_client.gatt_statue == gatt_status.BLE_GATT_WRITE_CHARA_DESC:
+ pass
+ else:
+ print('ble write characteristic with response failed.')
+ break
+ elif event_id == event.BLE_GATT_CHARA_WRITE_WITHOUT_RSP_IND:
+ print('')
+ print('event_id : BLE_GATT_CHARA_WRITE_WITHOUT_RSP_IND, status = {}'.format(status))
+ if status == 0:
+ print('write characteristic value without response successful.')
+ else:
+ print('write characteristic value without response failed.')
+ break
+ elif event_id == event.BLE_GATT_CHARA_READ_IND:
+ print('')
+ # read characteristic value by handle
+ print('event_id : BLE_GATT_CHARA_READ_IND, status = {}'.format(status))
+ if status == 0:
+ data_len = msg[2]
+ data = msg[3]
+ print('data_len = {}, data : {}'.format(data_len, data))
+ if ble_client.gatt_statue == gatt_status.BLE_GATT_READ_CHARA_VALUE:
+ # print('read characteristic value by handle.')
+ pass
+ else:
+ print('ble read characteristic failed.')
+ break
+ elif event_id == event.BLE_GATT_CHARA_READ_BY_UUID_IND:
+ print('')
+ # read characteristic value by uuid
+ print('event_id : BLE_GATT_CHARA_READ_BY_UUID_IND, status = {}'.format(status))
+ if status == 0:
+ data_len = msg[2]
+ data = msg[3]
+ print('data_len = {}, data : {}'.format(data_len, data))
+ handle = (data[2] << 8) | data[1]
+ print('handle = {:#06x}'.format(handle))
+ else:
+ print('ble read characteristic by uuid failed.')
+ break
+ elif event_id == event.BLE_GATT_CHARA_MULTI_READ_IND:
+ print('')
+ # read multiple characteristic value
+ print('event_id : BLE_GATT_CHARA_MULTI_READ_IND, status = {}'.format(status))
+ if status == 0:
+ data_len = msg[2]
+ data = msg[3]
+ print('data_len = {}, data : {}'.format(data_len, data))
+ else:
+ print('ble read multiple characteristic by uuid failed.')
+ break
+ elif event_id == event.BLE_GATT_DESC_WRITE_WITH_RSP_IND:
+ print('')
+ print('event_id : BLE_GATT_DESC_WRITE_WITH_RSP_IND, status = {}'.format(status))
+ if status == 0:
+ if ble_client.gatt_statue == gatt_status.BLE_GATT_WRITE_CHARA_VALUE:
+ pass
+ elif ble_client.gatt_statue == gatt_status.BLE_GATT_WRITE_CHARA_DESC:
+ pass
+ else:
+ print('ble write characteristic descriptor failed.')
+ break
+ elif event_id == event.BLE_GATT_DESC_READ_IND:
+ print('')
+ # read characteristic descriptor
+ print('event_id : BLE_GATT_DESC_READ_IND, status = {}'.format(status))
+ if status == 0:
+ data_len = msg[2]
+ data = msg[3]
+ print('data_len = {}, data : {}'.format(data_len, data))
+ if ble_client.gatt_statue == gatt_status.BLE_GATT_READ_CHARA_DESC:
+ # print('read characteristic descriptor.')
+ pass
+ else:
+ print('ble read characteristic descriptor failed.')
+ break
+ elif event_id == event.BLE_GATT_ATT_ERROR_IND:
+ print('')
+ print('event_id : BLE_GATT_ATT_ERROR_IND, status = {}'.format(status))
+ if status == 0:
+ errcode = msg[2]
+ print('errcode = {:#06x}'.format(errcode))
+ if ble_client.gatt_statue == gatt_status.BLE_GATT_DISCOVER_INCLUDES:
+ ble_client.gatt_statue = gatt_status.BLE_GATT_DISCOVER_CHARACTERISTIC
+ print('execute the function discover_all_characteristic.')
+ ret = ble_client.discover_all_characteristic()
+ if ret != 0:
+ print('Execution result: Failed.')
+ ble_client.gatt_close()
+ break
+ elif ble_client.gatt_statue == gatt_status.BLE_GATT_DISCOVER_CHARACTERISTIC:
+ ble_client.gatt_statue = gatt_status.BLE_GATT_IDLE
+ print('execute the function discover_all_characteristic_descriptor.')
+ ret = ble_client.discover_all_characteristic_descriptor()
+ if ret != 0:
+ print('Execution result: Failed.')
+ ble_client.gatt_close()
+ break
+ else:
+ print('ble attribute error.')
+ ble_client.gatt_close()
+ break
+ else:
+ print('unknown event id : {}.'.format(event_id))
+
+ # ble_client.release()
+
+
+event = EVENT(event_dict)
+gatt_status = EVENT(gatt_status_dict)
+msg_queue = Queue(50)
+ble_client = BleClient()
+
+
+def main():
+ checknet.poweron_print_once()
+ print('create client event handler task.')
+ _thread.start_new_thread(ble_gatt_client_event_handler, ())
+ # ble.setScanFilter(0) # 关闭扫描过滤功能
+ ret = ble_client.gatt_open()
+ if ret != 0:
+ return -1
+
+ count = 0
+ while True:
+ utime.sleep(1)
+ count += 1
+ cur_time = utime.localtime()
+ timestamp = "{:02d}:{:02d}:{:02d}".format(cur_time[3], cur_time[4], cur_time[5])
+ if count % 5 == 0:
+ print('[{}] BLE Client running, count = {}......'.format(timestamp, count))
+ print('')
+ if count > 130: # 这里设置计数是为了程序运行一会自己退出,方便测试,实际根据用户需要来处理
+ count = 0
+ print('!!!!! stop BLE Client now !!!!!')
+ ble_status = ble_client.gatt_get_status()
+ if ble_status == 1:
+ ble_client.gatt_close()
+ ble_client.release()
+ break
+ else:
+ ble_status = ble_client.gatt_get_status()
+ if ble_status == 0: # stopped
+ print('BLE connection has been disconnected.')
+ ble_client.release()
+ break
+
+if __name__ == '__main__':
+ main()
+
+```
+
+**注意**:
+
+当前仅EC200U/EC600U/EG915U/EG912U平台支持`ble`功能。
+
+## 初始化相关功能
+
+### ble.gattStart
+
+```python
+ble.gattStart()
+```
+
+开启 BLE GATT 功能。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+### ble.gattStop
+
+```python
+ble.gattStop()
+```
+
+关闭 BLE GATT 功能。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+### ble.getStatus
+
+```python
+ble.getStatus()
+```
+
+获取 BLE 的状态。
+
+**返回值描述:**
+
+- 0 - BLE处于停止状态。1 - BLE处于开启状态。-1 - 获取状态失败。
+
+### ble.getPublicAddr
+
+```python
+ble.getPublicAddr()
+```
+
+获取 BLE 协议栈正在使用的公共地址。该接口需要在BLE已经初始化完成并启动成功后才能调用,比如在回调中收到 event_id 为0的事件之后,即 start 成功后,去调用。
+
+**返回值描述:**
+
+- 执行成功返回bytearray类型的BLE地址,大小6个byte,失败返回整型-1。
+
+**示例**:
+
+```python
+>>> addr = ble.getPublicAddr()
+>>> print(addr)
+b'\xdb3\xf5\x1ek\xac'
+>>> mac = '{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}'.format(addr[5], addr[4], addr[3], addr[2], addr[1], addr[0])
+>>> print('mac = [{}]'.format(mac))
+mac = [ac:6b:1e:f5:33:db]
+```
+
+**注意**:
+
+如果有出厂设置默认蓝牙MAC地址,那么该接口获取的MAC地址和默认的蓝牙MAC地址是一致的;如果没有设置,那么该接口获取的地址,将是蓝牙启动后随机生成的静态地址,因此在每次重新上电运行蓝牙功能时都不相同。
+
+## BLE Server相关功能
+
+### ble.serverInit
+
+```python
+ble.serverInit(user_cb)
+```
+
+初始化 BLE Server 并注册回调函数。
+
+**参数描述:**
+
+- `user_cb`-回调函数,类型为function。回调函数参数含义:args[0] 固定表示event_id,args[1]固定 表示状态,0表示成功,非0表示失败。回调函数的参数个数并不是固定2个,而是根据第一个参数args[0]来决定的,下表中列出了不同事件ID对应的参数个数及说明。
+
+| event_id | 参数个数 | 参数说明 |
+| :------: | :------: | ------------------------------------------------------------ |
+| 0 | 2 | args[0] :event_id,表示 BT/BLE start
args[1] :status,表示操作的状态,0-成功,非0-失败 |
+| 1 | 2 | args[0] :event_id,表示 BT/BLE stop
args[1] :status,表示操作的状态,0-成功,非0-失败 |
+| 16 | 4 | args[0] :event_id,表示 BLE connect
args[1] :status,表示操作的状态,0-成功,非0-失败
args[2] :connect_id
args[3] :addr,BT/BLE address,bytearray类型数据 |
+| 17 | 4 | args[0] :event_id,表示 BLE disconnect
args[1] :status,表示操作的状态,0-成功,非0-失败
args[2] :connect_id,
args[3] :addr,BT/BLE address,bytearray类型数据 |
+| 18 | 7 | args[0] :event_id,表示 BLE update connection parameter
args[1] :status,表示操作的状态,0-成功,非0-失败
args[2] :connect_id
args[3] :max_interval,最大的间隔,间隔:1.25ms,取值范围:6-3200,时间范围:7.5ms\ ~ 4s
args[4] :min_interval,最小的间隔,间隔:1.25ms,取值范围:6-3200,时间范围:7.5ms\ ~ 4s
args[5] :latency,从机忽略连接状态事件的时间。需满足:(1+latecy)\*max_interval\*2\*1.25args[6] :timeout,没有交互,超时断开时间,间隔:10ms,取值范围:10-3200ms,时间范围:100ms ~ 32s |
+| 20 | 4 | args[0] :event_id,表示 BLE connection mtu
args[1] :status,表示操作的状态,0-成功,非0-失败
args[2] :handle
args[3] :mtu值 |
+| 21 | 7 | args[0] :event_id,表示 BLE server : when ble client write characteristic value or descriptor,server get the notice
args[1] :status,表示操作的状态,0-成功,非0-失败
args[2] :data_len,获取数据的长度
args[3] :data,一个数组,存放获取的数据
args[4] :attr_handle,属性句柄,整型值
args[5] :short_uuid,整型值
args[6] :long_uuid,一个16字节数组,存放长UUID |
+| 22 | 7 | args[0] :event_id,表示 server : when ble client read characteristic value or descriptor,server get the notice
args[1] :status,表示操作的状态,0-成功,非0-失败
args[2] :data_len,获取数据的长度
args[3] :data,一个数组,存放获取的数据
args[4] :attr_handle,属性句柄,整型值
args[5] :short_uuid,整型值
args[6] :long_uuid,一个16字节数组,存放长UUID |
+| 25 | 2 | args[0] :event_id,表示 server send notification,and recieve send end notice
args[1] :status,表示操作的状态,0-成功,非0-失败 |
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+**示例**:
+
+```python
+def ble_callback(args):
+ event_id = args[0]
+ status = args[1]
+ print('[ble_callback]: event_id={}, status={}'.format(event_id, status))
+
+ if event_id == 0: # ble start
+ if status == 0:
+ print('[callback] BLE start success.')
+ else:
+ print('[callback] BLE start failed.')
+ elif event_id == 1: # ble stop
+ if status == 0:
+ print('[callback] ble stop successful.')
+ else:
+ print('[callback] ble stop failed.')
+ elif event_id == 16: # ble connect
+ if status == 0:
+ print('[callback] ble connect successful.')
+ connect_id = args[2]
+ addr = args[3] # 这是一个bytearray类型
+ addr_str = '{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}'.format(addr[0], addr[1], addr[2], addr[3], addr[4], addr[5])
+ print('[callback] connect_id = {}, addr = {}'.format(connect_id, addr_str))
+ else:
+ print('[callback] ble connect failed.')
+ elif event_id == 17: # ble disconnect
+ if status == 0:
+ print('[callback] ble disconnect successful.')
+ connect_id = args[2]
+ addr = args[3] # 这是一个bytearray类型
+ addr_str = '{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}'.format(addr[0], addr[1], addr[2], addr[3], addr[4], addr[5])
+ print('[callback] connect_id = {}, addr = {}'.format(connect_id, addr_str))
+ else:
+ print('[callback] ble disconnect failed.')
+ ble.gattStop()
+ return
+ elif event_id == 18: # ble update connection parameter
+ if status == 0:
+ print('[callback] ble update parameter successful.')
+ connect_id = args[2]
+ max_interval = args[3]
+ min_interval = args[4]
+ latency = args[5]
+ timeout = args[6]
+ print('[callback] connect_id={},max_interval={},min_interval={},latency={},timeout={}'.format(connect_id, max_interval, min_interval, latency, timeout))
+ else:
+ print('[callback] ble update parameter failed.')
+ ble.gattStop()
+ return
+ elif event_id == 20: # ble connection mtu
+ if status == 0:
+ print('[callback] ble connect mtu successful.')
+ handle = args[2]
+ ble_mtu = args[3]
+ print('[callback] handle = {:#06x}, ble_mtu = {}'.format(handle, ble_mtu))
+ else:
+ print('[callback] ble connect mtu failed.')
+ ble.gattStop()
+ return
+ elif event_id == 21: # server:when ble client write characteristic value or descriptor,server get the notice
+ if status == 0:
+ print('[callback] ble recv successful.')
+ data_len = args[2]
+ data = args[3] # 这是一个bytearray类型
+ attr_handle = args[4]
+ short_uuid = args[5]
+ long_uuid = args[6] # 这是一个bytearray类型
+ print('len={}, data:{}'.format(data_len, data))
+ print('attr_handle = {:#06x}'.format(attr_handle))
+ print('short uuid = {:#06x}'.format(short_uuid))
+ print('long uuid = {}'.format(long_uuid))
+ else:
+ print('[callback] ble recv failed.')
+ ble.gattStop()
+ return
+ elif event_id == 22: # server:when ble client read characteristic value or descriptor,server get the notice
+ if status == 0:
+ print('[callback] ble recv read successful.')
+ data_len = args[2]
+ data = args[3] # 这是一个bytearray类型
+ attr_handle = args[4]
+ short_uuid = args[5]
+ long_uuid = args[6] # 这是一个bytearray类型
+ print('len={}, data:{}'.format(data_len, data))
+ print('attr_handle = {:#06x}'.format(attr_handle))
+ print('short uuid = {:#06x}'.format(short_uuid))
+ print('long uuid = {}'.format(long_uuid))
+ else:
+ print('[callback] ble recv read failed.')
+ ble.gattStop()
+ return
+ elif event_id == 25: # server send notification,and recieve send end notice
+ if status == 0:
+ print('[callback] ble send data successful.')
+ else:
+ print('[callback] ble send data failed.')
+ else:
+ print('unknown event id.')
+
+ble.serverInit(ble_callback)
+```
+
+### ble.serverRelease
+
+```python
+ble.serverRelease()
+```
+
+BLE Server 资源释放。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+### ble.setLocalName
+
+```python
+ble.setLocalName(code, name)
+```
+
+设置 BLE 名称。
+
+**参数描述:**
+
+- `code`-编码模式,类型为整型。0 - UTF8,1 - GBK。
+- `name`-编码模式,类型为string。BLE 名称,名称最长不能超过29个字节。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+**示例**:
+
+```python
+>>> ble.setLocalName(0, 'QuecPython-BLE')
+0
+```
+
+**注意**:
+
+对于BLE,设备在广播时,如果希望扫描软件扫描时,能看到广播设备的名称,是需要在广播数据中包含蓝牙名称的,或者在扫描回复数据中包含设备名称。
+
+### ble.setAdvParam
+
+```python
+ble.setAdvParam(min_adv,max_adv,adv_type,addr_type,channel,filter_policy,discov_mode,no_br_edr,enable_adv)
+```
+
+设置广播参数。
+
+**参数描述:**
+
+- 参数含义如下表。
+
+| 参数 | 类型 | 说明 |
+| ------------- | ---------- | ------------------------------------------------------------ |
+| min_adv | 无符号整型 | 最小广播间隔,范围0x0020-0x4000,计算如下:
时间间隔 = min_adv \* 0.625,单位ms |
+| max_adv | 无符号整型 | 最大广播间隔,范围0x0020-0x4000,计算如下:
时间间隔 = max_adv \* 0.625,单位ms |
+| adv_type | 无符号整型 | 广播类型,取值范围如下:
0 - 可连接的非定向广播,默认选择
1 - 可连接高占空比的定向广播
2 - 可扫描的非定向广播
3 - 不可连接的非定向广播
4 - 可连接低占空比的定向广播 |
+| addr_type | 无符号整型 | 本地地址类型,取值范围如下:
0 - 公共地址
1 - 随机地址 |
+| channel | 无符号整型 | 广播通道,取值范围如下:
1 - 37信道
2 - 38信道
4 - 39信道
7 - 上述3个通道都选择,默认该选项 |
+| filter_policy | 无符号整型 | 广播过滤策略,取值范围如下:
0 - 处理所有设备的扫描和连接请求
1 - 处理所有设备的连接请求和只处理白名单设备的扫描请求(暂不支持)
2 - 处理所有设备的扫描请求和只处理白名单设备的连接请求(暂不支持)
3 - 只处理白名单设备的连接和扫描请求(暂不支持) |
+| discov_mode | 无符号整型 | 发现模式,GAP协议使用,默认为2
1 - 有限可发现模式
2 - 一般可发现模式 |
+| no_br_edr | 无符号整型 | 不用BR/EDR,默认为1,如果用则为0 |
+| enable_adv | 无符号整型 | 使能广播,默认为1,不使能则为0 |
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+**示例**:
+
+```python
+def ble_gatt_set_param():
+ min_adv = 0x300
+ max_adv = 0x320
+ adv_type = 0 # 可连接的非定向广播,默认选择
+ addr_type = 0 # 公共地址
+ channel = 0x07
+ filter_strategy = 0 # 处理所有设备的扫描和连接请求
+ discov_mode = 2
+ no_br_edr = 1
+ enable_adv = 1
+ ret = ble.setAdvParam(min_adv, max_adv, adv_type, addr_type, channel, filter_strategy, discov_mode, no_br_edr, enable_adv)
+ if ret != 0:
+ print('ble_gatt_set_param failed.')
+ return -1
+ print('ble_gatt_set_param success.')
+ return 0
+```
+
+### ble.setAdvData
+
+```python
+ble.setAdvData(data)
+```
+
+设置广播数据内容。
+
+**参数描述:**
+
+- `data`-广播数据,最长不超过31个字节,类型为bytearray。广播数据的内容,采用 length+type+data 的格式。一条广播数据中可以包含多个这种格式数据的组合,如下示例中包含了两个数据组合,第一个是 "0x02, 0x01, 0x05",0x02表示后面有两个数据,分别是0x01和0x05,0x01即type,0x05表示具体数据;第二个是ble名称数据组合, length为ble名称长度加1、type为0x09,具体数据为name对应的具体编码值。关于type具体值代表的含义,请参考蓝牙协议官方标准文档。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+**示例**:
+
+```python
+def ble_gatt_set_data():
+ adv_data = [0x02, 0x01, 0x05]
+ ble_name = "Quectel_ble"
+ length = len(ble_name) + 1
+ adv_data.append(length)
+ adv_data.append(0x09)
+ name_encode = ble_name.encode('UTF-8')
+ for i in range(0, len(name_encode)):
+ adv_data.append(name_encode[i])
+ print('set adv_data:{}'.format(adv_data))
+ data = bytearray(adv_data)
+ ret = ble.setAdvData(data)
+ if ret != 0:
+ print('ble_gatt_set_data failed.')
+ return -1
+ print('ble_gatt_set_data success.')
+ return 0
+```
+
+### ble.setAdvRspData
+
+```python
+ble.setAdvRspData(data)
+```
+
+设置扫描回复数据。
+
+**参数描述:**
+
+- `data`-扫描回复数据,最长不超过31个字节,类型为bytearray。 格式和上面设置广播数据内容接口一致。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+**示例**:
+
+```python
+def ble_gatt_set_rsp_data():
+ adv_data = []
+ ble_name = "Quectel_ble"
+ length = len(ble_name) + 1
+ adv_data.append(length)
+ adv_data.append(0x09)
+ name_encode = ble_name.encode('UTF-8')
+ for i in range(0, len(name_encode)):
+ adv_data.append(name_encode[i])
+ print('set adv_rsp_data:{}'.format(adv_data))
+ data = bytearray(adv_data)
+ ret = ble.setAdvRspData(data)
+ if ret != 0:
+ print('ble_gatt_set_rsp_data failed.')
+ return -1
+ print('ble_gatt_set_rsp_data success.')
+ return 0
+```
+
+**注意**:
+
+当client设备扫描方式为积极扫描时,设置扫描回复数据才有意义。
+
+### ble.addService
+
+```python
+ble.addService(primary, server_id, uuid_type, uuid_s, uuid_l)
+```
+
+增加一个服务。
+
+**参数描述:**
+
+- `primary`-服务类型,1表示主要服务,其他值表示次要服务,类型为整型。
+- `server_id`-服务ID,用来确定某一个服务,类型为整型。
+- `uuid_type`-uuid类型,0 - 长UUID,128bit;1 - 短UUID,16bit。类型为整型。
+- `uuid_s`-短UUID,2个字节(16bit),类型为整型,当uuid_type为0时,该值给0。
+- `uuid_l`-长UUID,16个字节(128bit),类型为bytearray,当uuid_type为1时,该值填 bytearray([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+**示例**:
+
+```python
+def ble_gatt_add_service():
+ primary = 1
+ server_id = 0x01
+ uuid_type = 1 # 短UUID
+ uuid_s = 0x180F
+ uuid_l = bytearray([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])
+ ret = ble.addService(primary, server_id, uuid_type, uuid_s, uuid_l)
+ if ret != 0:
+ print('ble_gatt_add_service failed.')
+ return -1
+ print('ble_gatt_add_service success.')
+ return 0
+```
+
+### ble.addChara
+
+```python
+ble.addChara(server_id, chara_id, chara_prop, uuid_type, uuid_s, uuid_l)
+```
+
+在服务里增加一个特征。
+
+**参数描述:**
+
+- `server_id`-服务ID,用来确定某一个服务,类型为整型。
+- `chara_id`-特征ID,类型为整型。
+- `chara_prop`-特征的属性,十六进制数,可通过“或运算”同时指定多个属性,值具体含义如下表,类型为整型。
+
+| 值 | 含义 |
+| ---- | ----------------------------- |
+| 0x01 | 广播 |
+| 0x02 | 可读 |
+| 0x04 | 0x04 - 可写且不需要链路层应答 |
+| 0x08 | 可写 |
+| 0x10 | 通知 |
+| 0x20 | 指示 |
+| 0x40 | 认证签名写 |
+| 0x80 | 扩展属性 |
+
+- `uuid_type`-uuid类型,0 - 长UUID,128bit;1 - 短UUID,16bit。类型为整型。
+- `uuid_s`-短UUID,2个字节(16bit),类型为整型,当uuid_type为0时,该值给0。
+- `uuid_l`-长UUID,16个字节(128bit),类型为bytearray,当uuid_type为1时,该值填 bytearray([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+**示例**:
+
+```python
+def ble_gatt_add_characteristic():
+ server_id = 0x01
+ chara_id = 0x01
+ chara_prop = 0x02 | 0x10 | 0x20 # 0x02-可读 0x10-通知 0x20-指示
+ uuid_type = 1 # 短UUID
+ uuid_s = 0x2A19
+ uuid_l = bytearray([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])
+ ret = ble.addChara(server_id, chara_id, chara_prop, uuid_type, uuid_s, uuid_l)
+ if ret != 0:
+ print('ble_gatt_add_characteristic failed.')
+ return -1
+ print('ble_gatt_add_characteristic success.')
+ return 0
+```
+
+### ble.addCharaValue
+
+```python
+ble.addCharaValue(server_id, chara_id, permission, uuid_type, uuid_s, uuid_l, value)
+```
+
+在特征里增加一个特征值。
+
+**参数描述:**
+
+- `server_id`-服务ID,用来确定某一个服务,类型为整型。
+- `chara_id`-特征ID,类型为整型。
+- `permission`-特征值的权限,2个字节,十六进制数,可通过“或运算”同时指定多个属性,值具体含义如下表,类型为整型。
+
+| 值 | 含义 |
+| ------ | -------------- |
+| 0x0001 | 可读权限 |
+| 0x0002 | 可写权限 |
+| 0x0004 | 读需要认证 |
+| 0x0008 | 读需要授权 |
+| 0x0010 | 读需要加密 |
+| 0x0020 | 读需要授权认证 |
+| 0x0040 | 写需要认证 |
+| 0x0080 | 写需要授权 |
+| 0x0100 | 写需要加密 |
+| 0x0200 | 写需要授权认证 |
+
+- `uuid_type`-uuid类型,0 - 长UUID,128bit;1 - 短UUID,16bit。类型为整型。
+- `uuid_s`-短UUID,2个字节(16bit),类型为整型,当uuid_type为0时,该值给0。
+- `uuid_l`-长UUID,16个字节(128bit),类型为bytearray,当uuid_type为1时,该值填 bytearray([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])。
+- `value`-特征值数据。类型为bytearray。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+**示例**:
+
+```python
+def ble_gatt_add_characteristic_value():
+ data = []
+ server_id = 0x01
+ chara_id = 0x01
+ permission = 0x0001 | 0x0002
+ uuid_type = 1 # 短UUID
+ uuid_s = 0x2A19
+ uuid_l = bytearray([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])
+ for i in range(0, 244):
+ data.append(0x00)
+ value = bytearray(data)
+ ret = ble.addCharaValue(server_id, chara_id, permission, uuid_type, uuid_s, uuid_l, value)
+ if ret != 0:
+ print('ble_gatt_add_characteristic_value failed.')
+ return -1
+ print('ble_gatt_add_characteristic_value success.')
+ return 0
+```
+
+### ble.changeCharaValue
+
+```python
+ble.changeCharaValue(server_id, chara_id, value)
+```
+
+修改特征值。
+
+**参数描述:**
+
+- `server_id`-服务ID,用来确定某一个服务,类型为整型。
+- `chara_id`-特征ID,类型为整型。
+
+- `value`-特征值数据。类型为bytearray。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+### ble.addCharaDesc
+
+```python
+ble.addCharaDesc(server_id, chara_id, permission, uuid_type, uuid_s, uuid_l, value)
+```
+
+在特征里增加一个特征描述,注意特征描述和特征值同属与一个特征。
+
+**参数描述:**
+
+- `server_id`-服务ID,用来确定某一个服务,类型为整型。
+- `chara_id`-特征ID,类型为整型。
+- `permission`-特征值的权限,2个字节,十六进制数,可通过“或运算”同时指定多个属性,值具体含义如下表,类型为整型。
+
+| 值 | 含义 |
+| ------ | -------------- |
+| 0x0001 | 可读权限 |
+| 0x0002 | 可写权限 |
+| 0x0004 | 读需要认证 |
+| 0x0008 | 读需要授权 |
+| 0x0010 | 读需要加密 |
+| 0x0020 | 读需要授权认证 |
+| 0x0040 | 写需要认证 |
+| 0x0080 | 写需要授权 |
+| 0x0100 | 写需要加密 |
+| 0x0200 | 写需要授权认证 |
+
+- `uuid_type`-uuid类型,0 - 长UUID,128bit;1 - 短UUID,16bit。类型为整型。
+- `uuid_s`-短UUID,2个字节(16bit),类型为整型,当uuid_type为0时,该值给0。
+- `uuid_l`-长UUID,16个字节(128bit),类型为bytearray,当uuid_type为1时,该值填 bytearray([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])。
+- `value`-特征描述数据。类型为bytearray。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+**示例**:
+
+```python
+def ble_gatt_add_characteristic_desc():
+ data = [0x00, 0x00]
+ server_id = 0x01
+ chara_id = 0x01
+ permission = 0x0001 | 0x0002
+ uuid_type = 1 # 短UUID
+ uuid_s = 0x2902
+ uuid_l = bytearray([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])
+ value = bytearray(data)
+ ret = ble.addCharaDesc(server_id, chara_id, permission, uuid_type, uuid_s, uuid_l, value)
+ if ret != 0:
+ print('ble_gatt_add_characteristic_desc failed.')
+ return -1
+ print('ble_gatt_add_characteristic_desc success.')
+ return 0
+```
+
+### ble.addOrClearService
+
+```python
+ble.addOrClearService(option, mode)
+```
+
+增加前面已添加的所有服务信息到模块,或者删除模块中已增加的所有服务信息。
+
+**参数描述:**
+
+- `option`-操作类型,类型为整型。0 - 删除服务,1 - 增加服务。
+- `mode`-是否保留系统默认服务,类型为整型。 0 - 删除系统默认的GAP和GATT服务,1 - 保留系统默认的GAP和GATT服务。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+### ble.sendNotification
+
+```python
+ble.sendNotification(connect_id, attr_handle, value)
+```
+
+发送通知。
+
+**参数描述:**
+
+- `connect_id`-连接ID,类型为整型。
+- `attr_handle`-属性句柄,类型为整型。
+- `value`-要发送的数据,发送数据长度不要超过MTU,类型为bytearray。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+### ble.sendIndication
+
+```python
+ble.sendIndication(connect_id, attr_handle, value)
+```
+
+发送指示。
+
+**参数描述:**
+
+- `connect_id`-连接ID,类型为整型。
+- `attr_handle`-属性句柄,类型为整型。
+- `value`-要发送的数据,发送数据长度不要超过MTU,类型为bytearray。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+### ble.advStart
+
+```python
+ble.advStart()
+```
+
+开启广播。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+### ble.advStop
+
+```python
+ble.advStop()
+```
+
+停止广播。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+## BLE Client相关功能
+
+### ble.clientInit
+
+```python
+ble.clientInit(user_cb)
+```
+
+初始化 BLE Client 并注册回调函数。
+
+**参数描述:**
+
+- `user_cb`-回调函数,类型为function。回调函数参数含义:args[0] 固定表示event_id,args[1] 固定表示状态,0表示成功,非0表示失败。回调函数的参数个数并不是固定2个,而是根据第一个参数args[0]来决定的,下表中列出了不同事件ID对应的参数个数及说明。
+
+| event_id | 参数个数 | 参数说明 |
+| :------: | :------: | ------------------------------------------------------------ |
+| 0 | 2 | args[0] :event_id,表示 BT/BLE start
args[1] :status,表示操作的状态,0-成功,非0-失败 |
+| 1 | 2 | args[0] :event_id,表示 BT/BLE stop
args[1] :status,表示操作的状态,0-成功,非0-失败 |
+| 16 | 4 | args[0] :event_id,表示 BLE connect
args[1] :status,表示操作的状态,0-成功,非0-失败
args[2] :connect_id
args[3] :addr,BT/BLE address,bytearray类型数据 |
+| 17 | 4 | args[0] :event_id,表示 BLE disconnect
args[1] :status,表示操作的状态,0-成功,非0-失败
args[2] :connect_id,
args[3] :addr,BT/BLE address,bytearray类型数据 |
+| 18 | 7 | args[0] :event_id,表示 BLE update connection parameter
args[1] :status,表示操作的状态,0-成功,非0-失败
args[2] :connect_id
args[3] :max_interval,最大的间隔,间隔:1.25ms,取值范围:6-3200,时间范围:7.5ms ~ 4s
args[4] :min_interval,最小的间隔,间隔:1.25ms,取值范围:6-3200,时间范围:7.5ms ~ 4s
args[5] :latency,从机忽略连接状态事件的时间。需满足:(1+latecy)\*max_interval\*2\*1.25args[6] :timeout,没有交互,超时断开时间,间隔:10ms,取值范围:10-3200,时间范围:100ms ~ 32s |
+| 19 | 9 | args[0] :event_id,表示 BLE scan report
args[1] :status,表示操作的状态,0-成功,非0-失败
args[2] :event_type
args[3] :扫描到的设备名称
args[4] :设备地址类型
args[5] :设备地址,bytearray类型数据
args[6] :rssi,信号强度
args[7] :data_len,扫描的原始数据长度
args[8] :data,扫描的原始数据 |
+| 20 | 4 | args[0] :event_id,表示 BLE connection mtu
args[1] :status,表示操作的状态,0-成功,非0-失败
args[2] :handle
args[3] :mtu值 |
+| 23 | 4 | args[0] :event_id,表示 client recieve notification,即接收通知
args[1] :status,表示操作的状态,0-成功,非0-失败
args[2] :data_len,数据长度
args[3] :data,包含句柄等数据的原始数据,数据格式及解析见最后的综合示例程序 |
+| 24 | 4 | args[0] :event_id,表示 client recieve indication,即接收指示
args[1] :status,表示操作的状态,0-成功,非0-失败
args[2] :data_len,数据长度
args[3] :data,包含indication的原始数据,数据格式及解析见最后的综合示例程序 |
+| 26 | 2 | args[0] :event_id,表示 start discover service,即开始查找服务
args[1] :status,表示操作的状态,0-成功,非0-失败 |
+| 27 | 5 | args[0] :event_id,表示 discover service,即查找到服务
args[1] :status,表示操作的状态,0-成功,非0-失败
args[2] :start_handle,表示service的开始句柄
args[3] :end_handle,表示service的结束句柄
args[4] :UUID,表示service的UUID(短UUID) |
+| 28 | 4 | args[0] :event_id,表示 discover characteristic,即查找服务特征
args[1] :status,表示操作的状态,0-成功,非0-失败
args[2] :data_len,数据长度
args[3] :data,包含句柄、属性、UUID等数据的原始数据,数据格式及解析见最后的综合示例程序 |
+| 29 | 4 | args[0] :event_id,表示 discover characteristic descriptor,即查找特征描述
args[1] :status,表示操作的状态,0-成功,非0-失败
args[2] :data_len,数据长度
args[3] :data,包含句柄、UUID等数据的原始数据,数据格式及解析见最后的综合示例程序 |
+| 30 | 2 | args[0] :event_id,表示 write characteristic value with response,即写入特征值并需要链路层确认
args[1] :status,表示操作的状态,0-成功,非0-失败 |
+| 31 | 2 | args[0] :event_id,表示 write characteristic value without response,即写入特征值,无需链路层确认
args[1] :status,表示操作的状态,0-成功,非0-失败 |
+| 32 | 4 | args[0] :event_id,表示 read characteristic value by handle,即通过句柄来读取特征值
args[1] :status,表示操作的状态,0-成功,非0-失败
args[2] :data_len,数据长度
args[3] :data,原始数据 |
+| 33 | 4 | args[0] :event_id,表示 read characteristic value by uuid,即通过UUID来读取特征值
args[1] :status,表示操作的状态,0-成功,非0-失败
args[2] :data_len,数据长度
args[3] :data,原始数据 |
+| 34 | 4 | args[0] :event_id,表示 read miltiple characteristic value,即读取多个特征值
args[1] :status,表示操作的状态,0-成功,非0-失败
args[2] :data_len,数据长度
args[3] :data,原始数据 |
+| 35 | 2 | args[0] :event_id,表示 wirte characteristic descriptor,即写入特征描述,需链路层确认
args[1] :status,表示操作的状态,0-成功,非0-失败 |
+| 36 | 4 | args[0] :event_id,表示 read characteristic descriptor,即读特征描述
args[1] :status,表示操作的状态,0-成功,非0-失败
args[2] :data_len,数据长度
args[3] :data,原始数据 |
+| 37 | 3 | args[0] :event_id,表示 attribute error,即属性错误
args[1] :status,表示操作的状态,0-成功,非0-失败
args[2] :errcode,错误码 |
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+### ble.clientRelease
+
+```python
+ble.clientRelease()
+```
+
+BLE Client 资源释放。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+### ble.setScanParam
+
+```python
+ble.setScanParam(scan_mode, interval, scan_window, filter_policy, addr_type)
+```
+
+设置扫描参数。
+
+**参数描述:**
+
+- `scan_mode`-扫描模式,类型为整型。扫描模式,默认为积极扫描。0 - 消极扫描,1 - 积极扫描。
+- `interval`-扫描间隔,类型为整型。范围0x0004-0x4000,时间间隔 = interval \* 0.625,单位ms。
+- `scan_window`-一次扫描的时间,类型为整型。范围0x0004-0x4000,扫描时间 = scan_window\* 0.625,单位ms。
+- `filter_policy`-扫描过滤策略,类型为整型。默认为0。0 - 除了不是本设备的定向广播,其他所有的广播包,1 - 除了不是本设备的定向广播,白名单设备的广播包,2 - 非定向广播,指向本设备的定向广播或使用Resolvable private address的定向广播,3 - 白名单设备非定向广播,指向本设备的定向广播或使用Resolvable private address的定向广播。
+- `addr_type`-本地地址类型,类型为整型。0 - 公共地址,1 - 随机地址。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+**注意**:
+
+扫描时间 `scan_window` 不能大于扫描间隔 `interval` 。如果两者相等,则表示连续不停的扫描。此时 BLE 的 Controller 会连续运行扫描,占满系统资源而导致无法执行其他任务。所以不允许设置连续扫描。并且不建议将时间设置的太短,扫描越频繁则功耗越高。
+
+### ble.scanStart
+
+```python
+ble.scanStart()
+```
+
+开始扫描。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+### ble.scanStop
+
+```python
+ble.scanStop()
+```
+
+停止扫描。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+### ble.setScanFilter
+
+```python
+ble.setScanFilter(act)
+```
+
+打开或者关闭扫描过滤。如果打开,那么扫描设备的广播数据时,同一个设备的广播数据只会上报一次;如果关闭,则同一个设备的所有的广播数据都会上报。
+
+**参数描述:**
+
+- `act`-扫描过滤开关,类型为整型。0 - 关闭扫描过滤功能,1 - 打开扫描过滤功能。默认打开过滤功能。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+### ble.connect
+
+```python
+ble.connect(addr_type, addr)
+```
+
+根据指定的设备地址去连接设备。
+
+**参数描述:**
+
+- `addr_type`-地址类型,类型为整型。0 - 公共地址,1 - 随机地址。
+- `addr`-BLE地址,类型为bytearray,大小为6字节。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+### ble.cancelConnect
+
+```python
+ble.cancelConnect(addr)
+```
+
+取消正在建立的连接。
+
+**参数描述:**
+
+- `addr`-BLE地址,类型为bytearray,大小为6字节。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+### ble.disconnect
+
+```python
+ble.disconnect(connect_id)
+```
+
+断开已建立的连接。
+
+**参数描述:**
+
+- `connect_id`-连接ID,建立连接时得到的连接ID,类型为整型。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+### ble.discoverAllService
+
+```python
+ble.discoverAllService(connect_id)
+```
+
+扫描所有的服务。
+
+**参数描述:**
+
+- `connect_id`-连接ID,建立连接时得到的连接ID,类型为整型。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+### ble.discoverByUUID
+
+```python
+ble.discoverByUUID(connect_id, uuid_type, uuid_s, uuid_l)
+```
+
+扫描指定UUID的服务。
+
+**参数描述:**
+
+- `connect_id`-连接ID,建立连接时得到的连接ID,类型为整型。
+- `uuid_type`-uuid类型,0 - 长UUID,128bit;1 - 短UUID,16bit。类型为整型。
+- `uuid_s`-短UUID,2个字节(16bit),类型为整型,当uuid_type为0时,该值给0。
+- `uuid_l`-长UUID,16个字节(128bit),类型为bytearray,当uuid_type为1时,该值填 bytearray([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+### ble.discoverAllIncludes
+
+```python
+ble.discoverAllIncludes(connect_id, start_handle, end_handle)
+```
+
+扫描所有的引用,start_handle和end_handle要属于同一个服务。
+
+**参数描述:**
+
+- `connect_id`-连接ID,建立连接时得到的连接ID,类型为整型。
+- `start_handle`-开始句柄,从这个句柄开始寻找引用,类型为整型。
+- `end_handle`-结束句柄,从这个句柄结束寻找引用,类型为整型。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+### ble.discoverAllChara
+
+```python
+ble.discoverAllChara(connect_id, start_handle, end_handle)
+```
+
+扫描所有的特征,start_handle和end_handle要属于同一个服务。
+
+**参数描述:**
+
+- `connect_id`-连接ID,建立连接时得到的连接ID,类型为整型。
+- `start_handle`-开始句柄,从这个句柄开始寻找特征,类型为整型。
+- `end_handle`-结束句柄,从这个句柄结束寻找特征,类型为整型。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+### ble.discoverAllCharaDesc
+
+```python
+ble.discoverAllCharaDesc(connect_id, start_handle, end_handle)
+```
+
+扫描所有特征的描述,start_handle和end_handle要属于同一个服务。
+
+**参数描述:**
+
+- `connect_id`-连接ID,建立连接时得到的连接ID,类型为整型。
+- `start_handle`-开始句柄,从这个句柄开始寻找特征描述,类型为整型。
+- `end_handle`-结束句柄,从这个句柄结束寻找特征描述,类型为整型。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+### ble.readCharaByUUID
+
+```python
+ble.readCharaByUUID(connect_id, start_handle, end_handle, uuid_type, uuid_s, uuid_l)
+```
+
+读取指定UUID的特征值,start_handle和end_handle必须要包含一个特征值句柄。
+
+**参数描述:**
+
+- `connect_id`-连接ID,建立连接时得到的连接ID,类型为整型。
+- `start_handle`-开始句柄,一定要属于同一个特征的句柄,类型为整型。
+- `end_handle`-结束句柄,结束句柄,一定要属于同一个特征的句柄,类型为整型。
+- `uuid_type`-uuid类型,0 - 长UUID,128bit;1 - 短UUID,16bit。类型为整型。
+- `uuid_s`-短UUID,2个字节(16bit),类型为整型,当uuid_type为0时,该值给0。
+- `uuid_l`-长UUID,16个字节(128bit),类型为bytearray,当uuid_type为1时,该值填 bytearray([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+### ble.readCharaByHandle
+
+```python
+ble.readCharaByHandle(connect_id, handle, offset, is_long)
+```
+
+读取指定句柄的特征值。
+
+**参数描述:**
+
+- `connect_id`-连接ID,建立连接时得到的连接ID,类型为整型。
+- `handle`-特征值句柄,类型为整型。
+- `offset`-偏移位置,类型为整型。
+- `is_long`-长特征值标志,0-短特征值,一次可以读取完;1-长特征值,分多次读取。类型为整型。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+### ble.readCharaDesc
+
+```python
+ble.readCharaDesc(connect_id, handle, is_long)
+```
+
+读取特征描述。
+
+**参数描述:**
+
+- `connect_id`-连接ID,建立连接时得到的连接ID,类型为整型。
+- `handle`-特征值句柄,类型为整型。
+- `is_long`-长特征值标志,0-短特征值,一次可以读取完;1-长特征值,分多次读取。类型为整型。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+### ble.writeChara
+
+```python
+ble.writeChara(connect_id, handle, offset, is_long, data)
+```
+
+写入特征值,需要对端应答。
+
+**参数描述:**
+
+- `connect_id`-连接ID,建立连接时得到的连接ID,类型为整型。
+- `handle`-特征值句柄,类型为整型。
+- `offset`-偏移位置,类型为整型。
+- `is_long`-长特征值标志,0-短特征值,一次可以读取完;1-长特征值,分多次读取。类型为整型。
+- `data`-特征值数据,类型为bytearray。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+### ble.writeCharaNoRsp
+
+```python
+ble.writeCharaNoRsp(connect_id, handle, data)
+```
+
+写入特征值,不需要对端应答。
+
+**参数描述:**
+
+- `connect_id`-连接ID,建立连接时得到的连接ID,类型为整型。
+- `handle`-特征值句柄,类型为整型。
+- `data`-特征值数据,类型为bytearray。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+### ble.writeCharaDesc
+
+```python
+ble.writeCharaDesc(connect_id, handle, data)
+```
+
+写入特征描述。
+
+**参数描述:**
+
+- `connect_id`-连接ID,建立连接时得到的连接ID,类型为整型。
+- `handle`-特征描述句柄,类型为整型。
+- `data`-特征描述数据,类型为bytearray。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
\ No newline at end of file
diff --git "a/docs/API_reference/zh/QuecPython\347\261\273\345\272\223/bt.md" "b/docs/API_reference/zh/QuecPython\347\261\273\345\272\223/bt.md"
new file mode 100644
index 0000000000000000000000000000000000000000..b3b034019cd634abd35d98563cbcbede520a3d63
--- /dev/null
+++ "b/docs/API_reference/zh/QuecPython\347\261\273\345\272\223/bt.md"
@@ -0,0 +1,1557 @@
+# bt - 经典蓝牙相关功能
+
+`bt`模块提供经典蓝牙的相关功能,支持HFP、A2DP、AVRCP、SPP。
+
+**示例**:
+
+```python
+#HFP 示例程序
+
+"""
+示例说明:本例程提供一个通过HFP自动接听电话的功能
+运行平台:EC600UCN_LB 铀开发板
+运行本例程后,通过手机A搜索到设备名并点击连接;然后通过手机B拨打电话给手机A,
+当手机A开始响铃震动时,设备会自动接听电话
+"""
+import bt
+import utime
+import _thread
+from queue import Queue
+from machine import Pin
+
+# 如果对应播放通道外置了PA,且需要引脚控制PA开启,则需要下面步骤
+# 具体使用哪个GPIO取决于实际使用的引脚
+gpio11 = Pin(Pin.GPIO11, Pin.OUT, Pin.PULL_DISABLE, 0)
+gpio11.write(1)
+
+BT_NAME = 'QuecPython-hfp'
+
+BT_EVENT = {
+ 'BT_START_STATUS_IND': 0, # bt/ble start
+ 'BT_STOP_STATUS_IND': 1, # bt/ble stop
+ 'BT_HFP_CONNECT_IND': 40, # bt hfp connected
+ 'BT_HFP_DISCONNECT_IND': 41, # bt hfp disconnected
+ 'BT_HFP_CALL_IND': 42, # bt hfp call state
+ 'BT_HFP_CALL_SETUP_IND': 43, # bt hfp call setup state
+ 'BT_HFP_NETWORK_IND': 44, # bt hfp network state
+ 'BT_HFP_NETWORK_SIGNAL_IND': 45, # bt hfp network signal
+ 'BT_HFP_BATTERY_IND': 46, # bt hfp battery level
+ 'BT_HFP_CALLHELD_IND': 47, # bt hfp callheld state
+ 'BT_HFP_AUDIO_IND': 48, # bt hfp audio state
+ 'BT_HFP_VOLUME_IND': 49, # bt hfp volume type
+ 'BT_HFP_NETWORK_TYPE': 50, # bt hfp network type
+ 'BT_HFP_RING_IND': 51, # bt hfp ring indication
+ 'BT_HFP_CODEC_IND': 52, # bt hfp codec type
+}
+
+HFP_CONN_STATUS = 0
+HFP_CONN_STATUS_DICT = {
+ 'HFP_DISCONNECTED': 0,
+ 'HFP_CONNECTING': 1,
+ 'HFP_CONNECTED': 2,
+ 'HFP_DISCONNECTING': 3,
+}
+HFP_CALL_STATUS = 0
+HFP_CALL_STATUS_DICT = {
+ 'HFP_NO_CALL_IN_PROGRESS': 0,
+ 'HFP_CALL_IN_PROGRESS': 1,
+}
+
+BT_IS_RUN = 0
+
+msg_queue = Queue(30)
+
+
+def get_key_by_value(val, d):
+ for key, value in d.items():
+ if val == value:
+ return key
+ return None
+
+def bt_callback(args):
+ global msg_queue
+ msg_queue.put(args)
+
+def bt_event_proc_task():
+ global msg_queue
+ global BT_IS_RUN
+ global BT_EVENT
+ global HFP_CONN_STATUS
+ global HFP_CONN_STATUS_DICT
+ global HFP_CALL_STATUS
+ global HFP_CALL_STATUS_DICT
+
+ while True:
+ print('wait msg...')
+ msg = msg_queue.get() # 没有消息时会阻塞在这
+ event_id = msg[0]
+ status = msg[1]
+
+ if event_id == BT_EVENT['BT_START_STATUS_IND']:
+ print('event: BT_START_STATUS_IND')
+ if status == 0:
+ print('BT start successfully.')
+ BT_IS_RUN = 1
+ bt_status = bt.getStatus()
+ if bt_status == 1:
+ print('BT status is 1, normal status.')
+ else:
+ print('BT status is {}, abnormal status.'.format(bt_status))
+ bt.stop()
+ break
+
+ retval = bt.getLocalName()
+ if retval != -1:
+ print('The current BT name is : {}'.format(retval[1]))
+ else:
+ print('Failed to get BT name.')
+ bt.stop()
+ break
+
+ print('Set BT name to {}'.format(BT_NAME))
+ retval = bt.setLocalName(0, BT_NAME)
+ if retval != -1:
+ print('BT name set successfully.')
+ else:
+ print('BT name set failed.')
+ bt.stop()
+ break
+
+ retval = bt.getLocalName()
+ if retval != -1:
+ print('The new BT name is : {}'.format(retval[1]))
+ else:
+ print('Failed to get new BT name.')
+ bt.stop()
+ break
+
+ # 设置蓝牙可见模式为:可以被发现并且可以被连接
+ retval = bt.setVisibleMode(3)
+ if retval == 0:
+ mode = bt.getVisibleMode()
+ if mode == 3:
+ print('BT visible mode set successfully.')
+ else:
+ print('BT visible mode set failed.')
+ bt.stop()
+ break
+ else:
+ print('BT visible mode set failed.')
+ bt.stop()
+ break
+ else:
+ print('BT start failed.')
+ bt.stop()
+ break
+ elif event_id == BT_EVENT['BT_STOP_STATUS_IND']:
+ print('event: BT_STOP_STATUS_IND')
+ if status == 0:
+ BT_IS_RUN = 0
+ print('BT stop successfully.')
+ else:
+ print('BT stop failed.')
+ break
+ elif event_id == BT_EVENT['BT_HFP_CONNECT_IND']:
+ HFP_CONN_STATUS = msg[2]
+ addr = msg[3] # BT 主机端mac地址
+ mac = '{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}'.format(addr[5], addr[4], addr[3], addr[2], addr[1], addr[0])
+ print('BT_HFP_CONNECT_IND, {}, hfp_conn_status:{}, mac:{}'.format(status, get_key_by_value(msg[2], HFP_CONN_STATUS_DICT), mac))
+ if status != 0:
+ print('BT HFP connect failed.')
+ bt.stop()
+ continue
+ elif event_id == BT_EVENT['BT_HFP_DISCONNECT_IND']:
+ HFP_CONN_STATUS = msg[2]
+ addr = msg[3] # BT 主机端mac地址
+ mac = '{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}'.format(addr[5], addr[4], addr[3], addr[2], addr[1], addr[0])
+ print('BT_HFP_DISCONNECT_IND, {}, hfp_conn_status:{}, mac:{}'.format(status, get_key_by_value(msg[2], HFP_CONN_STATUS_DICT), mac))
+ if status != 0:
+ print('BT HFP disconnect failed.')
+ bt.stop()
+ elif event_id == BT_EVENT['BT_HFP_CALL_IND']:
+ call_sta = msg[2]
+ addr = msg[3] # BT 主机端mac地址
+ mac = '{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}'.format(addr[5], addr[4], addr[3], addr[2], addr[1], addr[0])
+ print('BT_HFP_CALL_IND, {}, hfp_call_status:{}, mac:{}'.format(status, get_key_by_value(msg[2], HFP_CALL_STATUS_DICT), mac))
+ if status != 0:
+ print('BT HFP call failed.')
+ bt.stop()
+ continue
+
+ if call_sta == HFP_CALL_STATUS_DICT['HFP_NO_CALL_IN_PROGRESS']:
+ if HFP_CALL_STATUS == HFP_CALL_STATUS_DICT['HFP_CALL_IN_PROGRESS']:
+ HFP_CALL_STATUS = call_sta
+ if HFP_CONN_STATUS == HFP_CONN_STATUS_DICT['HFP_CONNECTED']:
+ print('call ended, ready to disconnect hfp.')
+ retval = bt.hfpDisconnect(addr)
+ if retval == 0:
+ HFP_CONN_STATUS = HFP_CONN_STATUS_DICT['HFP_DISCONNECTING']
+ else:
+ print('Failed to disconnect hfp connection.')
+ bt.stop()
+ continue
+ else:
+ if HFP_CALL_STATUS == HFP_CALL_STATUS_DICT['HFP_NO_CALL_IN_PROGRESS']:
+ HFP_CALL_STATUS = call_sta
+ print('set audio output channel to 2.')
+ bt.setChannel(2)
+ print('set volume to 7.')
+ retval = bt.hfpSetVolume(addr, 7)
+ if retval != 0:
+ print('set volume failed.')
+ elif event_id == BT_EVENT['BT_HFP_CALL_SETUP_IND']:
+ call_setup_status = msg[2]
+ addr = msg[3] # BT 主机端mac地址
+ mac = '{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}'.format(addr[5], addr[4], addr[3], addr[2], addr[1], addr[0])
+ print('BT_HFP_CALL_SETUP_IND, {}, hfp_call_setup_status:{}, mac:{}'.format(status, call_setup_status, mac))
+ if status != 0:
+ print('BT HFP call setup failed.')
+ bt.stop()
+ continue
+ elif event_id == BT_EVENT['BT_HFP_CALLHELD_IND']:
+ callheld_status = msg[2]
+ addr = msg[3] # BT 主机端mac地址
+ mac = '{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}'.format(addr[5], addr[4], addr[3], addr[2], addr[1], addr[0])
+ print('BT_HFP_CALLHELD_IND, {}, callheld_status:{}, mac:{}'.format(status, callheld_status, mac))
+ if status != 0:
+ print('BT HFP callheld failed.')
+ bt.stop()
+ continue
+ elif event_id == BT_EVENT['BT_HFP_NETWORK_IND']:
+ network_status = msg[2]
+ addr = msg[3] # BT 主机端mac地址
+ mac = '{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}'.format(addr[5], addr[4], addr[3], addr[2], addr[1], addr[0])
+ print('BT_HFP_NETWORK_IND, {}, network_status:{}, mac:{}'.format(status, network_status, mac))
+ if status != 0:
+ print('BT HFP network status failed.')
+ bt.stop()
+ continue
+ elif event_id == BT_EVENT['BT_HFP_NETWORK_SIGNAL_IND']:
+ network_signal = msg[2]
+ addr = msg[3] # BT 主机端mac地址
+ mac = '{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}'.format(addr[5], addr[4], addr[3], addr[2], addr[1], addr[0])
+ print('BT_HFP_NETWORK_SIGNAL_IND, {}, signal:{}, mac:{}'.format(status, network_signal, mac))
+ if status != 0:
+ print('BT HFP network signal failed.')
+ bt.stop()
+ continue
+ elif event_id == BT_EVENT['BT_HFP_BATTERY_IND']:
+ battery_level = msg[2]
+ addr = msg[3] # BT 主机端mac地址
+ mac = '{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}'.format(addr[5], addr[4], addr[3], addr[2], addr[1], addr[0])
+ print('BT_HFP_BATTERY_IND, {}, battery_level:{}, mac:{}'.format(status, battery_level, mac))
+ if status != 0:
+ print('BT HFP battery level failed.')
+ bt.stop()
+ continue
+ elif event_id == BT_EVENT['BT_HFP_AUDIO_IND']:
+ audio_status = msg[2]
+ addr = msg[3] # BT 主机端mac地址
+ mac = '{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}'.format(addr[5], addr[4], addr[3], addr[2], addr[1], addr[0])
+ print('BT_HFP_AUDIO_IND, {}, audio_status:{}, mac:{}'.format(status, audio_status, mac))
+ if status != 0:
+ print('BT HFP audio failed.')
+ bt.stop()
+ continue
+ elif event_id == BT_EVENT['BT_HFP_VOLUME_IND']:
+ volume_type = msg[2]
+ addr = msg[3] # BT 主机端mac地址
+ mac = '{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}'.format(addr[5], addr[4], addr[3], addr[2], addr[1], addr[0])
+ print('BT_HFP_VOLUME_IND, {}, volume_type:{}, mac:{}'.format(status, volume_type, mac))
+ if status != 0:
+ print('BT HFP volume failed.')
+ bt.stop()
+ continue
+ elif event_id == BT_EVENT['BT_HFP_NETWORK_TYPE']:
+ service_type = msg[2]
+ addr = msg[3] # BT 主机端mac地址
+ mac = '{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}'.format(addr[5], addr[4], addr[3], addr[2], addr[1], addr[0])
+ print('BT_HFP_NETWORK_TYPE, {}, service_type:{}, mac:{}'.format(status, service_type, mac))
+ if status != 0:
+ print('BT HFP network service type failed.')
+ bt.stop()
+ continue
+ elif event_id == BT_EVENT['BT_HFP_RING_IND']:
+ addr = msg[3] # BT 主机端mac地址
+ mac = '{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}'.format(addr[5], addr[4], addr[3], addr[2], addr[1], addr[0])
+ print('BT_HFP_RING_IND, {}, mac:{}'.format(status, mac))
+ if status != 0:
+ print('BT HFP ring failed.')
+ bt.stop()
+ continue
+ retval = bt.hfpAnswerCall(addr)
+ if retval == 0:
+ print('The call was answered successfully.')
+ else:
+ print('Failed to answer the call.')
+ bt.stop()
+ continue
+ elif event_id == BT_EVENT['BT_HFP_CODEC_IND']:
+ codec_type = msg[2]
+ addr = msg[3] # BT 主机端mac地址
+ mac = '{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}'.format(addr[5], addr[4], addr[3], addr[2], addr[1], addr[0])
+ print('BT_HFP_CODEC_IND, {}, codec_type:{}, mac:{}'.format(status, codec_type, mac))
+ if status != 0:
+ print('BT HFP codec failed.')
+ bt.stop()
+ continue
+ print('Ready to release hfp.')
+ bt.hfpRelease()
+ bt.release()
+
+
+def main():
+ global BT_IS_RUN
+
+ _thread.start_new_thread(bt_event_proc_task, ())
+
+ retval = bt.init(bt_callback)
+ if retval == 0:
+ print('BT init successful.')
+ else:
+ print('BT init failed.')
+ return -1
+ retval = bt.hfpInit()
+ if retval == 0:
+ print('HFP init successful.')
+ else:
+ print('HFP init failed.')
+ return -1
+ retval = bt.start()
+ if retval == 0:
+ print('BT start successful.')
+ else:
+ print('BT start failed.')
+ retval = bt.hfpRelease()
+ if retval == 0:
+ print('HFP release successful.')
+ else:
+ print('HFP release failed.')
+ retval = bt.release()
+ if retval == 0:
+ print('BT release successful.')
+ else:
+ print('BT release failed.')
+ return -1
+
+ count = 0
+ while True:
+ utime.sleep(1)
+ count += 1
+ cur_time = utime.localtime()
+ timestamp = "{:02d}:{:02d}:{:02d}".format(cur_time[3], cur_time[4], cur_time[5])
+
+ if count % 5 == 0:
+ if BT_IS_RUN == 1:
+ print('[{}] BT HFP is running, count = {}......'.format(timestamp, count))
+ print('')
+ else:
+ print('BT HFP has stopped running, ready to exit.')
+ break
+
+
+if __name__ == '__main__':
+ main()
+
+```
+
+```python
+#A2DP/AVRCP 示例程序
+
+"""
+示例说明:本例程提供一个通过A2DP/AVRCP实现的简易蓝牙音乐播放控制功能
+运行本例程后,通过手机搜索到设备名并点击连接;然后打开手机上的音乐播放软件,
+回到例程运行界面,根据提示菜单输入对应的控制命令来实现音乐的播放、暂停、上一首、
+下一首以及设置音量的功能
+"""
+import bt
+import utime
+import _thread
+from queue import Queue
+from machine import Pin
+
+BT_STATUS_DICT = {
+ 'BT_NOT_RUNNING': 0,
+ 'BT_IS_RUNNING': 1
+}
+
+A2DP_AVRCP_CONNECT_STATUS = {
+ 'DISCONNECTED': 0,
+ 'CONNECTING': 1,
+ 'CONNECTED': 2,
+ 'DISCONNECTING': 3
+}
+
+host_addr = 0
+msg_queue = Queue(10)
+
+# 如果对应播放通道外置了PA,且需要引脚控制PA开启,则需要下面步骤
+# 具体使用哪个GPIO取决于实际使用的引脚
+gpio11 = Pin(Pin.GPIO11, Pin.OUT, Pin.PULL_DISABLE, 0)
+gpio11.write(1)
+
+
+def cmd_proc(cmd):
+ cmds = ('1', '2', '3', '4', '5')
+ vols = ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11')
+
+ if cmd in cmds:
+ if cmd == '5':
+ while True:
+ tmp = input('Please input volume: ')
+ if len(tmp) != 1:
+ vol = tmp.split('Please input volume: ')[1]
+ else:
+ vol = tmp
+ if vol in vols:
+ return cmd, int(vol)
+ else:
+ print('Volume should be in [0,11], try again.')
+ else:
+ return cmd, 0
+ else:
+ print('Command {} is not supported!'.format(cmd))
+ return -1
+
+def avrcp_play(args):
+ return bt.avrcpStart()
+
+def avrcp_pause(args):
+ return bt.avrcpPause()
+
+def avrcp_prev(args):
+ return bt.avrcpPrev()
+
+def avrcp_next(args):
+ return bt.avrcpNext()
+
+def avrcp_set_volume(vol):
+ return bt.avrcpSetVolume(vol)
+
+def bt_callback(args):
+ pass
+
+def bt_a2dp_avrcp_proc_task():
+ global msg_queue
+
+ cmd_handler = {
+ '1': avrcp_play,
+ '2': avrcp_pause,
+ '3': avrcp_prev,
+ '4': avrcp_next,
+ '5': avrcp_set_volume,
+ }
+ while True:
+ # print('wait msg...')
+ msg = msg_queue.get()
+ print('recv msg: {}'.format(msg))
+ cmd_handler.get(msg[0])(msg[1])
+
+
+def main():
+ global host_addr
+ global msg_queue
+
+ _thread.start_new_thread(bt_a2dp_avrcp_proc_task, ())
+ bt.init(bt_callback)
+ bt.setChannel(2)
+ retval = bt.a2dpavrcpInit()
+ if retval == 0:
+ print('BT A2DP/AVRCP initialization succeeded.')
+ else:
+ print('BT A2DP/AVRCP initialization failed.')
+ return -1
+
+ retval = bt.start()
+ if retval != 0:
+ print('BT start failed.')
+ return -1
+
+ utime.sleep_ms(1500)
+
+ old_name = bt.getLocalName()
+ if old_name == -1:
+ print('Get BT name error.')
+ return -1
+ print('The current BT name is {}'.format(old_name[1]))
+ new_name = 'QuecPython-a2dp'
+ print('Set new BT name to {}'.format(new_name))
+ retval = bt.setLocalName(0, new_name)
+ if retval == -1:
+ print('Set BT name failed.')
+ return -1
+ cur_name = bt.getLocalName()
+ if cur_name == -1:
+ print('Get new BT name error.')
+ return -1
+ else:
+ if cur_name[1] == new_name:
+ print('BT name changed successfully.')
+ else:
+ print('BT name changed failed.')
+
+ visible_mode = bt.getVisibleMode()
+ if visible_mode != -1:
+ print('The current BT visible mode is {}'.format(visible_mode))
+ else:
+ print('Get BT visible mode error.')
+ return -1
+
+ print('Set BT visible mode to 3.')
+ retval = bt.setVisibleMode(3)
+ if retval == -1:
+ print('Set BT visible mode error.')
+ return -1
+
+ print('BT reconnect check start......')
+ bt.reconnect_set(25, 2)
+ bt.reconnect()
+
+ count = 0
+ while True:
+ count += 1
+ if count % 5 == 0:
+ print('waiting to be connected...')
+ if count >= 10000:
+ count = 0
+ a2dp_status = bt.a2dpGetConnStatus()
+ avrcp_status = bt.avrcpGetConnStatus()
+ if a2dp_status == A2DP_AVRCP_CONNECT_STATUS['CONNECTED'] and avrcp_status == A2DP_AVRCP_CONNECT_STATUS['CONNECTED']:
+ print('========== BT connected! =========')
+ addr = bt.a2dpGetAddr()
+ if addr != -1:
+ mac = '{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}'.format(addr[5], addr[4], addr[3], addr[2], addr[1], addr[0])
+ print('The BT address on the host side: {}'.format(mac))
+ host_addr = addr
+ else:
+ print('Get BT addr error.')
+ return -1
+ print('Please open the music player software on your phone first.')
+ print('Please enter the following options to select a function:')
+ print('========================================================')
+ print('1 : play')
+ print('2 : pause')
+ print('3 : prev')
+ print('4 : next')
+ print('5 : set volume')
+ print('6 : exit')
+ print('========================================================')
+ while True:
+ tmp = input('> ')
+ if len(tmp) != 1:
+ cmd = tmp.split('> ')[1]
+ else:
+ cmd = tmp
+ if cmd == '6':
+ break
+ retval = cmd_proc(cmd)
+ if retval != -1:
+ msg_queue.put(retval)
+ break
+ else:
+ utime.sleep_ms(1000)
+ print('Ready to disconnect a2dp.')
+ retval = bt.a2dpDisconnect(host_addr)
+ if retval == 0:
+ print('a2dp connection disconnected successfully')
+ else:
+ print('Disconnect a2dp error.')
+ print('Ready to stop BT.')
+ retval = bt.stop()
+ if retval == 0:
+ print('BT has stopped.')
+ else:
+ print('BT stop error.')
+ bt.a2dpavrcpRelease()
+ bt.release()
+
+
+if __name__ == '__main__':
+ main()
+```
+
+```python
+#SPP 示例程序
+
+"""
+示例说明:本例程提供一个通过SPP实现与手机端进行数据传输的功能
+(1)运行之前,需要先在手机端(安卓)安装蓝牙串口APP,如BlueSPP,然后打开该软件;
+(2)修改本例程中的目标设备的蓝牙名称,即 DST_DEVICE_INFO['dev_name'] 的值改为用户准备连接的手机的蓝牙名称;
+(3)运行本例程,例程中会先发起搜索周边设备的操作,直到搜索到目标设备,就会结束搜索,然后向目标设备发起SPP连接请求;
+(4)用户注意查看手机界面是否弹出蓝牙配对请求的界面,当出现时,点击配对;
+(5)配对成功后,用户即可进入到蓝牙串口界面,发送数据给设备,设备在收到数据后会回复“I have received the data you sent.”
+(6)手机端APP中点击断开连接,即可结束例程;
+"""
+import bt
+import utime
+import _thread
+from queue import Queue
+
+
+BT_NAME = 'QuecPython-SPP'
+
+BT_EVENT = {
+ 'BT_START_STATUS_IND': 0, # bt/ble start
+ 'BT_STOP_STATUS_IND': 1, # bt/ble stop
+ 'BT_SPP_INQUIRY_IND': 6, # bt spp inquiry ind
+ 'BT_SPP_INQUIRY_END_IND': 7, # bt spp inquiry end ind
+ 'BT_SPP_RECV_DATA_IND': 14, # bt spp recv data ind
+ 'BT_SPP_CONNECT_IND': 61, # bt spp connect ind
+ 'BT_SPP_DISCONNECT_IND': 62, # bt spp disconnect ind
+}
+
+DST_DEVICE_INFO = {
+ 'dev_name': 'HUAWEI Mate40 Pro', # 要连接设备的蓝牙名称
+ 'bt_addr': None
+}
+
+BT_IS_RUN = 0
+msg_queue = Queue(30)
+
+
+def bt_callback(args):
+ global msg_queue
+ msg_queue.put(args)
+
+
+def bt_event_proc_task():
+ global msg_queue
+ global BT_IS_RUN
+ global DST_DEVICE_INFO
+
+ while True:
+ print('wait msg...')
+ msg = msg_queue.get() # 没有消息时会阻塞在这
+ event_id = msg[0]
+ status = msg[1]
+
+ if event_id == BT_EVENT['BT_START_STATUS_IND']:
+ print('event: BT_START_STATUS_IND')
+ if status == 0:
+ print('BT start successfully.')
+ BT_IS_RUN = 1
+
+ print('Set BT name to {}'.format(BT_NAME))
+ retval = bt.setLocalName(0, BT_NAME)
+ if retval != -1:
+ print('BT name set successfully.')
+ else:
+ print('BT name set failed.')
+ bt.stop()
+ continue
+
+ retval = bt.setVisibleMode(3)
+ if retval == 0:
+ mode = bt.getVisibleMode()
+ if mode == 3:
+ print('BT visible mode set successfully.')
+ else:
+ print('BT visible mode set failed.')
+ bt.stop()
+ continue
+ else:
+ print('BT visible mode set failed.')
+ bt.stop()
+ continue
+
+ retval = bt.startInquiry(15)
+ if retval != 0:
+ print('Inquiry error.')
+ bt.stop()
+ continue
+ else:
+ print('BT start failed.')
+ bt.stop()
+ continue
+ elif event_id == BT_EVENT['BT_STOP_STATUS_IND']:
+ print('event: BT_STOP_STATUS_IND')
+ if status == 0:
+ BT_IS_RUN = 0
+ print('BT stop successfully.')
+ else:
+ print('BT stop failed.')
+
+ retval = bt.sppRelease()
+ if retval == 0:
+ print('SPP release successfully.')
+ else:
+ print('SPP release failed.')
+ retval = bt.release()
+ if retval == 0:
+ print('BT release successfully.')
+ else:
+ print('BT release failed.')
+ break
+ elif event_id == BT_EVENT['BT_SPP_INQUIRY_IND']:
+ print('event: BT_SPP_INQUIRY_IND')
+ if status == 0:
+ rssi = msg[2]
+ name = msg[4]
+ addr = msg[5]
+ mac = '{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}'.format(addr[5], addr[4], addr[3], addr[2], addr[1], addr[0])
+ print('name: {}, addr: {}, rssi: {}'.format(name, mac, rssi))
+
+ if name == DST_DEVICE_INFO['dev_name']:
+ print('The target device is found, device name {}'.format(name))
+ DST_DEVICE_INFO['bt_addr'] = addr
+ retval = bt.cancelInquiry()
+ if retval != 0:
+ print('cancel inquiry failed.')
+ continue
+ else:
+ print('BT inquiry failed.')
+ bt.stop()
+ continue
+ elif event_id == BT_EVENT['BT_SPP_INQUIRY_END_IND']:
+ print('event: BT_SPP_INQUIRY_END_IND')
+ if status == 0:
+ print('BT inquiry has ended.')
+ inquiry_sta = msg[2]
+ if inquiry_sta == 0:
+ if DST_DEVICE_INFO['bt_addr'] is not None:
+ print('Ready to connect to the target device : {}'.format(DST_DEVICE_INFO['dev_name']))
+ retval = bt.sppConnect(DST_DEVICE_INFO['bt_addr'])
+ if retval != 0:
+ print('SPP connect failed.')
+ bt.stop()
+ continue
+ else:
+ print('Not found device [{}], continue to inquiry.'.format(DST_DEVICE_INFO['dev_name']))
+ bt.cancelInquiry()
+ bt.startInquiry(15)
+ else:
+ print('Inquiry end failed.')
+ bt.stop()
+ continue
+ elif event_id == BT_EVENT['BT_SPP_RECV_DATA_IND']:
+ print('event: BT_SPP_RECV_DATA_IND')
+ if status == 0:
+ datalen = msg[2]
+ data = msg[3]
+ print('recv {} bytes data: {}'.format(datalen, data))
+ send_data = 'I have received the data you sent.'
+ print('send data: {}'.format(send_data))
+ retval = bt.sppSend(send_data)
+ if retval != 0:
+ print('send data faied.')
+ else:
+ print('Recv data failed.')
+ bt.stop()
+ continue
+ elif event_id == BT_EVENT['BT_SPP_CONNECT_IND']:
+ print('event: BT_SPP_CONNECT_IND')
+ if status == 0:
+ conn_sta = msg[2]
+ addr = msg[3]
+ mac = '{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}'.format(addr[5], addr[4], addr[3], addr[2], addr[1], addr[0])
+ print('SPP connect successful, conn_sta = {}, addr {}'.format(conn_sta, mac))
+ else:
+ print('Connect failed.')
+ bt.stop()
+ continue
+ elif event_id == BT_EVENT['BT_SPP_DISCONNECT_IND']:
+ print('event: BT_SPP_DISCONNECT_IND')
+ conn_sta = msg[2]
+ addr = msg[3]
+ mac = '{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}'.format(addr[5], addr[4], addr[3], addr[2], addr[1], addr[0])
+ print('SPP disconnect successful, conn_sta = {}, addr {}'.format(conn_sta, mac))
+ bt.stop()
+ continue
+
+
+def main():
+ global BT_IS_RUN
+
+ _thread.start_new_thread(bt_event_proc_task, ())
+ retval = bt.init(bt_callback)
+ if retval == 0:
+ print('BT init successful.')
+ else:
+ print('BT init failed.')
+ return -1
+ retval = bt.sppInit()
+ if retval == 0:
+ print('SPP init successful.')
+ else:
+ print('SPP init failed.')
+ return -1
+ retval = bt.start()
+ if retval == 0:
+ print('BT start successful.')
+ else:
+ print('BT start failed.')
+ retval = bt.sppRelease()
+ if retval == 0:
+ print('SPP release successful.')
+ else:
+ print('SPP release failed.')
+ return -1
+
+ count = 0
+ while True:
+ utime.sleep(1)
+ count += 1
+ cur_time = utime.localtime()
+ timestamp = "{:02d}:{:02d}:{:02d}".format(cur_time[3], cur_time[4], cur_time[5])
+
+ if count % 5 == 0:
+ if BT_IS_RUN == 1:
+ print('[{}] BT SPP is running, count = {}......'.format(timestamp, count))
+ print('')
+ else:
+ print('BT SPP has stopped running, ready to exit.')
+ break
+
+
+if __name__ == '__main__':
+ main()
+```
+
+**注意**:
+
+当前仅EC200U/EC600U/EG915U/EG912U平台支持`bt`功能。
+
+## 初始化相关功能
+
+### bt.init
+
+```python
+bt.init(user_cb)
+```
+
+蓝牙初始化并注册回调函数。
+
+**参数描述:**
+
+- `user_cb`-回调函数,类型为function。回调函数参数含义:args[0] 固定表示event_id,args[1] 固定表示状态,0表示成功,非0表示失败。回调函数的参数个数并不是固定2个,而是根据第一个参数args[0]来决定的,下表中列出了不同事件ID对应的参数个数及说明。
+
+| event_id | 参数个数 | 参数说明 |
+| :------: | :------: | ------------------------------------------------------------ |
+| 0 | 2 | args[0] :event_id,表示 BT/BLE start 事件
args[1] :status,表示操作的状态,0 - 成功,非0 - 失败 |
+| 1 | 2 | args[0] :event_id,表示 BT/BLE stop
args[1] :status,表示操作的状态,0 - 成功,非0 - 失败 |
+| 6 | 6 | args[0] :event_id,表示 BT inquiry 事件
args[1] :status,表示操作的状态,0 - 成功,非0 - 失败
args[2] :rssi,搜索到的设备的信号强度;
args[3] :device_class
args[4] :device_name,设备名称,字符串类型
args[5] :addr,搜到的蓝牙设备的mac地址 |
+| 7 | 3 | args[0] :event_id,表示 BT inquiry end 事件
args[1] :status,表示操作的状态,0 - 成功,非0 - 失败
args[2] :end_status,0 - 正常结束搜索,8 - 强制结束搜索 |
+| 14 | 4 | args[0] :event_id,表示 BT spp recv 事件
args[1] :status,表示操作的状态,0 - 成功,非0 - 失败
args[2] :data_len,收到的数据长度
args[3] :data,收到的数据,bytearray类型数据 |
+| 40 | 4 | args[0] :event_id,表示 BT HFP connect 事件
args[1] :status,表示操作的状态,0 - 成功,非0 - 失败
args[2] :hfp_connect_status,表示hfp的连接状态;
0 - 已经断开连接
1 - 连接中
2 - 已经连接
3 - 断开连接中
args[3] :addr,BT 主设备的地址,bytearray类型数据 |
+| 41 | 4 | args[0] :event_id,表示 BT HFP disconnect 事件
args[1] :status,表示操作的状态,0 - 成功,非0 - 失败
args[2] :hfp_connect_status,表示hfp的连接状态;
0 - 已经断开连接
1 - 连接中
2 - 已经连接
3 - 断开连接中
args[3] :addr,BT 主设备的地址,bytearray类型数据 |
+| 42 | 4 | args[0] :event_id,表示 BT HFP call status 事件
args[1] :status,表示操作的状态,0 - 成功,非0 - 失败
args[2] :hfp_call_status,表示hfp的通话状态;
0 - 当前没有正在进行的通话
1 - 当前至少有一个正在进行的通话
args[3] :addr,BT 主设备的地址,bytearray类型数据 |
+| 43 | 4 | args[0] :event_id,表示 BT HFP call setup status 事件
args[1] :status,表示操作的状态,0 - 成功,非0 - 失败
args[2] :hfp_call_setup_status,表示hfp的call setup状态;
0 - 表示没有电话需要接通
1 - 表示有一个拨进来的电话还未接通
2 - 表示有一个拨出去的电话还没有接通
3 - 表示拨出电话的蓝牙连接的另一方正在响铃
args[3] :addr,BT 主设备的地址,bytearray类型数据 |
+| 44 | 4 | args[0] :event_id,表示 BT HFP network status 事件
args[1] :status,表示操作的状态,0 - 成功,非0 - 失败
args[2] :hfp_network_status,表示AG的网络状态;
0 - 表示网络不可用
1 - 表示网络正常
args[3] :addr,BT 主设备的地址,bytearray类型数据 |
+| 45 | 4 | args[0] :event_id,表示 BT HFP network signal 事件
args[1] :status,表示操作的状态,0 - 成功,非0 - 失败
args[2] :hfp_network_signal,表示AG的信号,范围 0~5
args[3] :addr,BT 主设备的地址,bytearray类型数据 |
+| 46 | 4 | args[0] :event_id,表示 BT HFP battery level 事件
args[1] :status,表示操作的状态,0 - 成功,非0 - 失败
args[2] :hfp_battery_level,表示AG端的电池电量,范围 0~5
args[3] :addr,BT 主设备的地址,bytearray类型数据 |
+| 47 | 4 | args[0] :event_id,表示 BT HFP call held status 事件
args[1] :status,表示操作的状态,0 - 成功,非0 - 失败
args[2] :hfp_call_held_status,表示hfp的call held状态;
0 - 表示没有保持呼叫
1 - 表示呼叫被暂停或活动/保持呼叫交换
2 - 表示呼叫暂停,没有活动呼叫
args[3] :addr,BT 主设备的地址,bytearray类型数据 |
+| 48 | 4 | args[0] :event_id,表示 BT HFP audio status 事件
args[1] :status,表示操作的状态,0 - 成功,非0 - 失败
args[2] :hfp_audio_status,表示audio连接状态;
0 - 表示audio已经断开连接
1 - 表示audio正在连接中
2 - 表示audio已经连接成功
3 - 表示audio正在断开连接
args[3] :addr,BT 主设备的地址,bytearray类型数据 |
+| 49 | 4 | args[0] :event_id,表示 BT HFP volume type 事件
args[1] :status,表示操作的状态,0 - 成功,非0 - 失败
args[2] :hfp_volume_type
0 - 表示volume type为speaker
1 - 表示volume type为microphone
args[3] :addr,BT 主设备的地址,bytearray类型数据 |
+| 50 | 4 | args[0] :event_id,表示 BT HFP service type 事件
args[1] :status,表示操作的状态,0 - 成功,非0 - 失败
args[2] :hfp_service_type,表示当前AG的网络服务模式;
0 - 表示AG当前为正常网络模式
1 - 表示AG当前处于漫游模式
args[3] :addr,BT 主设备的地址,bytearray类型数据 |
+| 51 | 4 | args[0] :event_id,表示 BT HFP ring 事件,即来电时响铃事件
args[1] :status,表示操作的状态,0 - 成功,非0 - 失败
args[2] :当前无实际意义,保留
args[3] :addr,BT 主设备的地址,bytearray类型数据 |
+| 52 | 4 | args[0] :event_id,表示 BT HFP codec type 事件,即编解码模式
args[1] :status,表示操作的状态,0 - 成功,非0 - 失败
args[2] :hfp_codec_type,表示当前使用哪个编解码模式;
1 - 表示 CVDS,采用8kHz采样率
2 - 表示mSBC,采用16kHz采样率
args[3] :addr,BT 主设备的地址,bytearray类型数据 |
+| 61 | 4 | args[0] :event_id,表示 BT SPP connect 事件
args[1] :status,表示操作的状态,0 - 成功,非0 - 失败
args[2] :spp_connect_status,表示spp的连接状态;
0 - 已经断开连接
1 - 连接中
2 - 已经连接
3 - 断开连接中
args[3] :addr,对端设备的mac地址,bytearray类型数据 |
+| 62 | 4 | args[0] :event_id,表示 BT SPP disconnect 事件
args[1] :status,表示操作的状态,0 - 成功,非0 - 失败
args[2] :spp_connect_status,表示spp的连接状态;
0 - 已经断开连接
1 - 连接中
2 - 已经连接
3 - 断开连接中
args[3] :addr,对端设备的mac地址,bytearray类型数据 |
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+**示例**:
+
+```python
+def bt_callback(args):
+ event_id = args[0] # 第一个参数固定是 event_id
+ status = args[1] # 第二个参数固定是状态,表示某个操作的执行结果是成功还是失败
+ ......
+```
+
+### bt.release
+
+```python
+bt.release()
+```
+
+蓝牙资源释放。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+### bt.start
+
+```python
+bt.start()
+```
+
+开启蓝牙功能。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+### bt.stop
+
+```python
+bt.stop()
+```
+
+关闭蓝牙功能。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+### bt.getStatus
+
+```python
+bt.getStatus()
+```
+
+获取蓝牙的状态。
+
+**返回值描述:**
+
+- 蓝牙状态:类型为整型,0-蓝牙处于停止状态,1-蓝牙正常运行中,-1-获取状态失败。
+
+### bt.getLocalAddr
+
+```python
+bt.getLocalAddr()
+```
+
+获取蓝牙地址。
+
+**返回值描述:**
+
+- 蓝牙地址:执行成功返回类型为bytearray的蓝牙地址,大小6字节,失败返回整型-1。
+
+**示例**:
+
+```python
+>>> addr = bt.getLocalAddr()
+>>> print(addr)
+b'\xc7\xa13\xf8\xbf\x1a'
+>>> mac = '{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}'.format(addr[5], addr[4], addr[3], addr[2], addr[1], addr[0])
+>>> print('mac = [{}]'.format(mac))
+mac = [1a:bf:f8:33:a1:c7]
+```
+
+**注意**:
+
+该接口需要在蓝牙已经初始化完成并启动成功后才能调用,比如在回调中收到 event_id 为0的事件之后,即 start 成功后,去调用。
+
+### bt.setLocalName
+
+```python
+bt.setLocalName(code, name)
+```
+
+设置蓝牙名称。
+
+**参数描述:**
+
+- `code`-编码模式,类型为整型,0 - UTF8,1 - GBK。
+- `name`-蓝牙名称,类型为string,最大长度22字节。
+
+**返回值描述:**
+
+- 蓝牙地址:执行成功返回类型为bytearray的蓝牙地址,大小6字节,失败返回整型-1。
+
+**示例**:
+
+```python
+>>> bt.setLocalName(0, 'QuecPython-BT')
+0
+```
+
+### bt.getLocalName
+
+```python
+bt.getLocalName()
+```
+
+获取蓝牙名称。
+
+**返回值描述:**
+
+- 执行成功返回一个元组`(code, name)`,包含名称编码模式和蓝牙名称,失败返回整型-1。
+
+
+**示例**:
+
+```python
+>>> bt.getLocalName()
+(0, 'QuecPython-BT')
+```
+
+### bt.setVisibleMode
+
+```python
+bt.setVisibleMode(mode)
+```
+
+设置蓝牙可见模式,即做从机时,被扫描时,是否可见以及可连接。
+
+**参数描述:**
+
+- `mode`-可见模式,类型为整型,具体含义如下表。
+
+| 值 | 含义 |
+| ---- | ------------------------ |
+| 0 | 不可被发现,不可被连接 |
+| 1 | 可以被发现,但不可被连接 |
+| 2 | 不可被发现,但可被连接 |
+| 3 | 可以被发现,可被连接 |
+
+**返回值描述:**
+
+- 蓝牙地址:执行成功返回类型为bytearray的蓝牙地址,大小6字节,失败返回整型-1。
+
+**示例**:
+
+```python
+>>> bt.setVisibleMode(3)
+0
+```
+
+### bt.getVisibleMode
+
+```python
+bt.getVisibleMode()
+```
+
+获取蓝牙可见模式。
+
+**返回值描述:**
+
+- 执行成功返回蓝牙当前的可见模式值,失败返回整型-1。
+
+**示例**:
+
+```python
+>>> bt.getVisibleMode()
+3
+```
+
+### bt.startInquiry
+
+```python
+bt.startInquiry(mode)
+```
+
+开始搜索周边的蓝牙设备。
+
+**参数描述:**
+
+- `mode`-搜索类型。表示查询哪一类设备,当前直接写15,表示搜索所有。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+**示例**:
+
+```python
+bt.startInquiry(15)
+```
+
+### bt.cancelInquiry
+
+```python
+bt.cancelInquiry()
+```
+
+取消搜索操作。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+### bt.setChannel
+
+```python
+bt.setChannel(channel)
+```
+
+设置音频输出通道,使用场景为蓝牙接听电话或者播放音频时。
+
+**参数描述:**
+
+- `channel`-音频通道,类型为整型。0 - 听筒,1 - 耳机,2 - 喇叭。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+### bt.reconnect_set
+
+```python
+bt.reconnect_set(max_count, period)
+```
+
+配置尝试重连的最大次数和相邻2次尝试重连的时间间隔,使用场景为模块和蓝牙设备距离拉远后断开连接时。
+
+**参数描述:**
+
+- `max_count`-尝试重连的最大次数,类型为整型,设置0则关闭自动重连功能。
+- `period`-相邻2次尝试重连的时间间隔,单位秒,类型为整型。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+**示例**:
+
+```python
+bt.reconnect_set(25, 2)#配置尝试重连的最大次数为25,每次尝试重连的间隔为2秒
+```
+
+### bt.reconnect
+
+```python
+bt.reconnect()
+```
+
+模组主动重连上次配对过的设备,如手机。使用场景为模组重启后重新初始化打开蓝牙、或者模组不重启仅关闭蓝牙再重新打开蓝牙。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+**示例**:
+
+参考A2DP示例程序。
+
+## HFP相关功能
+
+提供蓝牙通话相关功能。
+
+### bt.hfpInit
+
+```python
+bt.hfpInit()
+```
+
+HFP 功能初始化 。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+### bt.hfpRelease
+
+```python
+bt.hfpRelease()
+```
+
+HFP 资源释放。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+### bt.hfpConnect
+
+```python
+bt.hfpConnect(addr)
+```
+
+连接AG,建立HFP连接。
+
+**参数描述:**
+
+- `addr`-AG端蓝牙地址,6个字节,类型为bytearray。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+### bt.hfpDisonnect
+
+```python
+bt.hfpDisonnect(addr)
+```
+
+断开HFP连接。
+
+**参数描述:**
+
+- `addr`-AG端蓝牙地址,6个字节,类型为bytearray。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+### bt.hfpSetVolume
+
+```python
+bt.hfpSetVolume(addr, vol)
+```
+
+设置蓝牙通话时的音量。
+
+**参数描述:**
+
+- `addr`-AG端蓝牙地址,6个字节,类型为bytearray。
+- `vol`-通话音量,类型为整型,范围 1-15。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+### bt.hfpRejectAfterAnswer
+
+```python
+bt.hfpRejectAfterAnswer(addr)
+```
+
+挂断接通的电话。
+
+**参数描述:**
+
+- `addr`-AG端蓝牙地址,6个字节,类型为bytearray。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+### bt.hfpRejectCall
+
+```python
+bt.hfpRejectCall(addr)
+```
+
+拒接电话。
+
+**参数描述:**
+
+- `addr`-AG端蓝牙地址,6个字节,类型为bytearray。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+### bt.hfpAnswerCall
+
+```python
+bt.hfpAnswerCall(addr)
+```
+
+接听电话。
+
+**参数描述:**
+
+- `addr`-AG端蓝牙地址,6个字节,类型为bytearray。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+### bt.hfpEnableVR
+
+```python
+bt.hfpEnableVR(addr)
+```
+
+开启语音助手。
+
+**参数描述:**
+
+- `addr`-AG端蓝牙地址,6个字节,类型为bytearray。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+### bt.hfpDisableVR
+
+```python
+bt.hfpDisableVR(addr)
+```
+
+关闭语音助手。
+
+**参数描述:**
+
+- `addr`-AG端蓝牙地址,6个字节,类型为bytearray。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+### bt.hfpDisableVR
+
+```python
+bt.hfpDisableVR(addr, cmd)
+```
+
+三方通话控制。
+
+**参数描述:**
+
+- `addr`-AG端蓝牙地址,6个字节,类型为bytearray。
+- `cmd`-控制命令,类型为整型。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+## A2DP/AVRCP相关功能
+
+提供蓝牙音乐相关功能。
+
+### bt.a2dpavrcpInit
+
+```python
+bt.a2dpavrcpInit()
+```
+
+A2DP和AVRCP功能初始化。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+### bt.a2dpavrcpRelease
+
+```python
+bt.a2dpavrcpRelease()
+```
+
+A2DP和AVRCP 资源释放。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+### bt.a2dpDisconnect
+
+```python
+bt.a2dpDisconnect(addr)
+```
+
+断开A2DP连接。
+
+**参数描述:**
+
+- `addr`-A2DP主机蓝牙地址,6个字节,类型为bytearray。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+### bt.a2dpGetAddr
+
+```python
+bt.a2dpGetAddr()
+```
+
+获取A2DP主机蓝牙地址。
+
+**返回值描述:**
+
+- 执行成功返回bytearray类型的A2DP主机蓝牙地址,6字节,失败返回整型-1。
+
+### bt.a2dpGetConnStatus
+
+```python
+bt.a2dpGetConnStatus()
+```
+
+获取A2DP连接状态。
+
+**返回值描述:**
+
+- A2DP连接状态,具体含义如下表。
+
+| 值 | 类型 | 含义 |
+| ---- | ---- | ------------ |
+| -1 | int | 获取失败 |
+| 0 | int | 连接已断开 |
+| 1 | int | 正在连接中 |
+| 2 | int | 已连接 |
+| 3 | int | 正在断开连接 |
+
+### bt.avrcpStart
+
+```python
+bt.avrcpStart()
+```
+
+控制主机开始播放。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+### bt.avrcpPause
+
+```python
+bt.avrcpPause()
+```
+
+控制主机停止播放。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+### bt.avrcpPrev
+
+```python
+bt.avrcpPrev()
+```
+
+控制主机播放上一首。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+### bt.avrcpNext
+
+```python
+bt.avrcpNext()
+```
+
+控制主机播放下一首。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+### bt.avrcpSetVolume
+
+```python
+bt.avrcpSetVolume(vol)
+```
+
+设置主机播放音量。
+
+**参数描述:**
+
+- `vol`-播放音量,类型为整型,范围 0 - 11。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+### bt.avrcpGetVolume
+
+```python
+bt.avrcpGetVolume()
+```
+
+获取主机播放音量。
+
+**返回值描述:**
+
+- 执行成功返回整形音量值,失败返回整型-1。
+
+### bt.avrcpGetPlayStatus
+
+```python
+bt.avrcpGetPlayStatus()
+```
+
+获取主机播放状态。
+
+**返回值描述:**
+
+- 播放状态,具体含义如下表。
+
+| 值 | 类型 | 说明 |
+| ---- | ---- | -------------- |
+| -1 | int | 获取失败 |
+| 0 | int | 没有播放 |
+| 1 | int | 正在播放 |
+| 2 | int | 暂停播放 |
+| 3 | int | 正在切换下一首 |
+| 4 | int | 正在切换下一首 |
+
+### bt.avrcpGetConnStatus
+
+```python
+bt.avrcpGetConnStatus()
+```
+
+通过AVRCP协议获取主机连接状态。
+
+**返回值描述:**
+
+- 连接状态,具体含义如下表。
+
+| 值 | 类型 | 说明 |
+| ---- | ---- | ------------ |
+| -1 | int | 获取失败 |
+| 0 | int | 连接已断开 |
+| 1 | int | 正在连接中 |
+| 2 | int | 已连接 |
+| 3 | int | 正在断开连接 |
+
+## SPP相关功能
+
+提供蓝牙传输相关功能。
+
+### bt.sppInit
+
+```python
+bt.sppInit()
+```
+
+SPP 功能初始化。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+### bt.sppRelease
+
+```python
+bt.sppRelease()
+```
+
+SPP 资源释放。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+### bt.sppConnect
+
+```python
+bt.sppConnect(addr)
+```
+
+建立SPP连接。
+
+**参数描述:**
+
+- `addr`-蓝牙地址,类型为bytearray,6个字节。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+### bt.sppDisconnect
+
+```python
+bt.sppDisconnect()
+```
+
+断开SPP连接。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
+### bt.sppSend
+
+```python
+bt.sppSend(data)
+```
+
+**参数描述:**
+
+- `data`-待发送的数据,类型为bytearray。
+
+**返回值描述:**
+
+- 执行成功返回整型0,失败返回整型-1。
+
diff --git a/docs/API_reference/zh/sidebar.yaml b/docs/API_reference/zh/sidebar.yaml
index 2d294fabba0ae5090b1dd1effca4689ceb8ec299..48c445a149c7e720dc01e5b7938f72de284f1004 100644
--- a/docs/API_reference/zh/sidebar.yaml
+++ b/docs/API_reference/zh/sidebar.yaml
@@ -53,6 +53,10 @@ items:
file: QuecPython类库/cellLocator.md
- label: wifilocator - WIFI定位
file: QuecPython类库/wifilocator.md
+ - label: fota - 固件升级相关功能
+ file: QuecPython类库/fota.md
+ - label: app_fota - 用户文件升级相关功能
+ file: QuecPython类库/app_fota.md
- label: checkNet - 网络就绪检测
file: QuecPython类库/checkNet.md
- label: wifiScan - WiFi扫描
@@ -82,6 +86,10 @@ items:
file: QuecPython类库/quecgnss.md
- label: securedata - 安全数据区
file: QuecPython类库/securedata.md
+ - label: ble - 低功耗蓝牙相关功能
+ file: QuecPython类库/ble.md
+ - label: bt - 经典蓝牙相关功能
+ file: QuecPython类库/bt.md
- label: QuecPython组件库
file: QuecPython组件库/README.md
items: