Add BluetoothSerial library (#1144)
* Add BluetoothSerial library A simple UART to Classical Bluetooth bridge for ESP32 * Create README.md * Fix typos * Replace deprecated header and small fixes * Add coexistence with BLE * Add missing semicolon
This commit is contained in:
		
							parent
							
								
									835268c326
								
							
						
					
					
						commit
						b4b9a79eea
					
				
							
								
								
									
										19
									
								
								libraries/BluetoothSerial/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								libraries/BluetoothSerial/README.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | ||||
| ### Bluetooth Serial Library | ||||
| 
 | ||||
| A simple Serial compatible library using ESP32 classical bluetooth (SPP) | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| #### How to use it? | ||||
| 
 | ||||
| - Download one bluetooth terminal app in your smartphone<br> | ||||
| For Android: https://play.google.com/store/apps/details?id=de.kai_morich.serial_bluetooth_terminal <br> | ||||
| For iOS: https://itunes.apple.com/us/app/hm10-bluetooth-serial-lite/id1030454675 | ||||
| 
 | ||||
| - Flash an example sketch to your ESP32 | ||||
| 
 | ||||
| - Scan and pair the device in your smartphone | ||||
| 
 | ||||
| - Open the bluetooth terminal app | ||||
| 
 | ||||
| - Enjoy | ||||
| @ -0,0 +1,29 @@ | ||||
| //This example code is in the Public Domain (or CC0 licensed, at your option.)
 | ||||
| //By Evandro Copercini - 2018
 | ||||
| //
 | ||||
| //This example creates a bridge between Serial and Classical Bluetooth (SPP)
 | ||||
| //and also demonstrate that SerialBT have the same functionalities of a normal Serial
 | ||||
| 
 | ||||
| #include "BluetoothSerial.h" | ||||
| 
 | ||||
| #if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED) | ||||
| #error Bluetooth is not enabled! Please run `make menuconfig` to and enable it | ||||
| #endif | ||||
| 
 | ||||
| BluetoothSerial SerialBT; | ||||
| 
 | ||||
| void setup() { | ||||
|   Serial.begin(115200); | ||||
|   SerialBT.begin("ESP32test"); //Bluetooth device name
 | ||||
|   Serial.println("The device started, now you can pair it with bluetooth!"); | ||||
| } | ||||
| 
 | ||||
| void loop() { | ||||
|   if (Serial.available()) { | ||||
|     SerialBT.write(Serial.read()); | ||||
|   } | ||||
|   if (SerialBT.available()) { | ||||
|     Serial.write(SerialBT.read()); | ||||
|   } | ||||
|   delay(20); | ||||
| } | ||||
							
								
								
									
										26
									
								
								libraries/BluetoothSerial/keywords.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								libraries/BluetoothSerial/keywords.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,26 @@ | ||||
| ####################################### | ||||
| # Syntax Coloring Map For BluetoothSerial | ||||
| ####################################### | ||||
| 
 | ||||
| ####################################### | ||||
| # Library (KEYWORD3) | ||||
| ####################################### | ||||
| 
 | ||||
| BluetoothSerial	KEYWORD3 | ||||
| 
 | ||||
| ####################################### | ||||
| # Datatypes (KEYWORD1) | ||||
| ####################################### | ||||
| 
 | ||||
| BluetoothSerial	KEYWORD1 | ||||
| 
 | ||||
| ####################################### | ||||
| # Methods and Functions (KEYWORD2) | ||||
| ####################################### | ||||
| 
 | ||||
| SerialBT	KEYWORD2 | ||||
| 
 | ||||
| 
 | ||||
| ####################################### | ||||
| # Constants (LITERAL1) | ||||
| ####################################### | ||||
							
								
								
									
										9
									
								
								libraries/BluetoothSerial/library.properties
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								libraries/BluetoothSerial/library.properties
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | ||||
| name=BluetoothSerial | ||||
| version=1.0 | ||||
| author=Evandro Copercini | ||||
| maintainer=Evandro Copercini | ||||
| sentence=Simple UART to Classical Bluetooth bridge for ESP32 | ||||
| paragraph= | ||||
| category=Communication | ||||
| url= | ||||
| architectures=esp32 | ||||
							
								
								
									
										239
									
								
								libraries/BluetoothSerial/src/BluetoothSerial.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										239
									
								
								libraries/BluetoothSerial/src/BluetoothSerial.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,239 @@ | ||||
| // Copyright 2018 Evandro Luis Copercini
 | ||||
| //
 | ||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||
| // you may not use this file except in compliance with the License.
 | ||||
| // You may obtain a copy of the License at
 | ||||
| //
 | ||||
| //     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
| //
 | ||||
| // Unless required by applicable law or agreed to in writing, software
 | ||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| #include "sdkconfig.h" | ||||
| 
 | ||||
| #if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BLUEDROID_ENABLED) | ||||
| 
 | ||||
| #ifdef ARDUINO_ARCH_ESP32 | ||||
| #include "esp32-hal-log.h" | ||||
| #endif | ||||
| 
 | ||||
| #include "BluetoothSerial.h" | ||||
| 
 | ||||
| #include "esp_bt.h" | ||||
| #include "esp_bt_main.h" | ||||
| #include "esp_gap_bt_api.h" | ||||
| #include "esp_bt_device.h" | ||||
| #include "esp_spp_api.h" | ||||
| 
 | ||||
| #define SPP_SERVER_NAME "ESP32_SPP_SERVER" | ||||
| 
 | ||||
| #define QUEUE_SIZE 256 | ||||
| uint32_t client; | ||||
| xQueueHandle SerialQueueBT; | ||||
| 
 | ||||
| static const esp_spp_mode_t esp_spp_mode = ESP_SPP_MODE_CB; | ||||
| static const esp_spp_sec_t sec_mask = ESP_SPP_SEC_NONE; | ||||
| static const esp_spp_role_t role_slave = ESP_SPP_ROLE_SLAVE; | ||||
| 
 | ||||
| static void esp_spp_cb(esp_spp_cb_event_t event, esp_spp_cb_param_t *param) | ||||
| { | ||||
|     switch (event) | ||||
|     { | ||||
|     case ESP_SPP_INIT_EVT: | ||||
|         ESP_LOGI(SPP_TAG, "ESP_SPP_INIT_EVT"); | ||||
|         esp_bt_gap_set_scan_mode(ESP_BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE); | ||||
|         esp_spp_start_srv(sec_mask, role_slave, 0, SPP_SERVER_NAME); | ||||
|         break; | ||||
|     case ESP_SPP_DISCOVERY_COMP_EVT: | ||||
|         ESP_LOGI(SPP_TAG, "ESP_SPP_DISCOVERY_COMP_EVT"); | ||||
|         break; | ||||
|     case ESP_SPP_OPEN_EVT: | ||||
|         ESP_LOGI(SPP_TAG, "ESP_SPP_OPEN_EVT"); | ||||
|         break; | ||||
|     case ESP_SPP_CLOSE_EVT: | ||||
|         client = 0; | ||||
|         ESP_LOGI(SPP_TAG, "ESP_SPP_CLOSE_EVT"); | ||||
|         break; | ||||
|     case ESP_SPP_START_EVT: | ||||
|         ESP_LOGI(SPP_TAG, "ESP_SPP_START_EVT"); | ||||
|         break; | ||||
|     case ESP_SPP_CL_INIT_EVT: | ||||
|         ESP_LOGI(SPP_TAG, "ESP_SPP_CL_INIT_EVT"); | ||||
|         break; | ||||
|     case ESP_SPP_DATA_IND_EVT: | ||||
|         ESP_LOGV(SPP_TAG, "ESP_SPP_DATA_IND_EVT len=%d handle=%d", param->data_ind.len, param->data_ind.handle); | ||||
|         //esp_log_buffer_hex("",param->data_ind.data,param->data_ind.len); //for low level debug
 | ||||
| 
 | ||||
|         if (SerialQueueBT != 0){ | ||||
|             for (int i = 0; i < param->data_ind.len; i++) | ||||
|                 xQueueSend(SerialQueueBT, param->data_ind.data + i, (TickType_t)0); | ||||
|         } | ||||
|         else { | ||||
|             ESP_LOGE(SPP_TAG, "SerialQueueBT ERROR"); | ||||
|         } | ||||
|         break; | ||||
|     case ESP_SPP_CONG_EVT: | ||||
|         ESP_LOGI(SPP_TAG, "ESP_SPP_CONG_EVT"); | ||||
|         break; | ||||
|     case ESP_SPP_WRITE_EVT: | ||||
|         ESP_LOGV(SPP_TAG, "ESP_SPP_WRITE_EVT"); | ||||
|         break; | ||||
|     case ESP_SPP_SRV_OPEN_EVT: | ||||
|         client = param->open.handle; | ||||
|         ESP_LOGI(SPP_TAG, "ESP_SPP_SRV_OPEN_EVT"); | ||||
|         break; | ||||
|     default: | ||||
|         break; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static bool _init_bt(const char *deviceName) | ||||
| { | ||||
|     if (!btStarted() && !btStart()){ | ||||
|         ESP_LOGE(SPP_TAG, "%s initialize controller failed\n", __func__); | ||||
|         return false; | ||||
|     } | ||||
|      | ||||
|     esp_bluedroid_status_t bt_state = esp_bluedroid_get_status(); | ||||
|     if (bt_state == ESP_BLUEDROID_STATUS_UNINITIALIZED){ | ||||
|         if (esp_bluedroid_init()) { | ||||
|             ESP_LOGE(SPP_TAG, "%s initialize bluedroid failed\n", __func__); | ||||
|             return false; | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     if (bt_state != ESP_BLUEDROID_STATUS_ENABLED){ | ||||
|         if (esp_bluedroid_enable()) { | ||||
|             ESP_LOGE(SPP_TAG, "%s enable bluedroid failed\n", __func__); | ||||
|             return false; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     if (esp_spp_register_callback(esp_spp_cb) != ESP_OK){ | ||||
|         ESP_LOGE(SPP_TAG, "%s spp register failed\n", __func__); | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     if (esp_spp_init(esp_spp_mode) != ESP_OK){ | ||||
|         ESP_LOGE(SPP_TAG, "%s spp init failed\n", __func__); | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     SerialQueueBT = xQueueCreate(QUEUE_SIZE, sizeof(uint8_t)); //initialize the queue
 | ||||
|     if (SerialQueueBT == NULL){ | ||||
|         ESP_LOGE(SPP_TAG, "%s Queue creation error\n", __func__); | ||||
|         return false; | ||||
|     } | ||||
|     esp_bt_dev_set_device_name(deviceName); | ||||
| 
 | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| static bool _stop_bt() | ||||
| { | ||||
|     if (btStarted()){ | ||||
|         esp_bluedroid_disable(); | ||||
|         esp_bluedroid_deinit(); | ||||
|         btStop(); | ||||
|     } | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Serial Bluetooth Arduino | ||||
|  * | ||||
|  * */ | ||||
| 
 | ||||
| BluetoothSerial::BluetoothSerial() | ||||
| { | ||||
|     local_name = "ESP32"; //default bluetooth name
 | ||||
| } | ||||
| 
 | ||||
| BluetoothSerial::~BluetoothSerial(void) | ||||
| { | ||||
|     _stop_bt(); | ||||
| } | ||||
| 
 | ||||
| bool BluetoothSerial::begin(String localName) | ||||
| { | ||||
|     if (localName.length()){ | ||||
|         local_name = localName; | ||||
|     } | ||||
|     return _init_bt(local_name.c_str()); | ||||
| } | ||||
| 
 | ||||
| int BluetoothSerial::available(void) | ||||
| { | ||||
|     if (!client || SerialQueueBT == NULL){ | ||||
|         return 0; | ||||
|     } | ||||
|     return uxQueueMessagesWaiting(SerialQueueBT); | ||||
| } | ||||
| 
 | ||||
| int BluetoothSerial::peek(void) | ||||
| { | ||||
|     if (available()){ | ||||
|         if (!client || SerialQueueBT == NULL){ | ||||
|             return 0; | ||||
|         } | ||||
| 
 | ||||
|         uint8_t c; | ||||
|         if (xQueuePeek(SerialQueueBT, &c, 0)){ | ||||
|             return c; | ||||
|         } | ||||
|     } | ||||
|     return -1; | ||||
| } | ||||
| 
 | ||||
| int BluetoothSerial::read(void) | ||||
| { | ||||
|     if (available()){ | ||||
|         if (!client || SerialQueueBT == NULL){ | ||||
|             return 0; | ||||
|         } | ||||
| 
 | ||||
|         uint8_t c; | ||||
|         if (xQueueReceive(SerialQueueBT, &c, 0)){ | ||||
|             return c; | ||||
|         } | ||||
|         return 0; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| size_t BluetoothSerial::write(uint8_t c) | ||||
| { | ||||
|     if (client){ | ||||
|         uint8_t buffer[1]; | ||||
|         buffer[0] = c; | ||||
|         esp_spp_write(client, 1, buffer); | ||||
|         return 1; | ||||
|     } | ||||
|     return -1; | ||||
| } | ||||
| 
 | ||||
| size_t BluetoothSerial::write(const uint8_t *buffer, size_t size) | ||||
| { | ||||
|     if (client){ | ||||
|         esp_spp_write(client, size, (uint8_t *)buffer); | ||||
|     } | ||||
|     return size; | ||||
| } | ||||
| 
 | ||||
| void BluetoothSerial::flush() | ||||
| { | ||||
|     if (client){ | ||||
|         int qsize = available(); | ||||
|         uint8_t buffer[qsize]; | ||||
|         esp_spp_write(client, qsize, buffer); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void BluetoothSerial::end() | ||||
| { | ||||
|     _stop_bt(); | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										56
									
								
								libraries/BluetoothSerial/src/BluetoothSerial.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								libraries/BluetoothSerial/src/BluetoothSerial.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,56 @@ | ||||
| // Copyright 2018 Evandro Luis Copercini
 | ||||
| //
 | ||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||
| // you may not use this file except in compliance with the License.
 | ||||
| // You may obtain a copy of the License at
 | ||||
| 
 | ||||
| //     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
| //
 | ||||
| // Unless required by applicable law or agreed to in writing, software
 | ||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| #ifndef _BLUETOOTH_SERIAL_H_ | ||||
| #define _BLUETOOTH_SERIAL_H_ | ||||
| 
 | ||||
| #include "sdkconfig.h" | ||||
| 
 | ||||
| #if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BLUEDROID_ENABLED) | ||||
| 
 | ||||
| #include <cstdint> | ||||
| #include <cstdio> | ||||
| #include <cstdlib> | ||||
| #include <cstring> | ||||
| #include "freertos/FreeRTOS.h" | ||||
| #include "freertos/task.h" | ||||
| #include "esp_bt.h" | ||||
| 
 | ||||
| #include "Arduino.h" | ||||
| #include "Stream.h" | ||||
| 
 | ||||
| class BluetoothSerial: public Stream | ||||
| { | ||||
|     public: | ||||
| 
 | ||||
|         BluetoothSerial(void); | ||||
|         ~BluetoothSerial(void); | ||||
| 
 | ||||
|         bool begin(String localName=String()); | ||||
|         int available(void); | ||||
|         int peek(void); | ||||
|         int read(void); | ||||
|         size_t write(uint8_t c); | ||||
|         size_t write(const uint8_t *buffer, size_t size); | ||||
|         void flush(); | ||||
|         void end(void); | ||||
| 
 | ||||
|     private: | ||||
|         String local_name; | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| #endif | ||||
										
											Binary file not shown.
										
									
								
							
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user