본문으로 바로가기

[ESP-IDF][ble_hid_device_demo][6] spp 서비스 추가(TX)

category ESP32 2024. 2. 21. 13:08

: nRF Connect 앱을 통해 서비스 추가 및 TX 테스트 진행함.

ble_spp_server 프로젝트 참조 했습니다.

 

 

▶ esp_hidd_prf_api.c 수정사항

esp_err_t esp_hidd_register_callbacks(esp_hidd_event_cb_t callbacks)
{
   ~~ 중략 ~~

+	esp_ble_gatts_app_register(ESP_SPP_APP_ID);
    esp_ble_gatts_app_register(BATTRAY_APP_ID);
    
    ~~ 중략 ~~
}

 

 

hid_device_le_prf.c 수정사항

더보기
#define SPP_DATA_MAX_LEN           (512)
#define SPP_CMD_MAX_LEN            (20)
#define SPP_STATUS_MAX_LEN         (20)
#define SPP_DATA_BUFF_MAX_LEN      (2*1024)

///Attributes State Machine
enum{
    SPP_IDX_SVC,

    SPP_IDX_SPP_DATA_RECV_CHAR,
    SPP_IDX_SPP_DATA_RECV_VAL,

    SPP_IDX_SPP_DATA_NOTIFY_CHAR,
    SPP_IDX_SPP_DATA_NTY_VAL,
    SPP_IDX_SPP_DATA_NTF_CFG,

    SPP_IDX_SPP_COMMAND_CHAR,
    SPP_IDX_SPP_COMMAND_VAL,

    SPP_IDX_SPP_STATUS_CHAR,
    SPP_IDX_SPP_STATUS_VAL,
    SPP_IDX_SPP_STATUS_CFG,

    SPP_IDX_NB,
};

 

static uint16_t spp_handle_table[SPP_IDX_NB];

/// SPP Service
static const uint16_t spp_service_uuid = 0xABF0;

/// Characteristic UUID
#define ESP_GATT_UUID_SPP_DATA_RECEIVE      0xABF1
#define ESP_GATT_UUID_SPP_DATA_NOTIFY       0xABF2
#define ESP_GATT_UUID_SPP_COMMAND_RECEIVE   0xABF3
#define ESP_GATT_UUID_SPP_COMMAND_NOTIFY    0xABF4


// #define CHAR_DECLARATION_SIZE   (sizeof(uint8_t))
// static const uint16_t primary_service_uuid = ESP_GATT_UUID_PRI_SERVICE;
// static const uint16_t character_declaration_uuid = ESP_GATT_UUID_CHAR_DECLARE;
// static const uint16_t character_client_config_uuid = ESP_GATT_UUID_CHAR_CLIENT_CONFIG;

//static const uint8_t char_prop_read_notify = ESP_GATT_CHAR_PROP_BIT_READ|ESP_GATT_CHAR_PROP_BIT_NOTIFY;
static const uint8_t char_prop_read_write_nr = ESP_GATT_CHAR_PROP_BIT_WRITE_NR|ESP_GATT_CHAR_PROP_BIT_READ;

///SPP Service - data receive characteristic, read&write without response
static const uint16_t spp_data_receive_uuid = ESP_GATT_UUID_SPP_DATA_RECEIVE;
static const uint8_t  spp_data_receive_val[20] = {0x00};

///SPP Service - data notify characteristic, notify&read
static const uint16_t spp_data_notify_uuid = ESP_GATT_UUID_SPP_DATA_NOTIFY;
static const uint8_t  spp_data_notify_val[20] = {0x00};
static const uint8_t  spp_data_notify_ccc[2] = {0x00, 0x00};

///SPP Service - command characteristic, read&write without response
static const uint16_t spp_command_uuid = ESP_GATT_UUID_SPP_COMMAND_RECEIVE;
static const uint8_t  spp_command_val[10] = {0x00};

