Last Updated on : 2024-11-20 08:51:48download
This topic describes the Bluetooth pairing process. After reading this topic, you will get to know how to perform Bluetooth pairing and complete adaptation of Bluetooth pairing in the integrated gateway SDK.
Bluetooth pairing is to transmit pairing information over Bluetooth, such as the activation token, and the SSID and password of a router, and thus complete the pairing of devices.
The process of Bluetooth pairing works like this: The gateway sends device information through Bluetooth broadcast, and the mobile app receives and parses the Bluetooth broadcast packet. If the broadcast packet contains Tuya’s services, the mobile app initiates a scan request to further get the device details. After getting the complete information, the mobile app will display devices waiting for pairing. When a user chooses to activate the device, the mobile app establishes a Bluetooth connection to the gateway and sends the pairing information to the gateway over Bluetooth. The gateway gets the pairing information to complete the activation process.
Tuya Bluetooth pairing uses private services and private data. All data is parsed and encapsulated by the SDK, so you do not need to care about the data content.
If you use Tuya Bluetooth module designed for the gateway, the adaptation of the Bluetooth pairing has been implemented in the SDK, and the application does not need any code for adaptation. For more information, see Tuya Bluetooth Service Guide.
If a custom module is used, you need to complete the interface adaptation. The SDK has implemented the underlying logic of Bluetooth pairing and defined a set of adaptation interfaces. This section describes how to complete the adaptation.
The following figure shows the interaction process of Bluetooth pairing:
A Bluetooth device is paired in the following steps:
The following figure shows the data format of Bluetooth broadcast and scan response.
The Bluetooth broadcast and scan responses are defined in the Bluetooth specification. The SDK encapsulates the broadcast data and scan response data into the AD Structure format. The application does not need additional parsing and can use the data directly in the broadcast and scan response.
The following figure shows the data format of Bluetooth transmission.
After a Bluetooth connection is established between the mobile app and the gateway, the data is transmitted based on the Attribute Protocol (ATT). The data encapsulated and parsed by the SDK belongs to the ATT payload.
Service UUID: 0x1910
.
Characteristic | UUID | Attribute | Description |
---|---|---|---|
Write characteristic | 0x2B11 | Write without response | The mobile app sends data to the Bluetooth LE device. |
Notify characteristic | 0x2B10 | Notify | The Bluetooth LE device sends data to the mobile app. |
Next, perform the following steps to complete adaptation of Bluetooth pairing:
Before initializing the SDK, initialize the registration of the Bluetooth adaptation.
// ...
#if defined(TY_BT_MOD) && (TY_BT_MOD == 1)
#include "tuya_os_adapt_bt.h"
#endif
int main(int argc, char **argv)
{
/**
* Must be called earlier than other interfaces of the SDK
*/
#if defined(TY_BT_MOD) && (TY_BT_MOD == 1)
tuya_os_adapt_reg_bt_intf();
#endif
tuya_os_intf_init();
// ...
}
Adapt to the following interface to initialize the Bluetooth protocol stack, configure the Bluetooth to the Bluetooth LE central device mode, and save the function pointer of data processing. Through the function pointer, the received Bluetooth data will be sent to the SDK for processing.
TY_BT_MSG_CB bt_msg_cb;
OPERATE_RET tuya_adapter_bt_port_init(ty_bt_param_t *p)
{
/**
* The following features need to be implemented in the function:
* a) Initialize the Bluetooth protocol stack to ensure normal communications over Bluetooth.
* b) Save the function pointer variable, and pass the received Bluetooth data to the SDK through the function pointer.
*/
bt_msg_cb = p->cb;
return OPRT_OK;
}
Adapt to the interface of resetting the Bluetooth broadcast data, save the broadcast data and scan response data, and enable the broadcast.
tuya_ble_data_buf_t adv_data = {0};
tuya_ble_data_buf_t rsp_data = {0};
OPERATE_RET tuya_adapter_bt_adv_reset(tuya_ble_data_buf_t *adv, tuya_ble_data_buf_t *scan_resp)
{
if ((adv == NULL) || (adv->len == 0) || (scan_resp == NULL) || (scan_resp->len == 0)) {
return OPRT_INVALID_PARM;
}
if (adv_data.data != NULL) {
Free(adv_data.data);
adv_data.data = NULL;
}
adv_data.len = adv->len;
adv_data.data = Malloc(adv_data.len);
if (adv_data.data != NULL) {
memcpy(adv_data.data, adv->data, adv->len);
}
if (rsp_data.data != NULL) {
Free(rsp_data.data);
rsp_data.data = NULL;
}
rsp_data.len = scan_resp->len;
rsp_data.data = Malloc(rsp_data.len);
if (rsp_data.data != NULL) {
memcpy(rsp_data.data, scan_resp->data, scan_resp->len);
}
/**
* The logic to be implemented:
* a) Enable the broadcast (data: adv_data.data, data length: adv_data.len).
* b) Save the scan response data, and return the data when the scan response request is received (data: rsp_data.data, data length: rsp_data.len).
*/
return OPRT_OK;
}
Adapt to the following interface to send the data to the mobile app.
OPERATE_RET tuya_adapter_bt_send(BYTE_T *data, UINT8_T len)
{
/**
* Logic to be implemented: Send the data to the mobile app through Send Characteristic Notification of GATT Server.
*/
return OPRT_OK;
}
Send the received Bluetooth data to the SDK for parsing.
When the Bluetooth connection is established, send an event to the SDK:
VOID example_ble_connected(VOID)
{
tuya_ble_data_buf_t data = {0};
if (bt_msg_cb == NULL) {
return;
}
data.len = 0;
data.data = NULL;
bt_msg_cb(0, TY_BT_EVENT_CONNECTED, &data);
}
When the Bluetooth connection is disconnected, send an event to the SDK:
VOID example_ble_disconnected(VOID)
{
tuya_ble_data_buf_t data = {0};
if (bt_msg_cb == NULL) {
return;
}
data.len = 0;
data.data = NULL;
bt_msg_cb(0, TY_BT_EVENT_DISCONNECTED, &data);
bt_msg_cb(0, TY_BT_EVENT_ADV_READY, &data);
}
When the data is received over Bluetooth, send an event to the SDK:
/**
* Logic to be implemented: The application receives the Bluetooth data and passes the attribute value of the GATT server in the data to the SDK for processing.
*/
VOID example_ble_rx(BYTE_T *rx_data, UINT8_T rx_len)
{
tuya_ble_data_buf_t data = {0};
if (bt_msg_cb == NULL) {
return;
}
data.len = rx_len;
data.data = rx_data;
bt_msg_cb(0, TY_BT_EVENT_RX_DATA, &data);
}
#include <unistd.h>
#include "uni_log.h"
#include "base_os_adapter.h"
#include "tuya_iot_base_api.h"
#include "tuya_iot_com_api.h"
#include "tuya_iot_sdk_api.h"
#include "tuya_iot_sdk_defs.h"
#if defined(TY_BT_MOD) && (TY_BT_MOD == 1)
#include "tuya_os_adapt_bt.h"
#endif
#define PID "fljmamufiym5fktz" // Replaced with your own product ID
#define UUID "tuya461dbc63aeeb991f" // Replaced with your own UUID
#define AUTHKEY "c8X4PR4wx1gMFaQlaZu5dfgVvVRwB8Ug" // Replace with your own AuthKey
STATIC VOID __gw_reset_cb(GW_RESET_TYPE_E type)
{
PR_DEBUG("gw reset callback, type: %d", type);
if (GW_RESET_DATA_FACTORY != type) {
exit(0);
}
return;
}
STATIC VOID __gw_upgrade_cb(CONST FW_UG_S *fw)
{
PR_DEBUG("gw upgrade callback");
if (fw == NULL) {
PR_ERR("invalid param");
return;
}
PR_DEBUG(" tp: %d", fw->tp);
PR_DEBUG(" fw_url: %s", fw->fw_url);
PR_DEBUG(" sw_ver: %s", fw->sw_ver);
PR_DEBUG(" fw_hmac: %s", fw->fw_hmac);
PR_DEBUG(" file_size: %u", fw->file_size);
return;
}
STATIC VOID __gw_active_stat_cb(GW_STATUS_E status)
{
PR_DEBUG("gw active stat callback, status: %d", status);
return;
}
STATIC VOID __gw_reboot_cb(VOID)
{
PR_DEBUG("gw reboot callback");
exit(0);
return;
}
STATIC VOID __nw_stat_cb(IN CONST SDK_NW_STAT_T stat)
{
PR_DEBUG("network stat: %d", stat);
return;
}
STATIC VOID __wired_stat_cb(IN CONST SDK_WIRED_NW_STAT_T stat)
{
PR_DEBUG("wired stat: %d", stat);
return;
}
int main(int argc, char **argv)
{
OPERATE_RET rt = OPRT_OK;
GW_PROD_INFO_S prod_info = {0};
/* gw base callback */
TY_GW_INFRA_CBS_S gw_cbs = {
.gw_reset_cb = __gw_reset_cb,
.gw_upgrade_cb = __gw_upgrade_cb,
.gw_active_stat_cb = __gw_active_stat_cb,
.gw_reboot_cb = __gw_reboot_cb,
};
#if defined(TY_BT_MOD) && (TY_BT_MOD == 1)
tuya_os_adapt_reg_bt_intf();
#endif
/* initiate os-layer service*/
tuya_os_intf_init();
/* initiate iot-layer service */
TUYA_CALL_ERR_RETURN(tuya_iot_init("./"));
/* set the logging level to debug */
SET_PR_DEBUG_LEVEL(TY_LOG_LEVEL_DEBUG);
PR_DEBUG("SDK INFO: %s", tuya_iot_get_sdk_info());
/* set uuid and authkey */
prod_info.uuid = UUID;
prod_info.auth_key = AUTHKEY;
TUYA_CALL_ERR_RETURN(tuya_iot_set_gw_prod_info(&prod_info));
/* pre-initiate sdk service */
TUYA_CALL_ERR_RETURN(tuya_iot_sdk_pre_init(TRUE));
/* initiate application service, more service in here */
TUYA_CALL_ERR_RETURN(tuya_user_svc_init(&gw_cbs));
/* initiate sdk service */
#if defined(GW_SUPPORT_WIRED_WIFI) && (GW_SUPPORT_WIRED_WIFI==1)
TUYA_CALL_ERR_RETURN(tuya_iot_wired_wf_sdk_init(IOT_GW_NET_WIRED_WIFI, GWCM_OLD, WF_START_AP_ONLY, PID, USER_SW_VER, NULL, 0));
#elif defined(WIFI_GW) && (WIFI_GW==1)
TUYA_CALL_ERR_RETURN(tuya_iot_wf_sdk_init(GWCM_OLD, WF_START_AP_ONLY, PID, USER_SW_VER, NULL, 0));
#else
TUYA_CALL_ERR_RETURN(tuya_iot_sdk_init(PID, USER_SW_VER, NULL, 0));
#endif
/* register net stat notification callback */
TUYA_CALL_ERR_RETURN(tuya_iot_sdk_reg_netstat_cb(__nw_stat_cb, __wired_stat_cb, NULL));
/* start application service, more service in here */
TUYA_CALL_ERR_RETURN(tuya_user_svc_start(NULL));
while (1) {
sleep(10);
}
return 0;
}
#include "tuya_os_adapt_bt.h"
#include "mem_pool.h"
TY_BT_MSG_CB bt_msg_cb = NULL;
tuya_ble_data_buf_t adv_data = {0};
tuya_ble_data_buf_t rsp_data = {0};
OPERATE_RET tuya_adapter_bt_port_init(ty_bt_param_t *p)
{
/**
* The following features need to be implemented in the function:
* a) Initialize the Bluetooth protocol stack to ensure normal communications over Bluetooth.
* b) Save the function pointer variable, and pass the received Bluetooth data to the SDK through the function pointer.
*/
bt_msg_cb = p->cb;
return OPRT_OK;
}
OPERATE_RET tuya_adapter_bt_port_deinit(VOID)
{
return OPRT_OK;
}
OPERATE_RET tuya_adapter_bt_gap_disconnect(VOID)
{
return OPRT_OK;
}
OPERATE_RET tuya_adapter_bt_send(BYTE_T *data, UINT8_T len)
{
/**
* Logic to be implemented: Send the data to the mobile app through Send Characteristic Notification of GATT Server.
*/
return OPRT_OK;
}
OPERATE_RET tuya_adapter_bt_adv_reset(tuya_ble_data_buf_t *adv, tuya_ble_data_buf_t *scan_resp)
{
if ((adv == NULL) || (adv->len == 0) || (scan_resp == NULL) || (scan_resp->len == 0)) {
return OPRT_INVALID_PARM;
}
if (adv_data.data != NULL) {
Free(adv_data.data);
adv_data.data = NULL;
}
adv_data.len = adv->len;
adv_data.data = Malloc(adv_data.len);
if (adv_data.data != NULL) {
memcpy(adv_data.data, adv->data, adv->len);
}
if (rsp_data.data != NULL) {
Free(rsp_data.data);
rsp_data.data = NULL;
}
rsp_data.len = scan_resp->len;
rsp_data.data = Malloc(rsp_data.len);
if (rsp_data.data != NULL) {
memcpy(rsp_data.data, scan_resp->data, scan_resp->len);
}
/**
* The logic to be implemented:
* a) Enable the broadcast (data: adv_data.data, data length: adv_data.len).
* b) Save the scan response data, and return the data when the scan response request is received (data: rsp_data.data, data length: rsp_data.len).
*/
return OPRT_OK;
}
OPERATE_RET tuya_adapter_bt_adv_start(VOID)
{
return OPRT_OK;
}
OPERATE_RET tuya_adapter_bt_adv_stop(VOID)
{
return OPRT_OK;
}
OPERATE_RET tuya_adapter_bt_get_rssi(SCHAR_T *rssi)
{
return OPRT_OK;
}
OPERATE_RET tuya_adapter_bt_scan_assign(INOUT ty_bt_scan_info_t *info)
{
return OPRT_OK;
}
OPERATE_RET tuya_adapter_bt_scan_init(IN TY_BT_SCAN_ADV_CB scan_adv_cb)
{
return OPRT_OK;
}
OPERATE_RET tuya_adapter_bt_scan_start(VOID_T)
{
return OPRT_OK;
}
OPERATE_RET tuya_adapter_bt_scan_stop(VOID_T)
{
return OPRT_OK;
}
VOID example_ble_connected(VOID)
{
tuya_ble_data_buf_t data = {0};
if (bt_msg_cb == NULL) {
return;
}
data.len = 0;
data.data = NULL;
bt_msg_cb(0, TY_BT_EVENT_CONNECTED, &data);
}
VOID example_ble_disconnected(VOID)
{
tuya_ble_data_buf_t data = {0};
if (bt_msg_cb == NULL) {
return;
}
data.len = 0;
data.data = NULL;
bt_msg_cb(0, TY_BT_EVENT_DISCONNECTED, &data);
bt_msg_cb(0, TY_BT_EVENT_ADV_READY, &data);
}
/**
* Logic to be implemented: The application receives the Bluetooth data and passes the attribute value of the GATT server in the data to the SDK for processing.
*/
VOID example_ble_rx(BYTE_T *rx_data, UINT8_T rx_len)
{
tuya_ble_data_buf_t data = {0};
if (bt_msg_cb == NULL) {
return;
}
data.len = rx_len;
data.data = rx_data;
bt_msg_cb(0, TY_BT_EVENT_RX_DATA, &data);
}
/**
* Logic to be implemented: The application receives the Bluetooth data and passes the attribute value of the GATT server in the data to the SDK for processing.
*/
VOID example_ble_rx(BYTE_T *rx_data, UINT8_T rx_len)
{
tuya_ble_data_buf_t data = {0};
if (bt_msg_cb == NULL) {
return;
}
data.len = rx_len;
data.data = rx_data;
bt_msg_cb(0, TY_BT_EVENT_RX_DATA, &data);
}
Is this page helpful?
YesFeedbackIs this page helpful?
YesFeedback