ESP32 の BLEデバイス化にチャレンジ!(1) [Arduino]
ESP32 をスマホからBLEデバイスにするために試行錯誤をしています。コードを解析すればうまくいくかなと思ったのですが、なかなかうまくいかない。
BLEデバイスの中でも一番簡単なTHERMOMETER デバイスなら簡単にいくだろうと思い、 スケッチ化してみることにしました。参考にしたサイトはこちら。
Development of ESP-WROOM-32
https://github.com/mitazet/esp/blob/master/thermometer/main/gatts_thermometer.c
改造した Arduino のスケッチ?(ほぼCのプログラムですが)がこちらです。デバッグコードが入っていて、少し見苦しいですが我慢ください。
LAPIS Computer から出しているスマホアプリの BLE Tools を起動してみると、ESP32_THERMOMETER が見えました!
しかし、値は取れず…残念。
シリアルモニターを確認すると、CONNECTまでは成功していますが、その後にREADのイベントが発生していません。
うーん、何が原因なのか。そもそもシーケンスが間違っているのか。。。もう少し追いかけてみたいところですが、最近は忙しくて時間がとれないんだよなぁ。
(;´д`)トホホ
BLEデバイスの中でも一番簡単なTHERMOMETER デバイスなら簡単にいくだろうと思い、 スケッチ化してみることにしました。参考にしたサイトはこちら。
Development of ESP-WROOM-32
https://github.com/mitazet/esp/blob/master/thermometer/main/gatts_thermometer.c
改造した Arduino のスケッチ?(ほぼCのプログラムですが)がこちらです。デバッグコードが入っていて、少し見苦しいですが我慢ください。
#pragma GCC diagnostic push #pragma GCC diagnostic warning "-fpermissive" #include#include #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/event_groups.h" #include "esp_system.h" #include "esp_log.h" #include "nvs_flash.h" #include "bt.h" #include "bta_api.h" #include "esp_gap_ble_api.h" #include "esp_gatts_api.h" #include "esp_bt_defs.h" #include "esp_bt_main.h" #include "esp_bt_main.h" #include "sdkconfig.h" #define GATTS_TAG "GATTS_THERMO" static void gatts_profile_thermo_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param); #define GATTS_SERVICE_UUID_THERMOMETER 0x00FF #define GATTS_CHAR_UUID_THERMOMETER 0xFF01 #define GATTS_DESCR_UUID_THERMOMETER 0x3333 #define GATTS_NUM_HANDLE_THERMOMETER 4 #define TEST_DEVICE_NAME "ESP_THERMOMETER" #define GATTS_DEMO_CHAR_VAL_LEN_MAX 0x40 #define PREPARE_BUF_MAX_SIZE 1024 #define PROFILE_NUM 1 #define PROFILE_THERMOMETER_ID 0 uint8_t char1_str[] = {0x11,0x22,0x33}; esp_attr_value_t gatts_demo_char1_val = { .attr_max_len = GATTS_DEMO_CHAR_VAL_LEN_MAX, .attr_len = sizeof(char1_str), .attr_value = char1_str, }; static uint8_t service_uuid128[32] = { /* LSB <--------------------------------------------------------------------------------> MSB */ //first uuid, 16bit, [12],[13] is the value 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0xAB, 0xCD, 0x00, 0x00, //second uuid, 32bit, [12], [13], [14], [15] is the value 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0xAB, 0xCD, 0xAB, 0xCD, }; static esp_ble_adv_data_t test_adv_data = { .set_scan_rsp = false, .include_name = true, .include_txpower = true, .min_interval = 0x20, .max_interval = 0x40, .appearance = 0x00, .manufacturer_len = 0, .p_manufacturer_data = NULL, .service_data_len = 0, .p_service_data = NULL, .service_uuid_len = 32, .p_service_uuid = service_uuid128, .flag = (ESP_BLE_ADV_FLAG_GEN_DISC | ESP_BLE_ADV_FLAG_BREDR_NOT_SPT), }; static esp_ble_adv_params_t test_adv_params; struct gatts_profile_inst { esp_gatts_cb_t gatts_cb; uint16_t gatts_if; uint16_t app_id; uint16_t conn_id; uint16_t service_handle; esp_gatt_srvc_id_t service_id; esp_bt_uuid_t char_uuid; esp_bt_uuid_t descr_uuid; uint16_t char_handle; esp_gatt_perm_t perm; esp_gatt_char_prop_t property; uint16_t descr_handle; }; static struct gatts_profile_inst test_profile; typedef struct { uint8_t *prepare_buf; int prepare_len; } prepare_type_env_t; static prepare_type_env_t a_prepare_write_env; void example_write_event_env(esp_gatt_if_t gatts_if, prepare_type_env_t *prepare_write_env, esp_ble_gatts_cb_param_t *param); void example_exec_write_event_env(prepare_type_env_t *prepare_write_env, esp_ble_gatts_cb_param_t *param); static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) { Serial.println("gap_event_handler"); switch (event) { case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT: Serial.println("ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT"); esp_ble_gap_start_advertising(&test_adv_params); break; case ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT: Serial.println("ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT"); esp_ble_gap_start_advertising(&test_adv_params); break; case ESP_GAP_BLE_SCAN_RSP_DATA_RAW_SET_COMPLETE_EVT: Serial.println("ESP_GAP_BLE_SCAN_RSP_DATA_RAW_SET_COMPLETE_EVT"); esp_ble_gap_start_advertising(&test_adv_params); break; case ESP_GAP_BLE_ADV_START_COMPLETE_EVT: Serial.println("ESP_GAP_BLE_ADV_START_COMPLETE_EVT"); if (param->adv_start_cmpl.status != ESP_BT_STATUS_SUCCESS) { Serial.println("Advertising start failed\n"); } break; case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT: Serial.println("ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT"); if (param->adv_stop_cmpl.status != ESP_BT_STATUS_SUCCESS) { Serial.println("Advertising stop failed\n"); } else { Serial.println("Stop adv successfully\n"); } break; case ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT: Serial.println("ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT"); break; default: break; } } void example_write_event_env(esp_gatt_if_t gatts_if, prepare_type_env_t *prepare_write_env, esp_ble_gatts_cb_param_t *param){ Serial.println("example_write_event_env"); esp_gatt_status_t status = ESP_GATT_OK; if (param->write.need_rsp){ if (param->write.is_prep){ if (prepare_write_env->prepare_buf == NULL) { prepare_write_env->prepare_buf = (uint8_t*)malloc(PREPARE_BUF_MAX_SIZE*sizeof(uint8_t)); prepare_write_env->prepare_len = 0; } else { if(param->write.offset > PREPARE_BUF_MAX_SIZE) { status = ESP_GATT_INVALID_OFFSET; } else if ((param->write.offset + param->write.len) > PREPARE_BUF_MAX_SIZE) { status = ESP_GATT_INVALID_ATTR_LEN; } } esp_gatt_rsp_t *gatt_rsp = (esp_gatt_rsp_t*)malloc(sizeof(esp_gatt_rsp_t)); gatt_rsp->attr_value.len = param->write.len; gatt_rsp->attr_value.handle = param->write.handle; gatt_rsp->attr_value.offset = param->write.offset; gatt_rsp->attr_value.auth_req = ESP_GATT_AUTH_REQ_NONE; memcpy(gatt_rsp->attr_value.value, param->write.value, param->write.len); esp_err_t response_err = esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, status, gatt_rsp); free(gatt_rsp); if (status != ESP_GATT_OK) { return; } memcpy(prepare_write_env->prepare_buf + param->write.offset, param->write.value, param->write.len); prepare_write_env->prepare_len += param->write.len; }else{ esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, status, NULL); } } } void example_exec_write_event_env(prepare_type_env_t *prepare_write_env, esp_ble_gatts_cb_param_t *param){ Serial.println("example_exec_write_event_env"); if (param->exec_write.exec_write_flag == ESP_GATT_PREP_WRITE_EXEC){ esp_log_buffer_hex(GATTS_TAG, prepare_write_env->prepare_buf, prepare_write_env->prepare_len); } if (prepare_write_env->prepare_buf) { free(prepare_write_env->prepare_buf); prepare_write_env->prepare_buf = NULL; } prepare_write_env->prepare_len = 0; } static void gatts_profile_thermo_event_handler(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: Serial.println("ESP_GATTS_REG_EVT"); test_profile.service_id.is_primary = true; test_profile.service_id.id.inst_id = 0x00; test_profile.service_id.id.uuid.len = ESP_UUID_LEN_16; test_profile.service_id.id.uuid.uuid.uuid16 = GATTS_SERVICE_UUID_THERMOMETER; esp_ble_gap_set_device_name(TEST_DEVICE_NAME); esp_ble_gap_config_adv_data(&test_adv_data); esp_ble_gatts_create_service(gatts_if, &test_profile.service_id, GATTS_NUM_HANDLE_THERMOMETER); break; case ESP_GATTS_READ_EVT: { Serial.println("ESP_GATTS_READ_EVT"); char temp1 = 0x1E; // dummy data char temp2 = 0x00; // dummy data esp_gatt_rsp_t rsp; memset(&rsp, 0, sizeof(esp_gatt_rsp_t)); rsp.attr_value.handle = param->read.handle; rsp.attr_value.len = 2; rsp.attr_value.value[0] = temp1; rsp.attr_value.value[1] = temp2; esp_ble_gatts_send_response(gatts_if, param->read.conn_id, param->read.trans_id, ESP_GATT_OK, &rsp); break; } case ESP_GATTS_WRITE_EVT: { Serial.println("ESP_GATTS_WRITE_EVT"); example_write_event_env(gatts_if, &a_prepare_write_env, param); break; } case ESP_GATTS_EXEC_WRITE_EVT: Serial.println("ESP_GATTS_EXEC_EVT"); esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, ESP_GATT_OK, NULL); example_exec_write_event_env(&a_prepare_write_env, param); break; case ESP_GATTS_MTU_EVT: Serial.println("ESP_GATTS_MTU_EVT"); break; case ESP_GATTS_CONF_EVT: Serial.println("ESP_GATTS_CONF_EVT"); break; case ESP_GATTS_UNREG_EVT: Serial.println("ESP_GATTS_UNREG_EVT"); break; case ESP_GATTS_CREATE_EVT: Serial.println("ESP_GATTS_CREATE_EVT"); test_profile.service_handle = param->create.service_handle; test_profile.char_uuid.len = ESP_UUID_LEN_16; test_profile.char_uuid.uuid.uuid16 = GATTS_CHAR_UUID_THERMOMETER; esp_ble_gatts_start_service(test_profile.service_handle); esp_ble_gatts_add_char(test_profile.service_handle, &test_profile.char_uuid, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE, ESP_GATT_CHAR_PROP_BIT_READ | ESP_GATT_CHAR_PROP_BIT_WRITE | ESP_GATT_CHAR_PROP_BIT_NOTIFY, &gatts_demo_char1_val, NULL); break; case ESP_GATTS_ADD_INCL_SRVC_EVT: Serial.println("ESP_GATTS_ADD_INCL_SRVC_EVT"); break; case ESP_GATTS_ADD_CHAR_EVT: { uint16_t length = 0; const uint8_t *prf_char; Serial.println("ESP_GATTS_ADD_CHAR_EVT"); test_profile.char_handle = param->add_char.attr_handle; test_profile.descr_uuid.len = ESP_UUID_LEN_16; test_profile.descr_uuid.uuid.uuid16 = ESP_GATT_UUID_CHAR_CLIENT_CONFIG; esp_ble_gatts_get_attr_value(param->add_char.attr_handle, &length, &prf_char); esp_ble_gatts_add_char_descr(test_profile.service_handle, &test_profile.descr_uuid, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE, NULL, NULL); break; } case ESP_GATTS_ADD_CHAR_DESCR_EVT: Serial.println("ESP_GATTS_ADD_CHAR_DESCR_EVT"); break; case ESP_GATTS_DELETE_EVT: Serial.println("ESP_GATTS_DELETE_EVT"); break; case ESP_GATTS_START_EVT: Serial.println("ESP_GATTS_START_EVT"); break; case ESP_GATTS_STOP_EVT: Serial.println("ESP_GATTS_STOP_EVT"); break; case ESP_GATTS_CONNECT_EVT: { Serial.println("ESP_GATTS_CONNECT_EVT"); esp_ble_conn_update_params_t conn_params = {0}; memcpy(conn_params.bda, param->connect.remote_bda, sizeof(esp_bd_addr_t)); /* For the IOS system, please reference the apple official documents about the ble connection parameters restrictions. */ conn_params.latency = 0; conn_params.max_int = 0x50; // max_int = 0x50*1.25ms = 100ms conn_params.min_int = 0x30; // min_int = 0x30*1.25ms = 60ms conn_params.timeout = 400; // timeout = 400*10ms = 4000ms test_profile.conn_id = param->connect.conn_id; //start sent the update connection parameters to the peer device. esp_ble_gap_update_conn_params(&conn_params); break; } case ESP_GATTS_DISCONNECT_EVT: Serial.println("ESP_GATTS_DISCONNECT_EVT"); esp_ble_gap_start_advertising(&test_adv_params); break; case ESP_GATTS_OPEN_EVT: Serial.println("ESP_GATTS_OPEN_EVT"); break; case ESP_GATTS_CANCEL_OPEN_EVT: Serial.println("ESP_GATTS_CANCEL_OPEN_EVT"); break; case ESP_GATTS_CLOSE_EVT: Serial.println("ESP_GATTS_CLOSE_EVT"); break; case ESP_GATTS_LISTEN_EVT: Serial.println("ESP_GATTS_LISTEN_EVT"); break; case ESP_GATTS_CONGEST_EVT: Serial.println("ESP_GATTS_CONGEST_EVT"); break; default: break; } } static void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param) { Serial.println("gatts_event_handler"); /* If event is register event, store the gatts_if for each profile */ if (event == ESP_GATTS_REG_EVT) { if (param->reg.status == ESP_GATT_OK) { test_profile.gatts_if = gatts_if; } else { return; } } if (gatts_if == ESP_GATT_IF_NONE || gatts_if == test_profile.gatts_if) { if (test_profile.gatts_cb) { test_profile.gatts_cb(event, gatts_if, param); } } } void setup() { Serial.begin(115200); /* initialize advertising info */ test_adv_params.adv_int_min = 0x20; test_adv_params.adv_int_max = 0x40; test_adv_params.adv_type = ADV_TYPE_IND; test_adv_params.own_addr_type = BLE_ADDR_TYPE_PUBLIC; test_adv_params.channel_map = ADV_CHNL_ALL; test_adv_params.adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY; /* initialize profile and characteristic */ test_profile.gatts_cb = gatts_profile_thermo_event_handler; test_profile.gatts_if = ESP_GATT_IF_NONE; esp_err_t ret; btStart(); ret = esp_bluedroid_init(); if (ret) { Serial.println("Init bluetooth failed"); return; } ret = esp_bluedroid_enable(); if (ret) { Serial.println("Enable bluetooth failed"); return; } esp_ble_gatts_register_callback(gatts_event_handler); esp_ble_gap_register_callback(gap_event_handler); esp_ble_gatts_app_register(PROFILE_THERMOMETER_ID); Serial.println("Bluetooth setup success!"); } void loop() { }
LAPIS Computer から出しているスマホアプリの BLE Tools を起動してみると、ESP32_THERMOMETER が見えました!
しかし、値は取れず…残念。
シリアルモニターを確認すると、CONNECTまでは成功していますが、その後にREADのイベントが発生していません。
Bluetooth setup success! gatts_event_handler ESP_GATTS_REG_EVT gap_event_handler ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT gatts_event_handler ESP_GATTS_CREATE_EVT gap_event_handler ESP_GAP_BLE_ADV_START_COMPLETE_EVT gatts_event_handler ESP_GATTS_START_EVT gatts_event_handler ESP_GATTS_ADD_CHAR_EVT gatts_event_handler ESP_GATTS_ADD_CHAR_DESCR_EVT gatts_event_handler ESP_GATTS_CONNECT_EVT gap_event_handler ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT gatts_event_handler
うーん、何が原因なのか。そもそもシーケンスが間違っているのか。。。もう少し追いかけてみたいところですが、最近は忙しくて時間がとれないんだよなぁ。
(;´д`)トホホ
waves ESP32-DevKitC ESP-WROOM-32 ESP32 DevKitC V2 WiFi BLE 技適取得済 国内発送
- 出版社/メーカー: waves(ウェイブス)
- メディア: エレクトロニクス
SparkFun ESP32 Thing Development Workshop (English Edition)
- 出版社/メーカー: PE Press
- 発売日: 2017/04/09
- メディア: Kindle版
MicroPython for ESP32 Development Workshop (English Edition)
- 出版社/メーカー:
- 発売日: 2017/08/19
- メディア: Kindle版
コメント 0