///SPP Service - status characteristic, notify&read
static const uint16_t spp_status_uuid = ESP_GATT_UUID_SPP_COMMAND_NOTIFY;
static const uint8_t  spp_status_val[10] = {0x00};
static const uint8_t  spp_status_ccc[2] = {0x00, 0x00};

 

///Full HRS Database Description - Used to add attributes into the database
static const esp_gatts_attr_db_t spp_gatt_db[SPP_IDX_NB] =
{
    //SPP -  Service Declaration
    [SPP_IDX_SVC]                      	=
    {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&primary_service_uuid, ESP_GATT_PERM_READ,
    sizeof(spp_service_uuid), sizeof(spp_service_uuid), (uint8_t *)&spp_service_uuid}},

    //SPP -  data receive characteristic Declaration
    [SPP_IDX_SPP_DATA_RECV_CHAR]            =
    {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ,
    CHAR_DECLARATION_SIZE,CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_read_write_nr}},

    //SPP -  data receive characteristic Value
    [SPP_IDX_SPP_DATA_RECV_VAL]             	=
    {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&spp_data_receive_uuid, ESP_GATT_PERM_READ|ESP_GATT_PERM_WRITE,
    SPP_DATA_MAX_LEN,sizeof(spp_data_receive_val), (uint8_t *)spp_data_receive_val}},

    //SPP -  data notify characteristic Declaration
    [SPP_IDX_SPP_DATA_NOTIFY_CHAR]  =
    {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ,
    CHAR_DECLARATION_SIZE,CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_read_notify}},

    //SPP -  data notify characteristic Value
    [SPP_IDX_SPP_DATA_NTY_VAL]   =
    {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&spp_data_notify_uuid, ESP_GATT_PERM_READ,
    SPP_DATA_MAX_LEN, sizeof(spp_data_notify_val), (uint8_t *)spp_data_notify_val}},

    //SPP -  data notify characteristic - Client Characteristic Configuration Descriptor
    [SPP_IDX_SPP_DATA_NTF_CFG]         =
    {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid, ESP_GATT_PERM_READ|ESP_GATT_PERM_WRITE,
    sizeof(uint16_t),sizeof(spp_data_notify_ccc), (uint8_t *)spp_data_notify_ccc}},

    //SPP -  command characteristic Declaration
    [SPP_IDX_SPP_COMMAND_CHAR]            =
    {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ,
    CHAR_DECLARATION_SIZE,CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_read_write_nr}},

    //SPP -  command characteristic Value
    [SPP_IDX_SPP_COMMAND_VAL]                 =
    {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&spp_command_uuid, ESP_GATT_PERM_READ|ESP_GATT_PERM_WRITE,
    SPP_CMD_MAX_LEN,sizeof(spp_command_val), (uint8_t *)spp_command_val}},

    //SPP -  status characteristic Declaration
    [SPP_IDX_SPP_STATUS_CHAR]            =
    {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ,
    CHAR_DECLARATION_SIZE,CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_read_notify}},

    //SPP -  status characteristic Value
    [SPP_IDX_SPP_STATUS_VAL]                 =
    {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&spp_status_uuid, ESP_GATT_PERM_READ,
    SPP_STATUS_MAX_LEN,sizeof(spp_status_val), (uint8_t *)spp_status_val}},

    //SPP -  status characteristic - Client Characteristic Configuration Descriptor
    [SPP_IDX_SPP_STATUS_CFG]         =
    {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid, ESP_GATT_PERM_READ|ESP_GATT_PERM_WRITE,
    sizeof(uint16_t),sizeof(spp_status_ccc), (uint8_t *)spp_status_ccc}},
};

 

