This is a sample using ESP32 AT command for BLE.

Information

Japanese version is available in lower part of this page.
このページの後半に日本語版が用意されています.


What is this ?

This is a sample using ESP32 AT command for BLE.
You can test communication with your smartphone using the following GATT profile. In the sample, the GR board is the server and the smartphone is the client. In GR-LYCHEE, pressing the UB 0 button writes the value to C 300, and pressing the UB 1 button performs Notification to C 305.

UUIDAccess PropetySize(Byte)Characteristic Index
A002Read2-
C300Read11
C301Read5122
C302Write13
C303Write Without Response34
C304Write25
C305Notify56
C306Indicate57



概要

ESP32のBLE用ATコマンドを使用したサンプルです。
以下のGATTプロファイルを利用して、スマートフォンとの通信をテストできます。サンプルではGRボードがサーバとなり、スマートフォンがクライアントです。GR-LYCHEEでは、UB0ボタンを押すとC300への値書込み、UB1ボタンを押すとC305へのNotificationが行われます。

UUIDAccess PropetySize(Byte)Characteristic Index
A002Read2-
C300Read11
C301Read5122
C302Write13
C303Write Without Response34
C304Write25
C305Notify56
C306Indicate57
Committer:
dkato
Date:
Wed Nov 29 03:11:12 2017 +0000
Revision:
0:81023cbaf4d2
first commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dkato 0:81023cbaf4d2 1 #include "mbed.h"
dkato 0:81023cbaf4d2 2 #include "ESP32.h"
dkato 0:81023cbaf4d2 3
dkato 0:81023cbaf4d2 4 #define BLE_NOTIFICATION_CHAR 6
dkato 0:81023cbaf4d2 5 #define BLE_INDICATION_CHAR 7
dkato 0:81023cbaf4d2 6
dkato 0:81023cbaf4d2 7 BufferedSerial esp32(P7_1, P0_1, 1024);
dkato 0:81023cbaf4d2 8 ATParser_os esp_parser(esp32);
dkato 0:81023cbaf4d2 9 Serial pc(USBTX, USBRX); // tx, rx
dkato 0:81023cbaf4d2 10 DigitalOut esp_en(P5_3);
dkato 0:81023cbaf4d2 11 DigitalOut esp_io0(P3_14);
dkato 0:81023cbaf4d2 12 DigitalOut led_green(LED1);
dkato 0:81023cbaf4d2 13 DigitalOut led_yellow(LED2);
dkato 0:81023cbaf4d2 14 DigitalOut led_orange(LED3);
dkato 0:81023cbaf4d2 15 DigitalOut led_red(LED4);
dkato 0:81023cbaf4d2 16 InterruptIn button0(USER_BUTTON0);
dkato 0:81023cbaf4d2 17 InterruptIn button1(USER_BUTTON1);
dkato 0:81023cbaf4d2 18 Semaphore event_sem(0);
dkato 0:81023cbaf4d2 19
dkato 0:81023cbaf4d2 20 const char ble_name[] = "GR-LYCHEE";
dkato 0:81023cbaf4d2 21 bool ble_advertizing;
dkato 0:81023cbaf4d2 22 bool ble_connected;
dkato 0:81023cbaf4d2 23 uint8_t ble_conn_index;
dkato 0:81023cbaf4d2 24 uint8_t ble_srv_index;
dkato 0:81023cbaf4d2 25
dkato 0:81023cbaf4d2 26 bool button0_flag = false;
dkato 0:81023cbaf4d2 27 bool button1_flag = false;
dkato 0:81023cbaf4d2 28 bool ble_notification_on = false;
dkato 0:81023cbaf4d2 29 bool ble_indication_on = false;
dkato 0:81023cbaf4d2 30
dkato 0:81023cbaf4d2 31 void esp32_event() {
dkato 0:81023cbaf4d2 32 event_sem.release();
dkato 0:81023cbaf4d2 33 }
dkato 0:81023cbaf4d2 34
dkato 0:81023cbaf4d2 35 void ble_client_read() {
dkato 0:81023cbaf4d2 36 uint8_t mac[6] = {0};
dkato 0:81023cbaf4d2 37
dkato 0:81023cbaf4d2 38 led_yellow = 1;
dkato 0:81023cbaf4d2 39 esp_parser.recv("%hhd,\"%hhx:%hhx:%hhx:%hhx:%hhx:%hhx\"",
dkato 0:81023cbaf4d2 40 &ble_conn_index, &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]);
dkato 0:81023cbaf4d2 41 printf("conn_index=%d, mac[%x:%x:%x:%x:%x:%x]\r\n",
dkato 0:81023cbaf4d2 42 ble_conn_index, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
dkato 0:81023cbaf4d2 43 led_yellow = 0;
dkato 0:81023cbaf4d2 44 }
dkato 0:81023cbaf4d2 45
dkato 0:81023cbaf4d2 46 void ble_client_write() {
dkato 0:81023cbaf4d2 47 uint8_t char_index, desc_index = 0;
dkato 0:81023cbaf4d2 48 uint16_t len;
dkato 0:81023cbaf4d2 49
dkato 0:81023cbaf4d2 50 led_orange = 1;
dkato 0:81023cbaf4d2 51 esp_parser.recv("%hhd,%hhd,%hhd,", &ble_conn_index, &ble_srv_index, &char_index);
dkato 0:81023cbaf4d2 52 printf("conn=%d srv=%d char=%d\r\n", ble_conn_index, ble_srv_index, char_index);
dkato 0:81023cbaf4d2 53
dkato 0:81023cbaf4d2 54 char c = esp_parser.getc();
dkato 0:81023cbaf4d2 55 if (c != ',') {
dkato 0:81023cbaf4d2 56 desc_index = c;
dkato 0:81023cbaf4d2 57 esp_parser.getc(); // to read ',' after desc_index.
dkato 0:81023cbaf4d2 58 printf("desc=%d\r\n", desc_index);
dkato 0:81023cbaf4d2 59 }
dkato 0:81023cbaf4d2 60
dkato 0:81023cbaf4d2 61 esp_parser.recv("%hhd,", &len);
dkato 0:81023cbaf4d2 62 printf("length=%d\r\n", len);
dkato 0:81023cbaf4d2 63
dkato 0:81023cbaf4d2 64 uint8_t *data = (uint8_t *)malloc(len * sizeof(uint8_t));
dkato 0:81023cbaf4d2 65 for (int i = 0; i < len; i++) {
dkato 0:81023cbaf4d2 66 data[i] = esp_parser.getc();
dkato 0:81023cbaf4d2 67 printf("%x\r\n", data[i]);
dkato 0:81023cbaf4d2 68 }
dkato 0:81023cbaf4d2 69
dkato 0:81023cbaf4d2 70 if ((desc_index == 49) && (char_index == BLE_NOTIFICATION_CHAR)) {
dkato 0:81023cbaf4d2 71 if (data[0] == 1) {
dkato 0:81023cbaf4d2 72 printf("Notification On\r\n");
dkato 0:81023cbaf4d2 73 ble_notification_on = true;
dkato 0:81023cbaf4d2 74 } else {
dkato 0:81023cbaf4d2 75 printf("Notification Off\r\n");
dkato 0:81023cbaf4d2 76 ble_notification_on = false;
dkato 0:81023cbaf4d2 77 }
dkato 0:81023cbaf4d2 78 } else if ((desc_index == 49) && (char_index == BLE_INDICATION_CHAR)) {
dkato 0:81023cbaf4d2 79 if (data[0] == 2) {
dkato 0:81023cbaf4d2 80 printf("Indication On\r\n");
dkato 0:81023cbaf4d2 81 ble_indication_on = true;
dkato 0:81023cbaf4d2 82 } else {
dkato 0:81023cbaf4d2 83 printf("Indication Off\r\n");
dkato 0:81023cbaf4d2 84 ble_indication_on = false;
dkato 0:81023cbaf4d2 85 }
dkato 0:81023cbaf4d2 86 }
dkato 0:81023cbaf4d2 87 led_orange = 0;
dkato 0:81023cbaf4d2 88 }
dkato 0:81023cbaf4d2 89
dkato 0:81023cbaf4d2 90 void ble_client_disconn() {
dkato 0:81023cbaf4d2 91 led_green = 0;
dkato 0:81023cbaf4d2 92 printf("disconnected client\r\n");
dkato 0:81023cbaf4d2 93 ble_connected = false;
dkato 0:81023cbaf4d2 94 }
dkato 0:81023cbaf4d2 95
dkato 0:81023cbaf4d2 96 void ble_client_conn() {
dkato 0:81023cbaf4d2 97 uint8_t mac[6] = {0};
dkato 0:81023cbaf4d2 98 esp_parser.recv("%hhd,\"%hhx:%hhx:%hhx:%hhx:%hhx:%hhx\"",
dkato 0:81023cbaf4d2 99 &ble_conn_index, &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]);
dkato 0:81023cbaf4d2 100 printf("connected client conn_index is %d, mac[%x:%x:%x:%x:%x:%x]\r\n",
dkato 0:81023cbaf4d2 101 ble_conn_index, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
dkato 0:81023cbaf4d2 102
dkato 0:81023cbaf4d2 103 led_green = 1;
dkato 0:81023cbaf4d2 104 ble_advertizing = false;
dkato 0:81023cbaf4d2 105 ble_connected = true;
dkato 0:81023cbaf4d2 106 }
dkato 0:81023cbaf4d2 107
dkato 0:81023cbaf4d2 108 void ub0_interrupt() {
dkato 0:81023cbaf4d2 109 if (button0_flag == false) {
dkato 0:81023cbaf4d2 110 button0_flag = true;
dkato 0:81023cbaf4d2 111 event_sem.release();
dkato 0:81023cbaf4d2 112 }
dkato 0:81023cbaf4d2 113 }
dkato 0:81023cbaf4d2 114
dkato 0:81023cbaf4d2 115 void ub1_interrupt() {
dkato 0:81023cbaf4d2 116 if (button1_flag == false) {
dkato 0:81023cbaf4d2 117 button1_flag = true;
dkato 0:81023cbaf4d2 118 event_sem.release();
dkato 0:81023cbaf4d2 119 }
dkato 0:81023cbaf4d2 120 }
dkato 0:81023cbaf4d2 121
dkato 0:81023cbaf4d2 122 int main() {
dkato 0:81023cbaf4d2 123
dkato 0:81023cbaf4d2 124 printf("Bluetooth sample started\r\n");
dkato 0:81023cbaf4d2 125 led_green = 0;
dkato 0:81023cbaf4d2 126 led_yellow = 0;
dkato 0:81023cbaf4d2 127 led_orange = 0;
dkato 0:81023cbaf4d2 128 led_red = 0;
dkato 0:81023cbaf4d2 129 ble_advertizing = false;
dkato 0:81023cbaf4d2 130 ble_connected = false;
dkato 0:81023cbaf4d2 131 button0.fall(ub0_interrupt);
dkato 0:81023cbaf4d2 132 button1.fall(ub1_interrupt);
dkato 0:81023cbaf4d2 133
dkato 0:81023cbaf4d2 134 // Initializing esp32 access
dkato 0:81023cbaf4d2 135 esp32.baud(115200);
dkato 0:81023cbaf4d2 136 esp32.attach(Callback<void()>(esp32_event));
dkato 0:81023cbaf4d2 137 esp_io0 = 1;
dkato 0:81023cbaf4d2 138 esp_en = 0;
dkato 0:81023cbaf4d2 139 Thread::wait(10);
dkato 0:81023cbaf4d2 140 esp_en = 1;
dkato 0:81023cbaf4d2 141 esp_parser.setTimeout(1500);
dkato 0:81023cbaf4d2 142 if (esp_parser.recv("ready")) {
dkato 0:81023cbaf4d2 143 printf("ESP32 ready\r\n");
dkato 0:81023cbaf4d2 144 } else {
dkato 0:81023cbaf4d2 145 printf("ESP32 error\r\n");
dkato 0:81023cbaf4d2 146 led_red = 1;
dkato 0:81023cbaf4d2 147 while (1);
dkato 0:81023cbaf4d2 148 }
dkato 0:81023cbaf4d2 149
dkato 0:81023cbaf4d2 150 // Initializing esp32 as a server with GATT service
dkato 0:81023cbaf4d2 151 esp_parser.setTimeout(5000);
dkato 0:81023cbaf4d2 152 if (esp_parser.send("AT+BLEINIT=2") && esp_parser.recv("OK")
dkato 0:81023cbaf4d2 153 && esp_parser.send("AT+BLENAME=\"%s\"", ble_name) && esp_parser.recv("OK")
dkato 0:81023cbaf4d2 154 && esp_parser.send("AT+BLEGATTSSRVCRE") && esp_parser.recv("OK")
dkato 0:81023cbaf4d2 155 && esp_parser.send("AT+BLEGATTSSRVSTART") && esp_parser.recv("OK")) {
dkato 0:81023cbaf4d2 156 printf("GATT initialized\r\n");
dkato 0:81023cbaf4d2 157 } else {
dkato 0:81023cbaf4d2 158 printf("fail to initialize\r\n");
dkato 0:81023cbaf4d2 159 led_red = 1;
dkato 0:81023cbaf4d2 160 while (1);
dkato 0:81023cbaf4d2 161 }
dkato 0:81023cbaf4d2 162
dkato 0:81023cbaf4d2 163 uint8_t start, type;
dkato 0:81023cbaf4d2 164 uint16_t uuid;
dkato 0:81023cbaf4d2 165 esp_parser.send("AT+BLEGATTSSRV?");
dkato 0:81023cbaf4d2 166 if (esp_parser.recv("+BLEGATTSSRV:%hhd,%hhd,%hhx,%hhd\r\nOK", &ble_srv_index, &start, &uuid, &type)) {
dkato 0:81023cbaf4d2 167 printf("srv_index is %d\r\n", ble_srv_index);
dkato 0:81023cbaf4d2 168 } else {
dkato 0:81023cbaf4d2 169 printf("fail to get service\r\n");
dkato 0:81023cbaf4d2 170 led_red = 1;
dkato 0:81023cbaf4d2 171 }
dkato 0:81023cbaf4d2 172
dkato 0:81023cbaf4d2 173 esp_parser.oob("+READ:", ble_client_read);
dkato 0:81023cbaf4d2 174 esp_parser.oob("+WRITE:", ble_client_write);
dkato 0:81023cbaf4d2 175 esp_parser.oob("+BLEDISCONN:", ble_client_disconn);
dkato 0:81023cbaf4d2 176 esp_parser.oob("+BLECONN:", ble_client_conn);
dkato 0:81023cbaf4d2 177
dkato 0:81023cbaf4d2 178 while (1) {
dkato 0:81023cbaf4d2 179 esp_parser.setTimeout(5000);
dkato 0:81023cbaf4d2 180 if (esp_parser.send("AT+BLEADVSTART") && esp_parser.recv("OK")) {
dkato 0:81023cbaf4d2 181 printf("Advertising started. Please connect to any client\r\n");
dkato 0:81023cbaf4d2 182 ble_advertizing = true;
dkato 0:81023cbaf4d2 183 } else {
dkato 0:81023cbaf4d2 184 printf("fail to start advertising\r\n");
dkato 0:81023cbaf4d2 185 led_red = 1;
dkato 0:81023cbaf4d2 186 while (1);
dkato 0:81023cbaf4d2 187 }
dkato 0:81023cbaf4d2 188
dkato 0:81023cbaf4d2 189 while (ble_connected || ble_advertizing) {
dkato 0:81023cbaf4d2 190 event_sem.wait();
dkato 0:81023cbaf4d2 191 esp_parser.setTimeout(5);
dkato 0:81023cbaf4d2 192 esp_parser.recv(" "); //dummy read for parser callback
dkato 0:81023cbaf4d2 193
dkato 0:81023cbaf4d2 194 // Set attribute of C300
dkato 0:81023cbaf4d2 195 if (button0_flag) {
dkato 0:81023cbaf4d2 196 static uint8_t data = 1; // write data
dkato 0:81023cbaf4d2 197 esp_parser.setTimeout(5000);
dkato 0:81023cbaf4d2 198 // AT+BLEGATTSSETATTR=<srv_index>,<char_index>[,<desc_index>],<length>
dkato 0:81023cbaf4d2 199 if (esp_parser.send("AT+BLEGATTSSETATTR=%d,1,,1", ble_srv_index) && esp_parser.recv(">")) {
dkato 0:81023cbaf4d2 200 if (esp_parser.putc(data) && esp_parser.recv("OK")) {
dkato 0:81023cbaf4d2 201 printf("success to send\r\n");
dkato 0:81023cbaf4d2 202 } else {
dkato 0:81023cbaf4d2 203 printf("fail to send\r\n");
dkato 0:81023cbaf4d2 204 }
dkato 0:81023cbaf4d2 205 } else {
dkato 0:81023cbaf4d2 206 printf("fail to command AT\r\n");
dkato 0:81023cbaf4d2 207 }
dkato 0:81023cbaf4d2 208 esp_parser.flush();
dkato 0:81023cbaf4d2 209 button0_flag = false;
dkato 0:81023cbaf4d2 210 data++;
dkato 0:81023cbaf4d2 211 }
dkato 0:81023cbaf4d2 212
dkato 0:81023cbaf4d2 213 // Set notification of C305
dkato 0:81023cbaf4d2 214 if (button1_flag && ble_notification_on) {
dkato 0:81023cbaf4d2 215 static uint8_t data = 0xff; // write data
dkato 0:81023cbaf4d2 216 esp_parser.setTimeout(5000);
dkato 0:81023cbaf4d2 217 // AT+BLEGATTSNTFY=<conn_index>,<srv_index>,<char_index>,<length>
dkato 0:81023cbaf4d2 218 if (esp_parser.send("AT+BLEGATTSNTFY=%d,%d,%d,1", ble_conn_index, ble_srv_index, BLE_NOTIFICATION_CHAR)
dkato 0:81023cbaf4d2 219 && esp_parser.recv(">")) {
dkato 0:81023cbaf4d2 220 if (esp_parser.putc(data) && esp_parser.recv("OK")) {
dkato 0:81023cbaf4d2 221 printf("success to notify\r\n");
dkato 0:81023cbaf4d2 222 } else {
dkato 0:81023cbaf4d2 223 printf("fail to notify\r\n");
dkato 0:81023cbaf4d2 224 }
dkato 0:81023cbaf4d2 225 } else {
dkato 0:81023cbaf4d2 226 printf("fail to command AT\r\n");
dkato 0:81023cbaf4d2 227 }
dkato 0:81023cbaf4d2 228 esp_parser.flush();
dkato 0:81023cbaf4d2 229 button1_flag = false;
dkato 0:81023cbaf4d2 230 data--;
dkato 0:81023cbaf4d2 231 }
dkato 0:81023cbaf4d2 232 }
dkato 0:81023cbaf4d2 233 }
dkato 0:81023cbaf4d2 234 }