diff --git a/ci/build-arduino.sh b/ci/build-arduino.sh index 55a9814..fd30016 100644 --- a/ci/build-arduino.sh +++ b/ci/build-arduino.sh @@ -6,15 +6,16 @@ shopt -s globstar # Make sure we are inside the github workspace cd $GITHUB_WORKSPACE # Create directories -mkdir $HOME/Arduino -mkdir $HOME/Arduino/libraries +mkdir $HOME/Arduino -p +mkdir $HOME/Arduino/libraries -p # Install Arduino IDE export PATH=$PATH:$GITHUB_WORKSPACE/bin curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh | sh arduino-cli config init arduino-cli config set library.enable_unsafe_install true # arduino-cli core update-index --additional-urls https://arduino.esp8266.com/stable/package_esp8266com_index.json -arduino-cli core update-index --additional-urls https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json +#arduino-cli core update-index --additional-urls https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json +sed -i 's+\[\]+\[https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json\]+g' /home/runner/.arduino15/arduino-cli.yaml arduino-cli core update-index # Install Arduino AVR core @@ -24,13 +25,13 @@ arduino-cli core install arduino:samd arduino-cli core install esp32:esp32 # List the boards -arduino-cli board list +arduino-cli board listall # Link Arduino library ln -s $GITHUB_WORKSPACE $HOME/Arduino/libraries/CI_Test_Library arduino-cli lib install "MIDI library" -arduino-cli lib install ArduinoBLE +#arduino-cli lib install ArduinoBLE arduino-cli lib install NimBLE-Arduino # Compile all *.ino files for the Arduino Uno @@ -48,7 +49,14 @@ arduino-cli lib install NimBLE-Arduino # arduino-cli compile -b arduino:esp8266:??? $f # done +dR=$(pwd) + # Compile all *.ino files for the Arduino Uno for f in **/*.ino ; do - arduino-cli compile -b arduino:esp32:??? $f + echo "Project: $f" + d=$(dirname $(readlink -f $f)) + echo $d + cd $d + arduino-cli compile -b esp32:esp32:esp32 *.ino --clean + cd $dR done diff --git a/examples/CustomerBufferSize/CustomerBufferSize.ino b/examples/CustomerBufferSize/CustomerBufferSize.ino index 3dc8515..8aa7e94 100644 --- a/examples/CustomerBufferSize/CustomerBufferSize.ino +++ b/examples/CustomerBufferSize/CustomerBufferSize.ino @@ -1,13 +1,67 @@ #include +static uint32_t customPasskeyRequest() +{ + // FILL WITH YOUR CUSTOM AUTH METHOD CODE or PASSKEY + // FOR EXAMPLE: + uint32_t passkey = 123456; + + // Serial.println("Client Passkey Request"); + + /** return the passkey to send to the server */ + return passkey; +}; + struct CustomBufferSizeSettings : public BLEMIDI_NAMESPACE::DefaultSettings { + //See all options and them explanation in the library. + + /* + ##### BLE DEVICE NAME ##### + */ + //static constexpr char *name = "BleMidiClient"; + /* + ###### TX POWER ##### + */ + //static const esp_power_level_t clientTXPwr = ESP_PWR_LVL_P9; + /* + ###### SECURITY ##### + */ + //static const uint8_t clientSecurityCapabilities = BLE_HS_IO_NO_INPUT_OUTPUT; + //static const bool clientBond = true; + //static const bool clientMITM = false; + //static const bool clientPair = true; + //static constexpr PasskeyRequestCallback userOnPassKeyRequest = customPasskeyRequest; + /* + ###### BLE COMMUNICATION PARAMS ###### + */ + //static const uint16_t commMinInterval = 6; // 7.5ms + //static const uint16_t commMaxInterval = 35; // 40ms + //static const uint16_t commLatency = 0; // + //static const uint16_t commTimeOut = 200; // 2000ms + /* + ###### BLE FORCE NEW CONNECTION ###### + */ + //static const bool forceNewConnection = false; + /* + ###### BLE SUBSCRIPTION: NOTIFICATION & RESPONSE ###### + */ + //static const bool notification = true; + //static const bool response = true; + /* + ###### AND THE OTHER SETTINGS OF MIDI LIBRARY ###### + */ static const size_t MaxBufferSize = 16; + }; #include //#include //#include +#ifndef LED_BUILTIN +#define LED_BUILTIN 2 +#endif + BLEMIDI_CREATE_CUSTOM_INSTANCE("Esp32-NimBLE-MIDI", MIDI, CustomBufferSizeSettings); unsigned long t0 = millis(); @@ -61,4 +115,4 @@ void loop() MIDI.sendNoteOn (60, 100, 1); // note 60, velocity 100 on channel 1 } -} \ No newline at end of file +} diff --git a/examples/MidiBle/MidiBle.ino b/examples/MidiBle/MidiBle.ino index 69968b1..9022671 100644 --- a/examples/MidiBle/MidiBle.ino +++ b/examples/MidiBle/MidiBle.ino @@ -4,6 +4,10 @@ #include //#include +#ifndef LED_BUILTIN +#define LED_BUILTIN 2 +#endif + BLEMIDI_CREATE_DEFAULT_INSTANCE() unsigned long t0 = millis(); diff --git a/examples/MidiBle_Client/MidiBle_Client.ino b/examples/MidiBle_Client/MidiBle_Client.ino index 5109890..08efbeb 100644 --- a/examples/MidiBle_Client/MidiBle_Client.ino +++ b/examples/MidiBle_Client/MidiBle_Client.ino @@ -14,10 +14,10 @@ * the name of the server or the BLE address of the server. If you want to connect * to the first MIDI server BLE found by the device, you just have to set the name field empty (""). * - * FOR ADVANCED USERS: Other advanced BLE configurations can be changed in hardware/BLEMIDI_Client_ESP32.h - * #defines in the head of the file (IMPORTANT: Only the first user defines must be modified). These configurations - * are related to security (password, pairing and securityCallback()), communication params, the device name - * and other stuffs. Modify defines at your own risk. + * FOR ADVANCED USERS: Other advanced BLE configurations can be changed with a struct that heritate + * from BLEMIDI_NAMESPACE::DefaultSettingsClient. These configurations are related to + * security (password, pairing and securityCallback()), communication params, the device name + * and other stuffs. Modify those settings at your own risk. * * * @@ -28,21 +28,26 @@ #include #include - struct CustomBufferSizeSettings : public BLEMIDI_NAMESPACE::DefaultSettings { - static const size_t MaxBufferSize = 16; -}; - #include - //#include //#include //#include -BLEMIDI_CREATE_CUSTOM_INSTANCE("Esp32-BLE-MIDI", MIDI, CustomBufferSizeSettings); // Connect to first server found +#ifndef LED_BUILTIN +#define LED_BUILTIN 2 +#endif -//BLEMIDI_CREATE_INSTANCE("",MIDI) //Connect to the first server found -//BLEMIDI_CREATE_INSTANCE("f2:c1:d9:36:e7:6b",MIDI) //Connect to a specific BLE address server -//BLEMIDI_CREATE_INSTANCE("MyBLEserver",MIDI) //Connect to a specific name server +//See DefaultSettingsClient in hardware/BLEMIDI_Client_ESP32.h for more configurable settings +// If you do not redefine a parameter, it will use the default value for these parameter +struct CustomBufferSizeSettings : public BLEMIDI_NAMESPACE::DefaultSettingsClient { + static const size_t MaxBufferSize = 16; +}; + +BLEMIDI_CREATE_CUSTOM_INSTANCE("Esp32-BLE-MIDI", MIDI, CustomBufferSizeSettings); // Connect to a server named "Esp32-BLE-MIDI" and use CustomBufferSizeSettings as settings of client + +//BLEMIDI_CREATE_INSTANCE("",MIDI) //Connect to the first server found, using default settings +//BLEMIDI_CREATE_INSTANCE("f2:c1:d9:36:e7:6b",MIDI) //Connect to a specific BLE address server, using default settings +//BLEMIDI_CREATE_INSTANCE("MyBLEserver",MIDI) //Connect to a specific name server, using default settings #ifndef LED_BUILTIN #define LED_BUILTIN 2 //modify for match with yout board diff --git a/examples/SysEx_Receive/SysEx_Receive.ino b/examples/SysEx_Receive/SysEx_Receive.ino index 3b3adb1..79b4684 100644 --- a/examples/SysEx_Receive/SysEx_Receive.ino +++ b/examples/SysEx_Receive/SysEx_Receive.ino @@ -4,6 +4,10 @@ #include //#include +#ifndef LED_BUILTIN +#define LED_BUILTIN 2 +#endif + BLEMIDI_CREATE_INSTANCE("CustomName", MIDI) bool isConnected = false; diff --git a/examples/SysEx_Send/SysEx_Send.ino b/examples/SysEx_Send/SysEx_Send.ino index 9e83e60..4c5b855 100644 --- a/examples/SysEx_Send/SysEx_Send.ino +++ b/examples/SysEx_Send/SysEx_Send.ino @@ -4,6 +4,10 @@ //#include //#include +#ifndef LED_BUILTIN +#define LED_BUILTIN 2 +#endif + byte sysex4[] = { 0xF0, 0x43, 0x20, 0xF7 }; byte sysex5[] = { 0xF0, 0x43, 0x20, 0x7E, 0xF7 }; byte sysex6[] = { 0xF0, 0x43, 0x20, 0x7E, 0x4C, 0xF7 }; diff --git a/src/BLEMIDI_Transport.h b/src/BLEMIDI_Transport.h index d37d943..e84e7ad 100644 --- a/src/BLEMIDI_Transport.h +++ b/src/BLEMIDI_Transport.h @@ -256,10 +256,10 @@ public: byte headerByte = buffer[lPtr++]; auto timestampHigh = 0x3f & headerByte; - + timestampHigh = timestampHigh; // <-- This line is for avoid Warning message due it is unused byte timestampByte = buffer[lPtr++]; uint16_t timestamp = 0; - + timestamp = timestamp; // <-- This line is for avoid Warning message due it is unused bool sysExContinuation = false; bool runningStatusContinuation = false; diff --git a/src/hardware/BLEMIDI_Client_ESP32.h b/src/hardware/BLEMIDI_Client_ESP32.h index 0c1fcd0..92b3318 100644 --- a/src/hardware/BLEMIDI_Client_ESP32.h +++ b/src/hardware/BLEMIDI_Client_ESP32.h @@ -1,180 +1,143 @@ #pragma once -/* -############################################# -########## USER DEFINES BEGINNING ########### -####### Modify only these parameters ######## -############################################# -*/ +//#define MIDIBLECLIENTVERBOSE -/* -##### BLE DEVICE NAME ##### -*/ - -/** - * Set always the same name independently of name server - */ -//#define BLEMIDI_CLIENT_FIXED_NAME "BleMidiClient" - -#ifndef BLEMIDI_CLIENT_FIXED_NAME //Not modify -/** - * When client tries to connect to specific server, BLE name is composed as follows: - * BLEMIDI_CLIENT_NAME_PREFIX + + BLEMIDI_CLIENT_NAME_SUBFIX - * - * example: - * BLEMIDI_CLIENT_NAME_PREFIX "Client-" - * "AX-Edge" - * BLEMIDI_CLIENT_NAME_SUBFIX "-Midi1" - * - * Result: "Client-AX-Edge-Midi1" - */ -#define BLEMIDI_CLIENT_NAME_PREFIX "C-" -#define BLEMIDI_CLIENT_NAME_SUBFIX "" - -/** - * When client tries to connect to the first midi server found: - */ -#define BLEMIDI_CLIENT_DEFAULT_NAME "BLEMIDI-CLIENT" -#endif //Not modify - -/* -###### TX POWER ##### -*/ -/** - * Set power transmision - * - * ESP_PWR_LVL_N12 // Corresponding to -12dbm Minimum - * ESP_PWR_LVL_N9 // Corresponding to -9dbm - * ESP_PWR_LVL_N6 // Corresponding to -6dbm - * ESP_PWR_LVL_N3 // Corresponding to -3dbm - * ESP_PWR_LVL_N0 // Corresponding to 0dbm - * ESP_PWR_LVL_P3 // Corresponding to +3dbm - * ESP_PWR_LVL_P6 // Corresponding to +6dbm - * ESP_PWR_LVL_P9 // Corresponding to +9dbm Maximum -*/ - -#define BLEMIDI_TX_PWR ESP_PWR_LVL_P9 - -/* -###### SECURITY ##### -*/ - -/** Set the IO capabilities of the device, each option will trigger a different pairing method. - * BLE_HS_IO_KEYBOARD_ONLY - Passkey pairing - * BLE_HS_IO_DISPLAY_YESNO - Numeric comparison pairing - * BLE_HS_IO_NO_INPUT_OUTPUT - DEFAULT setting - just works pairing - */ -#define BLEMIDI_CLIENT_SECURITY_CAP BLE_HS_IO_NO_INPUT_OUTPUT - -/** Set the security method. - * bonding - * man in the middle protection - * pair. secure connections - * - * More info in nimBLE lib - * - * Uncomment what you need - * These are the default values. - * You can select some simultaneously. - */ -#define BLEMIDI_CLIENT_BOND -//#define BLEMIDI_CLIENT_MITM -#define BLEMIDI_CLIENT_PAIR - -/** - * This callback function defines what will be done when server requieres PassKey. - * Add your custom code here. - */ -static uint32_t userOnPassKeyRequest() -{ - //FILL WITH YOUR CUSTOM AUTH METHOD CODE or PASSKEY - //FOR EXAMPLE: - uint32_t passkey = 123456; - - //Serial.println("Client Passkey Request"); - - /** return the passkey to send to the server */ - return passkey; -}; - - /* -###### BLE COMMUNICATION PARAMS ###### -*/ - /** Set connection parameters: - * If you only use one connection, put recomended BLE server param communication - * (you may scan it ussing "nRF Connect" app or other similar apps). - * - * If you use more than one connection adjust, for example, settings like 15ms interval, 0 latency, 120ms timout. - * These settings may be safe for 3 clients to connect reliably, set faster values if you have less - * connections. - * - * Min interval (unit: 1.25ms): 12 * 1.25ms = 15 ms, - * Max interval (unit: 1.25ms): 12 * 1.25ms = 15, - * 0 latency (Number of intervals allowed to skip), - * TimeOut (unit: 10ms) 51 * 10ms = 510ms. Timeout should be minimum 100ms. - */ -#define BLEMIDI_CLIENT_COMM_MIN_INTERVAL 6 // 7.5ms -#define BLEMIDI_CLIENT_COMM_MAX_INTERVAL 35 // 40ms -#define BLEMIDI_CLIENT_COMM_LATENCY 0 // -#define BLEMIDI_CLIENT_COMM_TIMEOUT 200 //2000ms - -/* -###### BLE FORCE NEW CONNECTION ###### -*/ - -/** - * This parameter force to skip the "soft-reconnection" and force to create a new connection after a disconnect event. - * "Soft-reconnection" save some time and energy in comparation with performming a new connection, but some BLE devices - * don't support or don't perform correctly a "soft-reconnection" after a disconnection event. - * Uncomment this define if your device doesn't work propertily after a reconnection. - * -*/ -//#define BLEMIDI_FORCE_NEW_CONNECTION - -/** - * -*/ - -/* -############################################# -############ USER DEFINES END ############### -############################################# -*/ +#ifdef MIDIBLECLIENTVERBOSE +#define DEBUGCLIENT(_text_) Serial.println("DbgBC: " + (String)_text_); +#else +#define DEBUGCLIENT(_text_) ; +#endif // Headers for ESP32 nimBLE #include BEGIN_BLEMIDI_NAMESPACE -#ifdef BLEMIDI_CLIENT_BOND -#define BLEMIDI_CLIENT_BOND_DUMMY BLE_SM_PAIR_AUTHREQ_BOND -#else -#define BLEMIDI_CLIENT_BOND_DUMMY 0x00 -#endif +using PasskeyRequestCallback = uint32_t (*)(void); -#ifdef BLEMIDI_CLIENT_MITM -#define BLEMIDI_CLIENT_MITM_DUMMY BLE_SM_PAIR_AUTHREQ_MITM -#else -#define BLEMIDI_CLIENT_MITM_DUMMY 0x00 -#endif +static uint32_t defautlPasskeyRequest() +{ + // FILL WITH YOUR CUSTOM AUTH METHOD CODE or PASSKEY + // FOR EXAMPLE: + uint32_t passkey = 123456; -#ifdef BLEMIDI_CLIENT_PAIR -#define BLEMIDI_CLIENT_PAIR_DUMMY BLE_SM_PAIR_AUTHREQ_SC -#else -#define BLEMIDI_CLIENT_PAIR_DUMMY 0x00 -#endif + // Serial.println("Client Passkey Request"); -/** Set the security method. + /** return the passkey to send to the server */ + return passkey; +}; + +struct DefaultSettingsClient : public BLEMIDI_NAMESPACE::DefaultSettings +{ + + /* + ##### BLE DEVICE NAME ##### + */ + + /** + * Set name of ble device (not affect to connection with server) + * max 16 characters + */ + static constexpr char *name = "BleMidiClient"; + + /* + ###### TX POWER ##### + */ + + /** + * Set power transmision + * + * ESP_PWR_LVL_N12 // Corresponding to -12dbm Minimum + * ESP_PWR_LVL_N9 // Corresponding to -9dbm + * ESP_PWR_LVL_N6 // Corresponding to -6dbm + * ESP_PWR_LVL_N3 // Corresponding to -3dbm + * ESP_PWR_LVL_N0 // Corresponding to 0dbm + * ESP_PWR_LVL_P3 // Corresponding to +3dbm + * ESP_PWR_LVL_P6 // Corresponding to +6dbm + * ESP_PWR_LVL_P9 // Corresponding to +9dbm Maximum + */ + static const esp_power_level_t clientTXPwr = ESP_PWR_LVL_P9; + + /* + ###### SECURITY ##### + */ + + /** Set the IO capabilities of the device, each option will trigger a different pairing method. + * BLE_HS_IO_KEYBOARD_ONLY - Passkey pairing + * BLE_HS_IO_DISPLAY_YESNO - Numeric comparison pairing + * BLE_HS_IO_NO_INPUT_OUTPUT - DEFAULT setting - just works pairing + */ + static const uint8_t clientSecurityCapabilities = BLE_HS_IO_NO_INPUT_OUTPUT; + + /** Set the security method. * bonding * man in the middle protection * pair. secure connections - * + * * More info in nimBLE lib */ -#define BLEMIDI_CLIENT_SECURITY_AUTH (BLEMIDI_CLIENT_BOND_DUMMY | BLEMIDI_CLIENT_MITM_DUMMY | BLEMIDI_CLIENT_PAIR_DUMMY) + static const bool clientBond = true; + static const bool clientMITM = false; + static const bool clientPair = true; + + /** + * This callback function defines what will be done when server requieres PassKey. + * Add your custom code here. + */ + static constexpr PasskeyRequestCallback userOnPassKeyRequest = defautlPasskeyRequest; + + /* + ###### BLE COMMUNICATION PARAMS ###### + */ + + /** Set connection parameters: + * If you only use one connection, put recomended BLE server param communication + * (you may scan it ussing "nRF Connect" app or other similar apps). + * + * If you use more than one connection adjust, for example, settings like 15ms interval, 0 latency, 120ms timout. + * These settings may be safe for 3 clients to connect reliably, set faster values if you have less + * connections. + * + * Min interval (unit: 1.25ms): 12 * 1.25ms = 15 ms, + * Max interval (unit: 1.25ms): 12 * 1.25ms = 15, + * 0 latency (Number of intervals allowed to skip), + * TimeOut (unit: 10ms) 51 * 10ms = 510ms. Timeout should be minimum 100ms. + */ + static const uint16_t commMinInterval = 6; // 7.5ms + static const uint16_t commMaxInterval = 35; // 40ms + static const uint16_t commLatency = 0; // + static const uint16_t commTimeOut = 200; // 2000ms + + /* + ###### BLE FORCE NEW CONNECTION ###### + */ + + /** + * This parameter force to skip the "soft-reconnection" and force to create a new connection after a disconnect event. + * "Soft-reconnection" save some time and energy in comparation with performming a new connection, but some BLE devices + * don't support or don't perform correctly a "soft-reconnection" after a disconnection event. + * Set to "true" if your device doesn't work propertily after a reconnection. + * + */ + static const bool forceNewConnection = false; + + /* + ###### BLE SUBSCRIPTION: NOTIFICATION & RESPONSE ###### + */ + + /** + * Subscribe in Notification Mode [true] or Indication Mode [false] + * Don't modify this parameter except is completely necessary. + */ + static const bool notification = true; + /** + * Respond to after a notification message. + * Don't modify this parameter except is completely necessary. + */ + static const bool response = true; +}; /** Define a class to handle the callbacks when advertisments are received */ -template class AdvertisedDeviceCallbacks : public NimBLEAdvertisedDeviceCallbacks { public: @@ -188,32 +151,34 @@ public: protected: void onResult(NimBLEAdvertisedDevice *advertisedDevice) { - if (enableConnection) //not begin() or end() + if (!enableConnection) // not begin() or end() { - Serial.print("Advertised Device found: "); - Serial.println(advertisedDevice->toString().c_str()); - if (advertisedDevice->isAdvertisingService(NimBLEUUID(SERVICE_UUID))) - { - Serial.println("Found MIDI Service"); - if (!specificTarget || (advertisedDevice->getName() == nameTarget.c_str() || advertisedDevice->getAddress() == nameTarget)) - { - /** Ready to connect now */ - doConnect = true; - /** Save the device reference in a public variable that the client can use*/ - advDevice = *advertisedDevice; - /** stop scan before connecting */ - NimBLEDevice::getScan()->stop(); - } - else - { - Serial.println("Name error"); - } - } - else - { - doConnect = false; - } + return; } + + DEBUGCLIENT("Advertised Device found: "); + DEBUGCLIENT(advertisedDevice->toString().c_str()); + if (!advertisedDevice->isAdvertisingService(NimBLEUUID(SERVICE_UUID))) + { + doConnect = false; + return; + } + + DEBUGCLIENT("Found MIDI Service"); + if (!(!specificTarget || (advertisedDevice->getName() == nameTarget.c_str() || advertisedDevice->getAddress() == nameTarget))) + { + DEBUGCLIENT("Name error"); + return; + } + + /** Ready to connect now */ + doConnect = true; + /** Save the device reference in a public variable that the client can use*/ + advDevice = *advertisedDevice; + /** stop scan before connecting */ + NimBLEDevice::getScan()->stop(); + + return; }; }; @@ -229,16 +194,13 @@ private: BLEAdvertising *_advertising = nullptr; BLERemoteCharacteristic *_characteristic = nullptr; BLERemoteService *pSvc = nullptr; - bool firstTimeSend = true; //First writeValue get sends like Write with reponse for clean security flags. After first time, all messages are send like WriteNoResponse for increase transmision speed. + bool firstTimeSend = true; // First writeValue get sends like Write with reponse for clean security flags. After first time, all messages are send like WriteNoResponse for increase transmision speed. BLEMIDI_Transport, _Settings> *_bleMidiTransport = nullptr; bool specificTarget = false; - // TODO: somehow the forward declaration of the template class is not accepted by the compiler -// template friend MyClientCallbacks; - - AdvertisedDeviceCallbacks<_Settings> myAdvCB; + AdvertisedDeviceCallbacks myAdvCB; protected: QueueHandle_t mRxQueue; @@ -255,9 +217,11 @@ public: myAdvCB.enableConnection = false; xQueueReset(mRxQueue); _client->disconnect(); - _client = nullptr; + bool success = !_client->isConnected(); + if (success) + _client = nullptr; - return !_client->isConnected(); + return success; } void write(uint8_t *data, uint8_t length) @@ -300,7 +264,7 @@ protected: void scan(); bool connect(); -public: // TODO: somehow the forward declaration of the template class is not accepted by the compiler +public: void connected() { if (_bleMidiTransport->_connectedCallback) @@ -331,58 +295,56 @@ protected: uint32_t onPassKeyRequest() { - return userOnPassKeyRequest(); + // if (nullptr != _Settings::userOnPassKeyRequest) + return _Settings::userOnPassKeyRequest(); + // return 0; }; - void onConnect(BLEClient*) + void onConnect(BLEClient *pClient) { - //Serial.println("##Connected##"); - //pClient->updateConnParams(BLEMIDI_CLIENT_COMM_MIN_INTERVAL, BLEMIDI_CLIENT_COMM_MAX_INTERVAL, BLEMIDI_CLIENT_COMM_LATENCY, BLEMIDI_CLIENT_COMM_TIMEOUT); + DEBUGCLIENT("##Connected##"); + // pClient->updateConnParams(_Settings::commMinInterval, _Settings::commMaxInterval, _Settings::commLatency, _Settings::commTimeOut); vTaskDelay(1); if (_bluetoothEsp32) _bluetoothEsp32->connected(); }; - void onDisconnect(BLEClient*) + void onDisconnect(BLEClient *pClient) { - //Serial.print(pClient->getPeerAddress().toString().c_str()); - //Serial.println(" Disconnected - Starting scan"); + DEBUGCLIENT(pClient->getPeerAddress().toString().c_str()); + DEBUGCLIENT(" Disconnected - Starting scan"); if (_bluetoothEsp32) { _bluetoothEsp32->disconnected(); -#ifdef BLEMIDI_FORCE_NEW_CONNECTION - // Try reconnection or search a new one - _bluetoothEsp32->scan(); -#endif // BLEMIDI_FORCE_NEW_CONNECTION } -#ifdef BLEMIDI_FORCE_NEW_CONNECTION - // Renew Client - NimBLEDevice::deleteClient(pClient); - NimBLEDevice::createClient(); - pClient = nullptr; -#endif // BLEMIDI_FORCE_NEW_CONNECTION + if (_Settings::forceNewConnection) + { + // Renew Client + NimBLEDevice::deleteClient(pClient); + pClient = nullptr; + } - //Try reconnection or search a new one + // Try reconnection or search a new one NimBLEDevice::getScan()->start(1, scanEndedCB); } bool onConnParamsUpdateRequest(NimBLEClient *pClient, const ble_gap_upd_params *params) { - if (params->itvl_min < BLEMIDI_CLIENT_COMM_MIN_INTERVAL) + if (params->itvl_min < _Settings::commMinInterval) { /** 1.25ms units */ return false; } - else if (params->itvl_max > BLEMIDI_CLIENT_COMM_MAX_INTERVAL) + else if (params->itvl_max > _Settings::commMaxInterval) { /** 1.25ms units */ return false; } - else if (params->latency > BLEMIDI_CLIENT_COMM_LATENCY) + else if (params->latency > _Settings::commLatency) { /** Number of intervals allowed to skip */ return false; } - else if (params->supervision_timeout > BLEMIDI_CLIENT_COMM_TIMEOUT) + else if (params->supervision_timeout > _Settings::commMinInterval) { /** 10ms units */ return false; } @@ -404,41 +366,34 @@ bool BLEMIDI_Client_ESP32<_Settings>::begin(const char *deviceName, BLEMIDI_Tran _bleMidiTransport = bleMidiTransport; std::string strDeviceName(deviceName); - if (strDeviceName == "") // Connect to the first midi server found + // Connect to the first midi server found + if (strDeviceName == "") { myAdvCB.specificTarget = false; myAdvCB.nameTarget = ""; - -#ifdef BLEMIDI_CLIENT_FIXED_NAME - strDeviceName = BLEMIDI_CLIENT_FIXED_NAME; -#else - strDeviceName = BLEMIDI_CLIENT_DEFAULT_NAME; -#endif } - else // Connect to a specific name or address + // Connect to a specific name or address + else { myAdvCB.specificTarget = true; myAdvCB.nameTarget = strDeviceName; - -#ifdef BLEMIDI_CLIENT_FIXED_NAME - strDeviceName = BLEMIDI_CLIENT_FIXED_NAME; -#else - strDeviceName = BLEMIDI_CLIENT_NAME_PREFIX + strDeviceName + BLEMIDI_CLIENT_NAME_SUBFIX; -#endif } - Serial.println(strDeviceName.c_str()); + static char array[16]; + memcpy(array, _Settings::name, 16); + strDeviceName = array; + DEBUGCLIENT(strDeviceName.c_str()); NimBLEDevice::init(strDeviceName); // To communicate between the 2 cores. // Core_0 runs here, core_1 runs the BLE stack - mRxQueue = xQueueCreate(256, sizeof(uint8_t)); // TODO Settings::MaxBufferSize + mRxQueue = xQueueCreate(_Settings::MaxBufferSize, sizeof(uint8_t)); - NimBLEDevice::setSecurityIOCap(BLEMIDI_CLIENT_SECURITY_CAP); // Attention, it may need a passkey - NimBLEDevice::setSecurityAuth(BLEMIDI_CLIENT_SECURITY_AUTH); + NimBLEDevice::setSecurityIOCap(_Settings::clientSecurityCapabilities); // Attention, it may need a passkey + NimBLEDevice::setSecurityAuth(_Settings::clientBond, _Settings::clientMITM, _Settings::clientPair); /** Optional: set the transmit power, default is 3db */ - NimBLEDevice::setPower(BLEMIDI_TX_PWR); /** +9db */ + NimBLEDevice::setPower(_Settings::clientTXPwr); /** +9db */ myAdvCB.enableConnection = true; scan(); @@ -449,37 +404,37 @@ bool BLEMIDI_Client_ESP32<_Settings>::begin(const char *deviceName, BLEMIDI_Tran template bool BLEMIDI_Client_ESP32<_Settings>::available(byte *pvBuffer) { - if (myAdvCB.enableConnection) + if (!myAdvCB.enableConnection) { - if (_client == nullptr || !_client->isConnected()) //Try to connect/reconnect + return false; + } + + // Try to connect/reconnect + if (_client == nullptr || !_client->isConnected()) + { + if (myAdvCB.doConnect) { - if (myAdvCB.doConnect) - { - myAdvCB.doConnect = false; - if (!connect()) - { - scan(); - } - } - else if (myAdvCB.scanDone) + myAdvCB.doConnect = false; + if (!connect()) { scan(); } } - // return 1 byte from the Queue - return xQueueReceive(mRxQueue, (void *)pvBuffer, 0); // return immediately when the queue is empty - } - else - { - return false; + else if (myAdvCB.scanDone) + { + scan(); + } } + + // return 1 byte from the Queue + return xQueueReceive(mRxQueue, (void *)pvBuffer, 0); // return immediately when the queue is empty } /** Notification receiving handler callback */ template void BLEMIDI_Client_ESP32<_Settings>::notifyCB(NimBLERemoteCharacteristic *pRemoteCharacteristic, uint8_t *pData, size_t length, bool isNotify) { - if (this->_characteristic == pRemoteCharacteristic) //Redundant protection + if (this->_characteristic == pRemoteCharacteristic) // Redundant protection { receive(pData, length); } @@ -500,7 +455,7 @@ void BLEMIDI_Client_ESP32<_Settings>::scan() pBLEScan->setWindow(500); pBLEScan->setActiveScan(true); - Serial.println("Scanning..."); + DEBUGCLIENT("Scanning..."); pBLEScan->start(1, scanEndedCB); } }; @@ -510,43 +465,45 @@ bool BLEMIDI_Client_ESP32<_Settings>::connect() { using namespace std::placeholders; //<- for bind funtion in callback notification -#ifndef BLEMIDI_FORCE_NEW_CONNECTION - /** Check if we have a client we should reuse first - * Special case when we already know this device - * This saves considerable time and power. - */ - - if (_client) + // Retry to connecto to last one + if (!_Settings::forceNewConnection) { - if (_client == NimBLEDevice::getClientByPeerAddress(myAdvCB.advDevice.getAddress())) + /** Check if we have a client we should reuse first + * Special case when we already know this device + * This saves considerable time and power. + */ + + if (_client) { - if (_client->connect(&myAdvCB.advDevice, false)) + if (_client == NimBLEDevice::getClientByPeerAddress(myAdvCB.advDevice.getAddress())) { - if (_characteristic->canNotify()) + if (_client->connect(&myAdvCB.advDevice, false)) { - if (_characteristic->subscribe(true, std::bind(&BLEMIDI_Client_ESP32::notifyCB, this, _1, _2, _3, _4))) + if (_characteristic->canNotify()) { - //Re-connection SUCCESS - return true; + if (_characteristic->subscribe(_Settings::notification, std::bind(&BLEMIDI_Client_ESP32::notifyCB, this, _1, _2, _3, _4), _Settings::response)) + { + // Re-connection SUCCESS + return true; + } } + /** Disconnect if subscribe failed */ + _client->disconnect(); } - /** Disconnect if subscribe failed */ - _client->disconnect(); + /* If any connection problem exits, delete previous client and try again in the next attemp as new client*/ + NimBLEDevice::deleteClient(_client); + _client = nullptr; + return false; } - /* If any connection problem exits, delete previous client and try again in the next attemp as new client*/ + /*If client does not match, delete previous client and create a new one*/ NimBLEDevice::deleteClient(_client); _client = nullptr; - return false; } - /*If client does not match, delete previous client and create a new one*/ - NimBLEDevice::deleteClient(_client); - _client = nullptr; } -#endif //BLEMIDI_FORCE_NEW_CONNECTION if (NimBLEDevice::getClientListSize() >= NIMBLE_MAX_CONNECTIONS) { - Serial.println("Max clients reached - no more connections available"); + DEBUGCLIENT("Max clients reached - no more connections available"); return false; } @@ -555,7 +512,7 @@ bool BLEMIDI_Client_ESP32<_Settings>::connect() _client->setClientCallbacks(new MyClientCallbacks<_Settings>(this), false); - _client->setConnectionParams(BLEMIDI_CLIENT_COMM_MIN_INTERVAL, BLEMIDI_CLIENT_COMM_MAX_INTERVAL, BLEMIDI_CLIENT_COMM_LATENCY, BLEMIDI_CLIENT_COMM_TIMEOUT); + _client->setConnectionParams(_Settings::commMinInterval, _Settings::commMaxInterval, _Settings::commLatency, _Settings::commTimeOut); /** Set how long we are willing to wait for the connection to complete (seconds), default is 30. */ _client->setConnectTimeout(15); @@ -565,28 +522,23 @@ bool BLEMIDI_Client_ESP32<_Settings>::connect() /** Created a client but failed to connect, don't need to keep it as it has no data */ NimBLEDevice::deleteClient(_client); _client = nullptr; - //Serial.println("Failed to connect, deleted client"); + DEBUGCLIENT("Failed to connect, deleted client"); return false; } if (!_client->isConnected()) { - //Serial.println("Failed to connect"); + DEBUGCLIENT("Failed to connect"); _client->disconnect(); NimBLEDevice::deleteClient(_client); _client = nullptr; return false; } - Serial.print("Connected to: "); - Serial.print(myAdvCB.advDevice.getName().c_str()); - Serial.print(" / "); - Serial.println(_client->getPeerAddress().toString().c_str()); + DEBUGCLIENT("Connected to: " + myAdvCB.advDevice.getName().c_str() + " / " + _client->getPeerAddress().toString().c_str()); - /* - Serial.print("RSSI: "); - Serial.println(_client->getRssi()); - */ + DEBUGCLIENT("RSSI: "); + DEBUGCLIENT(_client->getRssi()); /** Now we can read/write/subscribe the charateristics of the services we are interested in */ pSvc = _client->getService(SERVICE_UUID); @@ -598,16 +550,16 @@ bool BLEMIDI_Client_ESP32<_Settings>::connect() { if (_characteristic->canNotify()) { - if (_characteristic->subscribe(true, std::bind(&BLEMIDI_Client_ESP32::notifyCB, this, _1, _2, _3, _4))) + if (_characteristic->subscribe(_Settings::notification, std::bind(&BLEMIDI_Client_ESP32::notifyCB, this, _1, _2, _3, _4), _Settings::response)) { - //Connection SUCCESS + // Connection SUCCESS return true; } } } } - //If anything fails, disconnect and delete client + // If anything fails, disconnect and delete client _client->disconnect(); NimBLEDevice::deleteClient(_client); _client = nullptr; @@ -617,7 +569,7 @@ bool BLEMIDI_Client_ESP32<_Settings>::connect() /** Callback to process the results of the last scan or restart it */ void scanEndedCB(NimBLEScanResults results) { - // Serial.println("Scan Ended"); + // DEBUGCLIENT("Scan Ended"); } END_BLEMIDI_NAMESPACE @@ -625,7 +577,7 @@ END_BLEMIDI_NAMESPACE /*! \brief Create a custom instance for ESP32 named , and advertise it like "Prefix + + Subfix" It will try to connect to a specific server with equal name or addr than . If is "", it will connect to first midi server */ -#define BLEMIDI_CREATE_CUSTOM_INSTANCE(DeviceName, Name, _Settings) \ +#define BLEMIDI_CREATE_CUSTOM_INSTANCE(DeviceName, Name, _Settings) \ BLEMIDI_NAMESPACE::BLEMIDI_Transport, _Settings> BLE##Name(DeviceName); \ MIDI_NAMESPACE::MidiInterface, _Settings>, BLEMIDI_NAMESPACE::MySettings> Name((BLEMIDI_NAMESPACE::BLEMIDI_Transport, _Settings> &)BLE##Name); @@ -633,9 +585,9 @@ END_BLEMIDI_NAMESPACE It will try to connect to a specific server with equal name or addr than . If is "", it will connect to first midi server */ #define BLEMIDI_CREATE_INSTANCE(DeviceName, Name) \ - BLEMIDI_CREATE_CUSTOM_INSTANCE (DeviceName, Name, BLEMIDI_NAMESPACE::DefaultSettings) + BLEMIDI_CREATE_CUSTOM_INSTANCE(DeviceName, Name, BLEMIDI_NAMESPACE::DefaultSettingsClient) -/*! \brief Create a default instance for ESP32 named BLEMIDI-CLIENT. +/*! \brief Create a default instance for ESP32 named BLEMIDI-CLIENT. It will try to connect to first midi ble server found. */ #define BLEMIDI_CREATE_DEFAULT_INSTANCE() \