diff --git a/examples/sandbox/ble/communication-ble-client/communication-ble-client.ino b/examples/sandbox/ble/communication-ble-client/communication-ble-client.ino index 196ea3d20c..a51863ef7f 100644 --- a/examples/sandbox/ble/communication-ble-client/communication-ble-client.ino +++ b/examples/sandbox/ble/communication-ble-client/communication-ble-client.ino @@ -26,7 +26,7 @@ void setup() { AudioLogger::instance().begin(Serial, AudioLogger::Info); // start BLE client - wait at most 10 minutes - ble.begin("ble-send", 60*10); + ble.begin("ble-receive", 60*10); // start decoder decoder.begin(info); diff --git a/examples/sandbox/ble/communication-ble-server/communication-ble-server.ino b/examples/sandbox/ble/communication-ble-server/communication-ble-server.ino index d6efb166c5..d8594f4692 100644 --- a/examples/sandbox/ble/communication-ble-server/communication-ble-server.ino +++ b/examples/sandbox/ble/communication-ble-server/communication-ble-server.ino @@ -28,6 +28,7 @@ void setup() { encoder.begin(info); + //ble.setAudioInfoActive(true); ble.begin("ble-send"); } diff --git a/src/Sandbox/BLE/AudioBLEClient.h b/src/Sandbox/BLE/AudioBLEClient.h index 798741e8d3..f114c2c2f7 100644 --- a/src/Sandbox/BLE/AudioBLEClient.h +++ b/src/Sandbox/BLE/AudioBLEClient.h @@ -23,18 +23,16 @@ class AudioBLEClient : public AudioBLEStream, public BLEClientCallbacks, public BLEAdvertisedDeviceCallbacks { public: - AudioBLEClient(int mtu = BLE_BUFFER_SIZE) : AudioBLEStream(mtu) { + AudioBLEClient(int mtu = BLE_MTU) : AudioBLEStream(mtu) { selfAudioBLEClient = this; + max_transfer_size = mtu; } - - /// starts a BLE client - bool begin(const char *serverName, int seconds) { + bool begin(const char *localName, int seconds) { TRACEI(); - ble_server_name = serverName; // Init BLE device - BLEDevice::init("client"); + BLEDevice::init(localName); // Retrieve a Scanner and set the callback we want to use to be informed // when we have detected a new device. @@ -53,22 +51,28 @@ class AudioBLEClient : public AudioBLEStream, size_t readBytes(uint8_t *data, size_t dataSize) override { TRACED(); - if (!is_client_connected || !is_client_set_up) return 0; - if (!ch01_char->canRead()) return 0; + setupBLEClient(); + if (!is_client_connected || !is_client_set_up) + return 0; + if (!ch01_char->canRead()) + return 0; // changed to auto to be version independent (it changed from std::string to // String) auto str = ch01_char->readValue(); - if (str.length() > 0){ + if (str.length() > 0) { memcpy(data, str.c_str(), str.length()); } return str.length(); } - int available() override { return BLE_BUFFER_SIZE; } + int available() override { return BLE_MTU; } size_t write(const uint8_t *data, size_t dataSize) override { + TRACED(); + setupBLEClient(); int result = 0; - if (!is_client_connected || !is_client_set_up) return 0; + if (!is_client_connected || !is_client_set_up) + return 0; if (ch02_char->canWrite()) { ch02_char->writeValue((uint8_t *)data, dataSize, false); result = dataSize; @@ -76,9 +80,16 @@ class AudioBLEClient : public AudioBLEStream, return result; } - int availableForWrite() override { return BLE_BUFFER_SIZE; } + int availableForWrite() override { return BLE_MTU; } + + bool connected() override { + if (!setupBLEClient()) { + LOGE("setupBLEClient failed"); + } + return is_client_connected; + } - virtual bool connected() override { return is_client_connected; } + void doLoop() { setupBLEClient(); } protected: // client @@ -90,14 +101,20 @@ class AudioBLEClient : public AudioBLEStream, BLERemoteCharacteristic *ch02_char = nullptr; // write BLERemoteCharacteristic *info_char = nullptr; BLEAdvertisedDevice advertised_device; + BLEUUID BLUEID_AUDIO_SERVICE_UUID{BLE_AUDIO_SERVICE_UUID}; + BLEUUID BLUEID_CH1_UUID{BLE_CH1_UUID}; + BLEUUID BLUEID_CH2_UUID{BLE_CH2_UUID}; + BLEUUID BLUEID_INFO_UUID{BLE_INFO_UUID}; + volatile bool is_client_connected = false; bool is_client_set_up = false; - virtual void onConnect(BLEClient *pClient) { + void onConnect(BLEClient *pClient) override { TRACEI(); is_client_connected = true; } - virtual void onDisconnect(BLEClient *pClient) { + + void onDisconnect(BLEClient *pClient) override { TRACEI(); is_client_connected = false; }; @@ -112,17 +129,13 @@ class AudioBLEClient : public AudioBLEStream, void onResult(BLEAdvertisedDevice advertisedDevice) override { TRACEI(); // Check if the name of the advertiser matches - if (advertisedDevice.getName() == ble_server_name) { - TRACEI(); + if (advertisedDevice.haveServiceUUID() && + advertisedDevice.isAdvertisingService(BLUEID_AUDIO_SERVICE_UUID)) { + LOGI("Service '%s' found!", BLE_AUDIO_SERVICE_UUID); + // save advertised_device in class variable advertised_device = advertisedDevice; // Scan can be stopped, we found what we are looking for advertised_device.getScan()->stop(); - // Address of advertiser is the one we need - // p_server_address = new BLEAddress(advertisedDevice.getAddress()); - - LOGI("Device '%s' found: Connecting!", - advertised_device.toString().c_str()); - setupBLEClient(); } delay(10); } @@ -137,6 +150,8 @@ class AudioBLEClient : public AudioBLEStream, } bool setupBLEClient() { + if (is_client_set_up) + return true; TRACEI(); if (p_client == nullptr) @@ -151,37 +166,53 @@ class AudioBLEClient : public AudioBLEStream, // p_client->connect(advertised_device.getAddress(),BLE_ADDR_TYPE_RANDOM); p_client->connect(&advertised_device); if (!p_client->isConnected()) { - LOGE("connect failed"); + LOGE("Connect failed"); return false; } + LOGI("Connected to %s ...", + advertised_device.getAddress().toString().c_str()); LOGI("Setting mtu to %d", max_transfer_size); + assert(max_transfer_size > 0); p_client->setMTU(max_transfer_size); // Obtain a reference to the service we are after in the remote BLE // server. if (p_remote_service == nullptr) { - p_remote_service = p_client->getService(BLE_SERIAL_SERVICE_UUID); + p_remote_service = p_client->getService(BLUEID_AUDIO_SERVICE_UUID); if (p_remote_service == nullptr) { - LOGE("Failed to find our service UUID: %s", BLE_SERIAL_SERVICE_UUID); + LOGE("Failed to find our service UUID: %s", BLE_AUDIO_SERVICE_UUID); return (false); } } if (ch01_char == nullptr) { - ch01_char = p_remote_service->getCharacteristic(BLE_CH1_UUID); + ch01_char = p_remote_service->getCharacteristic(BLUEID_CH1_UUID); + if (ch01_char == nullptr) { + LOGE("Failed to find char. UUID: %s", BLE_CH1_UUID); + return false; + } } if (ch02_char == nullptr) { - ch02_char = p_remote_service->getCharacteristic(BLE_CH2_UUID); + ch02_char = p_remote_service->getCharacteristic(BLUEID_CH2_UUID); + if (ch02_char == nullptr) { + LOGE("Failed to find char. UUID: %s", BLE_CH2_UUID); + return false; + } } if (is_audio_info_active && info_char == nullptr) { - info_char = p_remote_service->getCharacteristic(BLE_INFO_UUID); + info_char = p_remote_service->getCharacteristic(BLUEID_INFO_UUID); + if (info_char == nullptr) { + LOGE("Failed to find char. UUID: %s", BLE_INFO_UUID); + return false; + } info_char->registerForNotify(notifyCallback); } LOGI("Connected to server: %s", is_client_connected ? "true" : "false"); is_client_set_up = true; + is_client_connected = true; return is_client_connected; } }; diff --git a/src/Sandbox/BLE/AudioBLEServer.h b/src/Sandbox/BLE/AudioBLEServer.h index 9572f4b57f..b1e53bcf55 100644 --- a/src/Sandbox/BLE/AudioBLEServer.h +++ b/src/Sandbox/BLE/AudioBLEServer.h @@ -19,14 +19,14 @@ class AudioBLEServer : public AudioBLEStream, public BLECharacteristicCallbacks, public BLEServerCallbacks { public: - AudioBLEServer(int mtu = BLE_BUFFER_SIZE) : AudioBLEStream(mtu) {} + AudioBLEServer(int mtu = BLE_MTU) : AudioBLEStream(mtu) {} // starts a BLE server with the indicated name bool begin(const char *name) { TRACEI(); ble_server_name = name; BLEDevice::init(name); - BLEDevice::setMTU(BLE_BUFFER_SIZE); + //BLEDevice::setMTU(BLE_MTU); // Increase connection interval to 30 milliseconds (30 * 1.25 ms) // BLEDevice::setConnectionParams(30, 30, 0, 0); @@ -36,9 +36,9 @@ class AudioBLEServer : public AudioBLEStream, setupBLEService(); p_advertising = BLEDevice::getAdvertising(); - p_advertising->addServiceUUID(BLE_SERIAL_SERVICE_UUID); - p_advertising->setScanResponse(false); - p_advertising->setMinPreferred(0x00); + p_advertising->addServiceUUID(BLE_AUDIO_SERVICE_UUID); + //p_advertising->setScanResponse(false); + //p_advertising->setMinPreferred(0x00); // p_advertising->setMinPreferred(0x06); BLEDevice::startAdvertising(); return true; @@ -99,7 +99,6 @@ class AudioBLEServer : public AudioBLEStream, RingBuffer transmit_buffer_sizes{0}; virtual void receiveAudio(const uint8_t *data, size_t size) { - setupRXBuffer(); while (receive_buffer.availableForWrite() < size) { // wait for ringbuffer to get freed up delay(10); @@ -123,7 +122,7 @@ class AudioBLEServer : public AudioBLEStream, if (max_transfer_size == 0) { int peer_max_transfer_size = p_server->getPeerMTU(p_server->getConnId()) - 5; - max_transfer_size = std::min(BLE_BUFFER_SIZE, peer_max_transfer_size); + max_transfer_size = std::min(BLE_MTU, peer_max_transfer_size); LOGI("max_transfer_size: %d", max_transfer_size); } @@ -135,7 +134,7 @@ class AudioBLEServer : public AudioBLEStream, // characteristic property is what the other device does. if (p_service == nullptr) { - p_service = p_server->createService(BLE_SERIAL_SERVICE_UUID); + p_service = p_server->createService(BLE_AUDIO_SERVICE_UUID); ch01_char = p_service->createCharacteristic( BLE_CH1_UUID, BLECharacteristic::PROPERTY_READ ); @@ -160,16 +159,21 @@ class AudioBLEServer : public AudioBLEStream, info_desc.setValue("Audio Info"); info_char->addDescriptor(&info_desc); info_char->setCallbacks(this); + } p_service->start(); + + getMTU(); + + if (info_char != nullptr) { + writeAudioInfoCharacteristic(info); + } } } void onConnect(BLEServer *pServer) override { TRACEI(); - getMTU(); - writeAudioInfoCharacteristic(info); } void onDisconnect(BLEServer *pServer) override { @@ -180,6 +184,7 @@ class AudioBLEServer : public AudioBLEStream, /// store the next batch of data void onWrite(BLECharacteristic *pCharacteristic) override { TRACED(); + setupRXBuffer(); // changed to auto to be version independent (it changed from std::string to String) auto value = pCharacteristic->getValue(); if (pCharacteristic->getUUID().toString() == BLE_INFO_UUID) { @@ -210,6 +215,7 @@ class AudioBLEServer : public AudioBLEStream, void setupTXBuffer() { if (transmit_buffer.size() == 0) { + LOGI("Setting transmit_buffer to %d for mtu %d", RX_BUFFER_SIZE, getMTU()); transmit_buffer.resize(TX_BUFFER_SIZE); if (is_framed) { transmit_buffer_sizes.resize(TX_COUNT); @@ -219,6 +225,7 @@ class AudioBLEServer : public AudioBLEStream, void setupRXBuffer() { if (receive_buffer.size() == 0) { + LOGI("Setting receive_buffer to %d for mtu %d", RX_BUFFER_SIZE, getMTU()); receive_buffer.resize(RX_BUFFER_SIZE); if (is_framed) { receive_sizes.resize(RX_COUNT); diff --git a/src/Sandbox/BLE/AudioBLEStream.h b/src/Sandbox/BLE/AudioBLEStream.h index 87c534db65..b50a904969 100644 --- a/src/Sandbox/BLE/AudioBLEStream.h +++ b/src/Sandbox/BLE/AudioBLEStream.h @@ -5,7 +5,7 @@ #include "AudioTools/Buffers.h" // must be greater than MTU, less than ESP_GATT_MAX_ATTR_LEN -#define BLE_BUFFER_SIZE 512 +#define BLE_MTU 517 #define RX_BUFFER_SIZE 4096 #define RX_COUNT 100 #define TX_BUFFER_SIZE 4096 @@ -39,7 +39,7 @@ class AudioBLEStream : public AudioStream { operator bool() { return connected(); } - void setServiceUUID(const char *uuid) { BLE_SERIAL_SERVICE_UUID = uuid; } + void setServiceUUID(const char *uuid) { BLE_AUDIO_SERVICE_UUID = uuid; } void setRxUUID(const char *uuid) { BLE_CH2_UUID = uuid; } @@ -77,19 +77,21 @@ class AudioBLEStream : public AudioStream { // Bluetooth LE GATT UUIDs for the Nordic UART profile Change UUID here if // required - const char *BLE_SERIAL_SERVICE_UUID = "6e400001-b5a3-f393-e0a9-e50e24dcca9e"; + const char *BLE_AUDIO_SERVICE_UUID = "6e400001-b5a3-f393-e0a9-e50e24dcca9e"; const char *BLE_CH1_UUID = "6e400002-b5a3-f393-e0a9-e50e24dcca9e"; // RX const char *BLE_CH2_UUID = "6e400003-b5a3-f393-e0a9-e50e24dcca9e"; // TX const char *BLE_INFO_UUID = "6e400004-b5a3-f393-e0a9-e50e24dcca9e"; - virtual int getMTU() { return BLE_BUFFER_SIZE; } + virtual int getMTU() { return BLE_MTU; } + // override to implement your own extended logic virtual void setAudioInfo(const uint8_t *data, size_t size) { if (is_audio_info_active) { AudioInfo ai = toInfo(data); setAudioInfo(ai); } } + // override to implement your own extended logic virtual void writeAudioInfoCharacteristic(AudioInfo info) = 0; };