This commit is contained in:
RobertoHE 2023-01-08 12:10:07 +00:00 committed by GitHub
commit e78981ae98
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 343 additions and 312 deletions

View File

@ -6,15 +6,16 @@ shopt -s globstar
# Make sure we are inside the github workspace # Make sure we are inside the github workspace
cd $GITHUB_WORKSPACE cd $GITHUB_WORKSPACE
# Create directories # Create directories
mkdir $HOME/Arduino mkdir $HOME/Arduino -p
mkdir $HOME/Arduino/libraries mkdir $HOME/Arduino/libraries -p
# Install Arduino IDE # Install Arduino IDE
export PATH=$PATH:$GITHUB_WORKSPACE/bin export PATH=$PATH:$GITHUB_WORKSPACE/bin
curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh | sh curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh | sh
arduino-cli config init arduino-cli config init
arduino-cli config set library.enable_unsafe_install true 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://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 arduino-cli core update-index
# Install Arduino AVR core # Install Arduino AVR core
@ -24,13 +25,13 @@ arduino-cli core install arduino:samd
arduino-cli core install esp32:esp32 arduino-cli core install esp32:esp32
# List the boards # List the boards
arduino-cli board list arduino-cli board listall
# Link Arduino library # Link Arduino library
ln -s $GITHUB_WORKSPACE $HOME/Arduino/libraries/CI_Test_Library ln -s $GITHUB_WORKSPACE $HOME/Arduino/libraries/CI_Test_Library
arduino-cli lib install "MIDI library" arduino-cli lib install "MIDI library"
arduino-cli lib install ArduinoBLE #arduino-cli lib install ArduinoBLE
arduino-cli lib install NimBLE-Arduino arduino-cli lib install NimBLE-Arduino
# Compile all *.ino files for the Arduino Uno # 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 # arduino-cli compile -b arduino:esp8266:??? $f
# done # done
dR=$(pwd)
# Compile all *.ino files for the Arduino Uno # Compile all *.ino files for the Arduino Uno
for f in **/*.ino ; do 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 done

View File

@ -1,13 +1,67 @@
#include <BLEMIDI_Transport.h> #include <BLEMIDI_Transport.h>
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 { 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; static const size_t MaxBufferSize = 16;
}; };
#include <hardware/BLEMIDI_ESP32_NimBLE.h> #include <hardware/BLEMIDI_ESP32_NimBLE.h>
//#include <hardware/BLEMIDI_ESP32.h> //#include <hardware/BLEMIDI_ESP32.h>
//#include <hardware/BLEMIDI_ArduinoBLE.h> //#include <hardware/BLEMIDI_ArduinoBLE.h>
#ifndef LED_BUILTIN
#define LED_BUILTIN 2
#endif
BLEMIDI_CREATE_CUSTOM_INSTANCE("Esp32-NimBLE-MIDI", MIDI, CustomBufferSizeSettings); BLEMIDI_CREATE_CUSTOM_INSTANCE("Esp32-NimBLE-MIDI", MIDI, CustomBufferSizeSettings);
unsigned long t0 = millis(); unsigned long t0 = millis();
@ -61,4 +115,4 @@ void loop()
MIDI.sendNoteOn (60, 100, 1); // note 60, velocity 100 on channel 1 MIDI.sendNoteOn (60, 100, 1); // note 60, velocity 100 on channel 1
} }
} }

View File

@ -4,6 +4,10 @@
#include <hardware/BLEMIDI_ESP32.h> #include <hardware/BLEMIDI_ESP32.h>
//#include <hardware/BLEMIDI_ArduinoBLE.h> //#include <hardware/BLEMIDI_ArduinoBLE.h>
#ifndef LED_BUILTIN
#define LED_BUILTIN 2
#endif
BLEMIDI_CREATE_DEFAULT_INSTANCE() BLEMIDI_CREATE_DEFAULT_INSTANCE()
unsigned long t0 = millis(); unsigned long t0 = millis();

View File

@ -14,10 +14,10 @@
* the name of the server or the BLE address of the server. If you want to connect * 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 (""). * 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 * FOR ADVANCED USERS: Other advanced BLE configurations can be changed with a struct that heritate
* #defines in the head of the file (IMPORTANT: Only the first user defines must be modified). These configurations * from BLEMIDI_NAMESPACE::DefaultSettingsClient. These configurations are related to
* are related to security (password, pairing and securityCallback()), communication params, the device name * security (password, pairing and securityCallback()), communication params, the device name
* and other stuffs. Modify defines at your own risk. * and other stuffs. Modify those settings at your own risk.
* *
* *
* *
@ -28,21 +28,26 @@
#include <Arduino.h> #include <Arduino.h>
#include <BLEMIDI_Transport.h> #include <BLEMIDI_Transport.h>
struct CustomBufferSizeSettings : public BLEMIDI_NAMESPACE::DefaultSettings {
static const size_t MaxBufferSize = 16;
};
#include <hardware/BLEMIDI_Client_ESP32.h> #include <hardware/BLEMIDI_Client_ESP32.h>
//#include <hardware/BLEMIDI_ESP32_NimBLE.h> //#include <hardware/BLEMIDI_ESP32_NimBLE.h>
//#include <hardware/BLEMIDI_ESP32.h> //#include <hardware/BLEMIDI_ESP32.h>
//#include <hardware/BLEMIDI_ArduinoBLE.h> //#include <hardware/BLEMIDI_ArduinoBLE.h>
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 //See DefaultSettingsClient in hardware/BLEMIDI_Client_ESP32.h for more configurable settings
//BLEMIDI_CREATE_INSTANCE("f2:c1:d9:36:e7:6b",MIDI) //Connect to a specific BLE address server // If you do not redefine a parameter, it will use the default value for these parameter
//BLEMIDI_CREATE_INSTANCE("MyBLEserver",MIDI) //Connect to a specific name server 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 #ifndef LED_BUILTIN
#define LED_BUILTIN 2 //modify for match with yout board #define LED_BUILTIN 2 //modify for match with yout board

View File

@ -4,6 +4,10 @@
#include <hardware/BLEMIDI_ESP32.h> #include <hardware/BLEMIDI_ESP32.h>
//#include <hardware/BLEMIDI_ArduinoBLE.h> //#include <hardware/BLEMIDI_ArduinoBLE.h>
#ifndef LED_BUILTIN
#define LED_BUILTIN 2
#endif
BLEMIDI_CREATE_INSTANCE("CustomName", MIDI) BLEMIDI_CREATE_INSTANCE("CustomName", MIDI)
bool isConnected = false; bool isConnected = false;

View File

@ -4,6 +4,10 @@
//#include <hardware/BLEMIDI_ESP32.h> //#include <hardware/BLEMIDI_ESP32.h>
//#include <hardware/BLEMIDI_ArduinoBLE.h> //#include <hardware/BLEMIDI_ArduinoBLE.h>
#ifndef LED_BUILTIN
#define LED_BUILTIN 2
#endif
byte sysex4[] = { 0xF0, 0x43, 0x20, 0xF7 }; byte sysex4[] = { 0xF0, 0x43, 0x20, 0xF7 };
byte sysex5[] = { 0xF0, 0x43, 0x20, 0x7E, 0xF7 }; byte sysex5[] = { 0xF0, 0x43, 0x20, 0x7E, 0xF7 };
byte sysex6[] = { 0xF0, 0x43, 0x20, 0x7E, 0x4C, 0xF7 }; byte sysex6[] = { 0xF0, 0x43, 0x20, 0x7E, 0x4C, 0xF7 };

View File

@ -256,10 +256,10 @@ public:
byte headerByte = buffer[lPtr++]; byte headerByte = buffer[lPtr++];
auto timestampHigh = 0x3f & headerByte; auto timestampHigh = 0x3f & headerByte;
timestampHigh = timestampHigh; // <-- This line is for avoid Warning message due it is unused
byte timestampByte = buffer[lPtr++]; byte timestampByte = buffer[lPtr++];
uint16_t timestamp = 0; uint16_t timestamp = 0;
timestamp = timestamp; // <-- This line is for avoid Warning message due it is unused
bool sysExContinuation = false; bool sysExContinuation = false;
bool runningStatusContinuation = false; bool runningStatusContinuation = false;

View File

@ -1,180 +1,143 @@
#pragma once #pragma once
/* //#define MIDIBLECLIENTVERBOSE
#############################################
########## USER DEFINES BEGINNING ###########
####### Modify only these parameters ########
#############################################
*/
/* #ifdef MIDIBLECLIENTVERBOSE
##### BLE DEVICE NAME ##### #define DEBUGCLIENT(_text_) Serial.println("DbgBC: " + (String)_text_);
*/ #else
#define DEBUGCLIENT(_text_) ;
/** #endif
* 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 + <NameServer/addrServer> + BLEMIDI_CLIENT_NAME_SUBFIX
*
* example:
* BLEMIDI_CLIENT_NAME_PREFIX "Client-"
* <NameServer/addrServer> "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 ###############
#############################################
*/
// Headers for ESP32 nimBLE // Headers for ESP32 nimBLE
#include <NimBLEDevice.h> #include <NimBLEDevice.h>
BEGIN_BLEMIDI_NAMESPACE BEGIN_BLEMIDI_NAMESPACE
#ifdef BLEMIDI_CLIENT_BOND using PasskeyRequestCallback = uint32_t (*)(void);
#define BLEMIDI_CLIENT_BOND_DUMMY BLE_SM_PAIR_AUTHREQ_BOND
#else
#define BLEMIDI_CLIENT_BOND_DUMMY 0x00
#endif
#ifdef BLEMIDI_CLIENT_MITM static uint32_t defautlPasskeyRequest()
#define BLEMIDI_CLIENT_MITM_DUMMY BLE_SM_PAIR_AUTHREQ_MITM {
#else // FILL WITH YOUR CUSTOM AUTH METHOD CODE or PASSKEY
#define BLEMIDI_CLIENT_MITM_DUMMY 0x00 // FOR EXAMPLE:
#endif uint32_t passkey = 123456;
#ifdef BLEMIDI_CLIENT_PAIR // Serial.println("Client Passkey Request");
#define BLEMIDI_CLIENT_PAIR_DUMMY BLE_SM_PAIR_AUTHREQ_SC
#else
#define BLEMIDI_CLIENT_PAIR_DUMMY 0x00
#endif
/** 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 * bonding
* man in the middle protection * man in the middle protection
* pair. secure connections * pair. secure connections
* *
* More info in nimBLE lib * 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 */ /** Define a class to handle the callbacks when advertisments are received */
template <class _Settings>
class AdvertisedDeviceCallbacks : public NimBLEAdvertisedDeviceCallbacks class AdvertisedDeviceCallbacks : public NimBLEAdvertisedDeviceCallbacks
{ {
public: public:
@ -188,32 +151,34 @@ public:
protected: protected:
void onResult(NimBLEAdvertisedDevice *advertisedDevice) void onResult(NimBLEAdvertisedDevice *advertisedDevice)
{ {
if (enableConnection) //not begin() or end() if (!enableConnection) // not begin() or end()
{ {
Serial.print("Advertised Device found: "); return;
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;
}
} }
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; BLEAdvertising *_advertising = nullptr;
BLERemoteCharacteristic *_characteristic = nullptr; BLERemoteCharacteristic *_characteristic = nullptr;
BLERemoteService *pSvc = 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<class BLEMIDI_Client_ESP32<_Settings>, _Settings> *_bleMidiTransport = nullptr; BLEMIDI_Transport<class BLEMIDI_Client_ESP32<_Settings>, _Settings> *_bleMidiTransport = nullptr;
bool specificTarget = false; bool specificTarget = false;
// TODO: somehow the forward declaration of the template class is not accepted by the compiler AdvertisedDeviceCallbacks myAdvCB;
// template <class> friend MyClientCallbacks;
AdvertisedDeviceCallbacks<_Settings> myAdvCB;
protected: protected:
QueueHandle_t mRxQueue; QueueHandle_t mRxQueue;
@ -255,9 +217,11 @@ public:
myAdvCB.enableConnection = false; myAdvCB.enableConnection = false;
xQueueReset(mRxQueue); xQueueReset(mRxQueue);
_client->disconnect(); _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) void write(uint8_t *data, uint8_t length)
@ -300,7 +264,7 @@ protected:
void scan(); void scan();
bool connect(); bool connect();
public: // TODO: somehow the forward declaration of the template class is not accepted by the compiler public:
void connected() void connected()
{ {
if (_bleMidiTransport->_connectedCallback) if (_bleMidiTransport->_connectedCallback)
@ -331,58 +295,56 @@ protected:
uint32_t onPassKeyRequest() uint32_t onPassKeyRequest()
{ {
return userOnPassKeyRequest(); // if (nullptr != _Settings::userOnPassKeyRequest)
return _Settings::userOnPassKeyRequest();
// return 0;
}; };
void onConnect(BLEClient*) void onConnect(BLEClient *pClient)
{ {
//Serial.println("##Connected##"); DEBUGCLIENT("##Connected##");
//pClient->updateConnParams(BLEMIDI_CLIENT_COMM_MIN_INTERVAL, BLEMIDI_CLIENT_COMM_MAX_INTERVAL, BLEMIDI_CLIENT_COMM_LATENCY, BLEMIDI_CLIENT_COMM_TIMEOUT); // pClient->updateConnParams(_Settings::commMinInterval, _Settings::commMaxInterval, _Settings::commLatency, _Settings::commTimeOut);
vTaskDelay(1); vTaskDelay(1);
if (_bluetoothEsp32) if (_bluetoothEsp32)
_bluetoothEsp32->connected(); _bluetoothEsp32->connected();
}; };
void onDisconnect(BLEClient*) void onDisconnect(BLEClient *pClient)
{ {
//Serial.print(pClient->getPeerAddress().toString().c_str()); DEBUGCLIENT(pClient->getPeerAddress().toString().c_str());
//Serial.println(" Disconnected - Starting scan"); DEBUGCLIENT(" Disconnected - Starting scan");
if (_bluetoothEsp32) if (_bluetoothEsp32)
{ {
_bluetoothEsp32->disconnected(); _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 if (_Settings::forceNewConnection)
// Renew Client {
NimBLEDevice::deleteClient(pClient); // Renew Client
NimBLEDevice::createClient(); NimBLEDevice::deleteClient(pClient);
pClient = nullptr; pClient = nullptr;
#endif // BLEMIDI_FORCE_NEW_CONNECTION }
//Try reconnection or search a new one // Try reconnection or search a new one
NimBLEDevice::getScan()->start(1, scanEndedCB); NimBLEDevice::getScan()->start(1, scanEndedCB);
} }
bool onConnParamsUpdateRequest(NimBLEClient *pClient, const ble_gap_upd_params *params) 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 */ { /** 1.25ms units */
return false; return false;
} }
else if (params->itvl_max > BLEMIDI_CLIENT_COMM_MAX_INTERVAL) else if (params->itvl_max > _Settings::commMaxInterval)
{ /** 1.25ms units */ { /** 1.25ms units */
return false; return false;
} }
else if (params->latency > BLEMIDI_CLIENT_COMM_LATENCY) else if (params->latency > _Settings::commLatency)
{ /** Number of intervals allowed to skip */ { /** Number of intervals allowed to skip */
return false; return false;
} }
else if (params->supervision_timeout > BLEMIDI_CLIENT_COMM_TIMEOUT) else if (params->supervision_timeout > _Settings::commMinInterval)
{ /** 10ms units */ { /** 10ms units */
return false; return false;
} }
@ -404,41 +366,34 @@ bool BLEMIDI_Client_ESP32<_Settings>::begin(const char *deviceName, BLEMIDI_Tran
_bleMidiTransport = bleMidiTransport; _bleMidiTransport = bleMidiTransport;
std::string strDeviceName(deviceName); 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.specificTarget = false;
myAdvCB.nameTarget = ""; 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.specificTarget = true;
myAdvCB.nameTarget = strDeviceName; 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); NimBLEDevice::init(strDeviceName);
// To communicate between the 2 cores. // To communicate between the 2 cores.
// Core_0 runs here, core_1 runs the BLE stack // 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::setSecurityIOCap(_Settings::clientSecurityCapabilities); // Attention, it may need a passkey
NimBLEDevice::setSecurityAuth(BLEMIDI_CLIENT_SECURITY_AUTH); NimBLEDevice::setSecurityAuth(_Settings::clientBond, _Settings::clientMITM, _Settings::clientPair);
/** Optional: set the transmit power, default is 3db */ /** Optional: set the transmit power, default is 3db */
NimBLEDevice::setPower(BLEMIDI_TX_PWR); /** +9db */ NimBLEDevice::setPower(_Settings::clientTXPwr); /** +9db */
myAdvCB.enableConnection = true; myAdvCB.enableConnection = true;
scan(); scan();
@ -449,37 +404,37 @@ bool BLEMIDI_Client_ESP32<_Settings>::begin(const char *deviceName, BLEMIDI_Tran
template <class _Settings> template <class _Settings>
bool BLEMIDI_Client_ESP32<_Settings>::available(byte *pvBuffer) 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())
myAdvCB.doConnect = false;
if (!connect())
{
scan();
}
}
else if (myAdvCB.scanDone)
{ {
scan(); scan();
} }
} }
// return 1 byte from the Queue else if (myAdvCB.scanDone)
return xQueueReceive(mRxQueue, (void *)pvBuffer, 0); // return immediately when the queue is empty {
} scan();
else }
{
return false;
} }
// return 1 byte from the Queue
return xQueueReceive(mRxQueue, (void *)pvBuffer, 0); // return immediately when the queue is empty
} }
/** Notification receiving handler callback */ /** Notification receiving handler callback */
template <class _Settings> template <class _Settings>
void BLEMIDI_Client_ESP32<_Settings>::notifyCB(NimBLERemoteCharacteristic *pRemoteCharacteristic, uint8_t *pData, size_t length, bool isNotify) 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); receive(pData, length);
} }
@ -500,7 +455,7 @@ void BLEMIDI_Client_ESP32<_Settings>::scan()
pBLEScan->setWindow(500); pBLEScan->setWindow(500);
pBLEScan->setActiveScan(true); pBLEScan->setActiveScan(true);
Serial.println("Scanning..."); DEBUGCLIENT("Scanning...");
pBLEScan->start(1, scanEndedCB); pBLEScan->start(1, scanEndedCB);
} }
}; };
@ -510,43 +465,45 @@ bool BLEMIDI_Client_ESP32<_Settings>::connect()
{ {
using namespace std::placeholders; //<- for bind funtion in callback notification using namespace std::placeholders; //<- for bind funtion in callback notification
#ifndef BLEMIDI_FORCE_NEW_CONNECTION // Retry to connecto to last one
/** Check if we have a client we should reuse first if (!_Settings::forceNewConnection)
* Special case when we already know this device
* This saves considerable time and power.
*/
if (_client)
{ {
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 if (_characteristic->subscribe(_Settings::notification, std::bind(&BLEMIDI_Client_ESP32::notifyCB, this, _1, _2, _3, _4), _Settings::response))
return true; {
// Re-connection SUCCESS
return true;
}
} }
/** Disconnect if subscribe failed */
_client->disconnect();
} }
/** Disconnect if subscribe failed */ /* If any connection problem exits, delete previous client and try again in the next attemp as new client*/
_client->disconnect(); 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); NimBLEDevice::deleteClient(_client);
_client = nullptr; _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) 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; return false;
} }
@ -555,7 +512,7 @@ bool BLEMIDI_Client_ESP32<_Settings>::connect()
_client->setClientCallbacks(new MyClientCallbacks<_Settings>(this), false); _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. */ /** Set how long we are willing to wait for the connection to complete (seconds), default is 30. */
_client->setConnectTimeout(15); _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 */ /** Created a client but failed to connect, don't need to keep it as it has no data */
NimBLEDevice::deleteClient(_client); NimBLEDevice::deleteClient(_client);
_client = nullptr; _client = nullptr;
//Serial.println("Failed to connect, deleted client"); DEBUGCLIENT("Failed to connect, deleted client");
return false; return false;
} }
if (!_client->isConnected()) if (!_client->isConnected())
{ {
//Serial.println("Failed to connect"); DEBUGCLIENT("Failed to connect");
_client->disconnect(); _client->disconnect();
NimBLEDevice::deleteClient(_client); NimBLEDevice::deleteClient(_client);
_client = nullptr; _client = nullptr;
return false; return false;
} }
Serial.print("Connected to: "); DEBUGCLIENT("Connected to: " + myAdvCB.advDevice.getName().c_str() + " / " + _client->getPeerAddress().toString().c_str());
Serial.print(myAdvCB.advDevice.getName().c_str());
Serial.print(" / ");
Serial.println(_client->getPeerAddress().toString().c_str());
/* DEBUGCLIENT("RSSI: ");
Serial.print("RSSI: "); DEBUGCLIENT(_client->getRssi());
Serial.println(_client->getRssi());
*/
/** Now we can read/write/subscribe the charateristics of the services we are interested in */ /** Now we can read/write/subscribe the charateristics of the services we are interested in */
pSvc = _client->getService(SERVICE_UUID); pSvc = _client->getService(SERVICE_UUID);
@ -598,16 +550,16 @@ bool BLEMIDI_Client_ESP32<_Settings>::connect()
{ {
if (_characteristic->canNotify()) 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; return true;
} }
} }
} }
} }
//If anything fails, disconnect and delete client // If anything fails, disconnect and delete client
_client->disconnect(); _client->disconnect();
NimBLEDevice::deleteClient(_client); NimBLEDevice::deleteClient(_client);
_client = nullptr; _client = nullptr;
@ -617,7 +569,7 @@ bool BLEMIDI_Client_ESP32<_Settings>::connect()
/** Callback to process the results of the last scan or restart it */ /** Callback to process the results of the last scan or restart it */
void scanEndedCB(NimBLEScanResults results) void scanEndedCB(NimBLEScanResults results)
{ {
// Serial.println("Scan Ended"); // DEBUGCLIENT("Scan Ended");
} }
END_BLEMIDI_NAMESPACE END_BLEMIDI_NAMESPACE
@ -625,7 +577,7 @@ END_BLEMIDI_NAMESPACE
/*! \brief Create a custom instance for ESP32 named <DeviceName>, and advertise it like "Prefix + <DeviceName> + Subfix" /*! \brief Create a custom instance for ESP32 named <DeviceName>, and advertise it like "Prefix + <DeviceName> + Subfix"
It will try to connect to a specific server with equal name or addr than <DeviceName>. If <DeviceName> is "", it will connect to first midi server It will try to connect to a specific server with equal name or addr than <DeviceName>. If <DeviceName> 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<BLEMIDI_NAMESPACE::BLEMIDI_Client_ESP32<_Settings>, _Settings> BLE##Name(DeviceName); \ BLEMIDI_NAMESPACE::BLEMIDI_Transport<BLEMIDI_NAMESPACE::BLEMIDI_Client_ESP32<_Settings>, _Settings> BLE##Name(DeviceName); \
MIDI_NAMESPACE::MidiInterface<BLEMIDI_NAMESPACE::BLEMIDI_Transport<BLEMIDI_NAMESPACE::BLEMIDI_Client_ESP32<_Settings>, _Settings>, BLEMIDI_NAMESPACE::MySettings> Name((BLEMIDI_NAMESPACE::BLEMIDI_Transport<BLEMIDI_NAMESPACE::BLEMIDI_Client_ESP32<_Settings>, _Settings> &)BLE##Name); MIDI_NAMESPACE::MidiInterface<BLEMIDI_NAMESPACE::BLEMIDI_Transport<BLEMIDI_NAMESPACE::BLEMIDI_Client_ESP32<_Settings>, _Settings>, BLEMIDI_NAMESPACE::MySettings> Name((BLEMIDI_NAMESPACE::BLEMIDI_Transport<BLEMIDI_NAMESPACE::BLEMIDI_Client_ESP32<_Settings>, _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 <DeviceName>. If <DeviceName> is "", it will connect to first midi server It will try to connect to a specific server with equal name or addr than <DeviceName>. If <DeviceName> is "", it will connect to first midi server
*/ */
#define BLEMIDI_CREATE_INSTANCE(DeviceName, Name) \ #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. It will try to connect to first midi ble server found.
*/ */
#define BLEMIDI_CREATE_DEFAULT_INSTANCE() \ #define BLEMIDI_CREATE_DEFAULT_INSTANCE() \