3 #include "AudioBLEStream.h"
4 #include "ConstantsESP32.h"
13 static AudioBLEClient *selfAudioBLEClient =
nullptr;
23 class AudioBLEClient :
public AudioBLEStream,
24 public BLEClientCallbacks,
25 public BLEAdvertisedDeviceCallbacks {
27 AudioBLEClient(
int mtu = BLE_MTU) : AudioBLEStream(mtu) {
28 selfAudioBLEClient =
this;
29 max_transfer_size = mtu;
33 bool begin(
const char *localName,
int seconds) {
36 BLEDevice::init(localName);
40 BLEScan *pBLEScan = BLEDevice::getScan();
41 pBLEScan->setAdvertisedDeviceCallbacks(
this);
42 pBLEScan->setActiveScan(
true);
43 pBLEScan->start(seconds);
53 size_t readBytes(uint8_t *data,
size_t len)
override {
56 if (!is_client_connected || !is_client_set_up)
58 if (!ch01_char->canRead())
62 auto str = ch01_char->readValue();
63 if (str.length() > 0) {
64 memcpy(data, str.c_str(), str.length());
69 int available()
override {
return BLE_MTU - BLE_MTU_OVERHEAD; }
71 size_t write(
const uint8_t *data,
size_t len)
override {
74 if (!is_client_connected || !is_client_set_up)
76 if (!ch02_char->canWrite()){
81 writeChannel2Characteristic(data, len);
85 for (
int j=0; j<len; j++){
86 write_buffer.
write(data[j]);
87 if (write_buffer.
isFull()){
88 writeChannel2Characteristic(write_buffer.
data(), write_buffer.
available());
96 int availableForWrite()
override {
97 return is_framed ? (BLE_MTU - BLE_MTU_OVERHEAD) : DEFAULT_BUFFER_SIZE;
100 bool connected()
override {
101 if (!setupBLEClient()) {
102 LOGE(
"setupBLEClient failed");
104 return is_client_connected;
107 void setWriteThrottle(
int ms){
111 void setConfirmWrite(
bool flag){
112 write_confirmation_flag = flag;
117 BLEClient *p_client =
nullptr;
118 BLEAdvertising *p_advertising =
nullptr;
119 BLERemoteService *p_remote_service =
nullptr;
120 BLEAddress *p_server_address =
nullptr;
121 BLERemoteCharacteristic *ch01_char =
nullptr;
122 BLERemoteCharacteristic *ch02_char =
nullptr;
123 BLERemoteCharacteristic *info_char =
nullptr;
124 BLEAdvertisedDevice advertised_device;
125 BLEUUID BLUEID_AUDIO_SERVICE_UUID{BLE_AUDIO_SERVICE_UUID};
126 BLEUUID BLUEID_CH1_UUID{BLE_CH1_UUID};
127 BLEUUID BLUEID_CH2_UUID{BLE_CH2_UUID};
128 BLEUUID BLUEID_INFO_UUID{BLE_INFO_UUID};
129 SingleBuffer<uint8_t> write_buffer{0};
130 int write_throttle = 0;
131 bool write_confirmation_flag =
false;
133 volatile bool is_client_connected =
false;
134 bool is_client_set_up =
false;
136 void onConnect(BLEClient *pClient)
override {
138 is_client_connected =
true;
141 void onDisconnect(BLEClient *pClient)
override {
143 is_client_connected =
false;
146 void writeAudioInfoCharacteristic(AudioInfo info)
override {
149 info_char->writeValue((uint8_t *)&info,
sizeof(AudioInfo));
152 void writeChannel2Characteristic(
const uint8_t*data,
size_t len){
153 if (ch02_char->canWrite()) {
154 ch02_char->writeValue((uint8_t *)data, len, write_confirmation_flag);
155 delay(write_throttle);
159 bool readAudioInfoCharacteristic(){
160 if (!info_char->canRead())
162 auto str = info_char->readValue();
163 if (str.length() > 0) {
164 setAudioInfo((
const uint8_t*)str.c_str(), str.length());
171 void onResult(BLEAdvertisedDevice advertisedDevice)
override {
174 if (advertisedDevice.haveServiceUUID() &&
175 advertisedDevice.isAdvertisingService(BLUEID_AUDIO_SERVICE_UUID)) {
176 LOGI(
"Service '%s' found!", BLE_AUDIO_SERVICE_UUID);
178 advertised_device = advertisedDevice;
180 advertised_device.getScan()->stop();
185 static void notifyCallback(BLERemoteCharacteristic *pBLERemoteCharacteristic,
186 uint8_t *pData,
size_t length,
bool isNotify) {
188 if (pBLERemoteCharacteristic->getUUID().toString() ==
189 selfAudioBLEClient->BLE_INFO_UUID) {
194 bool setupBLEClient() {
195 if (is_client_set_up)
201 if (write_buffer.size()==0){
202 write_buffer.resize(getMTU() - BLE_MTU_OVERHEAD);
205 if (p_client ==
nullptr)
206 p_client = BLEDevice::createClient();
209 p_client->setClientCallbacks(
this);
212 LOGI(
"Connecting to %s ...",
213 advertised_device.getAddress().toString().c_str());
215 p_client->connect(&advertised_device);
216 if (!p_client->isConnected()) {
217 LOGE(
"Connect failed");
220 LOGI(
"Connected to %s ...",
221 advertised_device.getAddress().toString().c_str());
223 LOGI(
"Setting mtu to %d", max_transfer_size);
224 assert(max_transfer_size > 0);
225 p_client->setMTU(max_transfer_size);
229 if (p_remote_service ==
nullptr) {
230 p_remote_service = p_client->getService(BLUEID_AUDIO_SERVICE_UUID);
231 if (p_remote_service ==
nullptr) {
232 LOGE(
"Failed to find our service UUID: %s", BLE_AUDIO_SERVICE_UUID);
237 if (ch01_char ==
nullptr) {
238 ch01_char = p_remote_service->getCharacteristic(BLUEID_CH1_UUID);
239 if (ch01_char ==
nullptr) {
240 LOGE(
"Failed to find char. UUID: %s", BLE_CH1_UUID);
245 if (ch02_char ==
nullptr) {
246 ch02_char = p_remote_service->getCharacteristic(BLUEID_CH2_UUID);
247 if (ch02_char ==
nullptr) {
248 LOGE(
"Failed to find char. UUID: %s", BLE_CH2_UUID);
253 if (is_audio_info_active && info_char ==
nullptr) {
254 info_char = p_remote_service->getCharacteristic(BLUEID_INFO_UUID);
255 if (info_char ==
nullptr) {
256 LOGE(
"Failed to find char. UUID: %s", BLE_INFO_UUID);
259 info_char->registerForNotify(notifyCallback);
260 readAudioInfoCharacteristic();
263 LOGI(
"Connected to server: %s", is_client_connected ?
"true" :
"false");
264 is_client_set_up =
true;
265 is_client_connected =
true;
266 return is_client_connected;
269 int getMTU()
override {
return BLE_MTU; }