Control Surface  1.1.1
MIDI Control Surface library for Arduino
BLEMIDI.hpp
Go to the documentation of this file.
1 #pragma once
2 
3 #ifdef ARDUINO
4 
5 #ifndef ARDUINO_ARCH_ESP32
6 #error "MIDI over Bluetooth is only supported on ESP32 boards"
7 #endif
8 
9 #include <BLE2902.h>
10 #include <BLEDevice.h>
11 #include <BLEServer.h>
12 #include <BLEUtils.h>
13 
14 #include <AH/Error/Error.hpp>
15 
17 
18 // https://www.midi.org/specifications/item/bluetooth-le-midi
19 const char *SERVICE_UUID = "03b80e5a-ede8-4b33-a751-6ce34ec4c700";
20 const char *CHARACTERISTIC_UUID = "7772e5db-3868-4112-a1a9-f2669d106bf3";
21 
22 constexpr const char *BLE_MIDI_NAME = "Control Surface (BLE)";
23 
24 class BLEMIDI {
25  public:
27  // TODO
28  }
29 
33  void setServerCallbacks(BLEServerCallbacks *cb) {
34  if (pServer == nullptr) {
35  ERROR(F("Error: pServer has not been initialized"), 0x2020);
36  return;
37  }
38  pServer->setCallbacks(cb);
39  }
40 
44  void setCharacteristicsCallbacks(BLECharacteristicCallbacks *cb) {
45  if (pCharacteristic == nullptr) {
46  ERROR(F("Error: Characteristic has not been initialized"), 0x2021);
47  return;
48  }
49  pCharacteristic->setCallbacks(cb);
50  }
51 
52  void begin(BLEServerCallbacks *serverCallbacks,
53  BLECharacteristicCallbacks *midiCallbacks) {
54  DEBUGFN("Initializing BLE MIDI Interface");
55  if (BLEDevice::getInitialized()) {
56  ERROR(F("Error: BLEDevice is initialized already"), 0x2022);
57  return; // TODO: What to do here?
58  }
59 
60  // Initialize the BLE device
61  BLEDevice::init(BLE_MIDI_NAME);
62 
63  // Create the BLE server
64  pServer = BLEDevice::createServer();
65  setServerCallbacks(serverCallbacks);
66 
67  // Create the BLE service
68  BLEService *pService = pServer->createService(BLEUUID(SERVICE_UUID));
69 
70  // Create a BLE characteristic
71  pCharacteristic = pService->createCharacteristic(
72  BLEUUID(CHARACTERISTIC_UUID),
73  BLECharacteristic::PROPERTY_READ |
74  BLECharacteristic::PROPERTY_NOTIFY |
75  BLECharacteristic::PROPERTY_WRITE_NR);
76 
77  // Create a BLE descriptor
78  descriptor = new BLE2902();
79  pCharacteristic->addDescriptor(descriptor);
80  // descriptor.setNotifications(true);
81  setCharacteristicsCallbacks(midiCallbacks);
82 
83  // Start the service
84  pService->start();
85 
86  // Start advertising
87  BLEAdvertising *pAdvertising = pServer->getAdvertising();
88  pAdvertising->addServiceUUID(pService->getUUID());
89  pAdvertising->start();
90  }
91 
92  void notifyValue(uint8_t *data, size_t len) {
93  pCharacteristic->setValue(data, len);
94  pCharacteristic->notify();
95  }
96 
97  std::string getValue() { return pCharacteristic->getValue(); }
98 
99  private:
100  BLECharacteristic *pCharacteristic = nullptr;
101  BLEServer *pServer = nullptr;
102  BLE2902 *descriptor;
103 };
104 
106 
107 #else
108 
109 #include <Def/Def.hpp>
110 #include <gmock-wrapper.h>
111 #include <string>
112 
113 class BLECharacteristic {
114  public:
115  MOCK_METHOD0(getValue, std::string(void));
116  MOCK_METHOD2(setValue, void(uint8_t *data, size_t len));
117 };
118 
119 class BLECharacteristicCallbacks {
120  public:
121  virtual ~BLECharacteristicCallbacks() = default;
122  virtual void onRead(BLECharacteristic *pCharacteristic) {
123  (void)pCharacteristic;
124  }
125  virtual void onWrite(BLECharacteristic *pCharacteristic) {
126  (void)pCharacteristic;
127  }
128 };
129 
130 class BLEServer {};
131 
132 class BLEServerCallbacks {
133  public:
134  virtual ~BLEServerCallbacks() = default;
135  virtual void onConnect(BLEServer *pServer) { (void)pServer; }
136  virtual void onDisconnect(BLEServer *pServer) { (void)pServer; }
137 };
138 
140 
141 class BLEMIDI {
142  public:
143  MOCK_METHOD1(setServerCallbacks, void(BLEServerCallbacks *));
144  MOCK_METHOD1(setCharacteristicsCallbacks,
145  void(BLECharacteristicCallbacks *));
146  MOCK_METHOD2(begin,
147  void(BLEServerCallbacks *, BLECharacteristicCallbacks *));
148  MOCK_METHOD2(notifyValue, void(uint8_t *data, size_t len));
149  MOCK_METHOD0(getValue, std::string(void));
150 };
151 
153 
154 #endif
BLEMIDI::begin
void begin(BLEServerCallbacks *serverCallbacks, BLECharacteristicCallbacks *midiCallbacks)
Definition: BLEMIDI.hpp:52
BLEMIDI::setCharacteristicsCallbacks
void setCharacteristicsCallbacks(BLECharacteristicCallbacks *cb)
Definition: BLEMIDI.hpp:44
BLEMIDI::descriptor
BLE2902 * descriptor
Definition: BLEMIDI.hpp:102
BLEMIDI::pCharacteristic
BLECharacteristic * pCharacteristic
Definition: BLEMIDI.hpp:100
Error.hpp
Def.hpp
BEGIN_CS_NAMESPACE
#define BEGIN_CS_NAMESPACE
Definition: Settings/NamespaceSettings.hpp:9
END_CS_NAMESPACE
#define END_CS_NAMESPACE
Definition: Settings/NamespaceSettings.hpp:10
SERVICE_UUID
const char * SERVICE_UUID
Definition: BLEMIDI.hpp:19
ERROR
#define ERROR(msg, errc)
Print the error message and error code, and stop the execution if FATAL_ERRORS are enabled.
Definition: Error.hpp:42
BLEMIDI::notifyValue
void notifyValue(uint8_t *data, size_t len)
Definition: BLEMIDI.hpp:92
CHARACTERISTIC_UUID
const char * CHARACTERISTIC_UUID
Definition: BLEMIDI.hpp:20
BLEMIDI
Definition: BLEMIDI.hpp:24
BLEMIDI::setServerCallbacks
void setServerCallbacks(BLEServerCallbacks *cb)
Definition: BLEMIDI.hpp:33
MIDI_Notes::F
constexpr int8_t F
Definition: Notes.hpp:23
DEBUGFN
#define DEBUGFN(x)
Print an expression and its function (function name and line number) to the debug output if debugging...
Definition: Debug.hpp:93
BLEMIDI::getValue
std::string getValue()
Definition: BLEMIDI.hpp:97
BLE_MIDI_NAME
constexpr const char * BLE_MIDI_NAME
Definition: BLEMIDI.hpp:22
BLEMIDI::pServer
BLEServer * pServer
Definition: BLEMIDI.hpp:101
BLEMIDI::~BLEMIDI
~BLEMIDI()
Definition: BLEMIDI.hpp:26