void esp_hidd_prf_cb_hdl(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if,
									esp_ble_gatts_cb_param_t *param)
{
    switch(event) {
        case ESP_GATTS_REG_EVT: {
            ~~ 중략 ~~
            if(param->reg.app_id == HIDD_APP_ID) {
                hidd_le_env.gatt_if = gatts_if;
                if(hidd_le_env.hidd_cb != NULL) {
                    (hidd_le_env.hidd_cb)(ESP_HIDD_EVENT_REG_FINISH, &hidd_param);
                    hidd_le_create_service(hidd_le_env.gatt_if);
+					esp_ble_gatts_create_attr_tab(spp_gatt_db, gatts_if, SPP_IDX_NB, 0);   <----
                }
            }
            ~~ 중략 ~~
            break;
        case ESP_GATTS_WRITE_EVT: {
            ~~ 중략 ~~
            if(param->write.handle == spp_handle_table[SPP_IDX_SPP_DATA_RECV_VAL]){
				ESP_LOGI(HID_LE_PRF_TAG,"ESP_GATTS_WRITE_EVT > %d ",param->write.handle);
				esp_log_buffer_char(HID_LE_PRF_TAG,(char *)(param->write.value),param->write.len);
			}
            ~~ 중략 ~~
            break;
        case ESP_GATTS_CREAT_ATTR_TAB_EVT: 
		{
            ~~ 중략 ~~
            if (param->add_attr_tab.num_handle == HIDD_LE_IDX_NB &&
                param->add_attr_tab.status == ESP_GATT_OK) {
                memcpy(hidd_le_env.hidd_inst.att_tbl, param->add_attr_tab.handles,
                            HIDD_LE_IDX_NB*sizeof(uint16_t));
                ESP_LOGI(HID_LE_PRF_TAG, "ESP_GATTS_CREAT_ATTR_TAB_EVT - hid svc handle = %d",hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_SVC]);
                hid_add_id_tbl();
		        esp_ble_gatts_start_service(hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_SVC]);
+           }else if (param->add_attr_tab.num_handle == SPP_IDX_NB && param->add_attr_tab.status == ESP_GATT_OK) {
+				ESP_LOGI(HID_LE_PRF_TAG, "ESP_GATTS_CREAT_ATTR_TAB_EVT - spp handle = %d",param->add_attr_tab.handles[0]);
+     	        memcpy(spp_handle_table, param->add_attr_tab.handles, sizeof(spp_handle_table));
+    	        esp_ble_gatts_start_service(spp_handle_table[SPP_IDX_SVC]);
            } else {
	            ESP_LOGI(HID_LE_PRF_TAG, "ESP_GATTS_CREAT_ATTR_TAB_EVT - other handle = %d",param->add_attr_tab.handles[0]);
                esp_ble_gatts_start_service(param->add_attr_tab.handles[0]);
            }
            break;
         }

 

 

hidd_le_prf_int.h  수정사항

#define ESP_SPP_APP_ID       0x56

 

 

 

▶ nRF connect  사용해 service 항목 읽기

   : 장치 페어링이 되고 연결상태에서 테스트 함.

 

 

 

▶ nRF connect  사용해  UUID 0xABF1 에 1234 쓰기

 

→ 시리얼 로그

I (19942) HID_LE_PRF: ESP_GATTS_WRITE_EVT > 47
I (19942) HID_LE_PRF: 1234

 

<동작 설명>

 1>  esp_ble_gatts_app_register(ESP_SPP_APP_ID); 추가 

    >> esp_ble_gatts_app_register() 추가하면 ESP_GATTS_REG_EVT  이벤트가  들어옵니다. 
          2번항목의 코드를 적당한 곳에 넣어줍니다.

 2>  esp_ble_gatts_create_attr_tab(spp_gatt_db, gatts_if, SPP_IDX_NB, 0); 추가

    >> ESP_GATTS_CREAT_ATTR_TAB_EVT 이벤트가 들어오고 3번항목의 내용을 적당한 곳에 추가해 줍니다.

 3>  esp_ble_gatts_start_service(spp_handle_table[SPP_IDX_SVC]);  추가

 

 

 

RX 관련 사항은 추후 작성

그럼 수고하세요.

반응형