arduino-audio-tools
AudioBLEClient.h
1 #pragma once
2 
3 #include "AudioBLEStream.h"
4 #include "ConstantsArduino.h"
5 #include <ArduinoBLE.h>
6 
7 namespace audio_tools {
8 
9 class AudioBLEClient;
10 static AudioBLEClient *selfAudioBLEClient = nullptr;
11 
21 public:
22  AudioBLEClient(int mtu = BLE_MTU) : AudioBLEStream(mtu) {
23  selfAudioBLEClient = this;
24  max_transfer_size = mtu;
25  }
26 
28  bool begin(const char *localName, int seconds) {
29  TRACEI();
30  // Init BLE device
31  BLE.begin();
32  BLE.setLocalName(localName);
33  BLE.scanForUuid(BLE_AUDIO_SERVICE_UUID);
34  return true;
35  }
36 
37  void end() override {
38  TRACEI();
39  flush();
40  BLE.end();
41  }
42 
43  size_t readBytes(uint8_t *data, size_t len) override {
44  TRACED();
45  if (!setupBLEClient()) {
46  return 0;
47  }
48 
49  if (!ch01_char.canRead())
50  return 0;
51 
52  return ch01_char.readValue(data, len);
53  }
54 
55  int available() override { return BLE_MTU - BLE_MTU_OVERHEAD; }
56 
57  size_t write(const uint8_t *data, size_t len) override {
58  TRACED();
59  if (!setupBLEClient()) {
60  return 0;
61  }
62 
63  if (!ch02_char.canWrite()) {
64  return 0;
65  }
66 
67  if (is_framed) {
68  writeChannel2Characteristic(data, len);
69  delay(1);
70  } else {
71  // send only data with max mtu
72  for (int j = 0; j < len; j++) {
73  write_buffer.write(data[j]);
74  if (write_buffer.isFull()) {
75  writeChannel2Characteristic(write_buffer.data(),
76  write_buffer.available());
77  write_buffer.reset();
78  }
79  }
80  }
81  return len;
82  }
83 
84  int availableForWrite() override {
85  return is_framed ? (BLE_MTU - BLE_MTU_OVERHEAD) : DEFAULT_BUFFER_SIZE;
86  }
87 
88  bool connected() override { return setupBLEClient(); }
89 
90  void setWriteThrottle(int ms) { write_throttle = ms; }
91 
92  void setConfirmWrite(bool flag) { write_confirmation_flag = flag; }
93 
94 protected:
95  BLEDevice peripheral;
96  BLECharacteristic ch01_char;
97  BLECharacteristic ch02_char;
98  BLECharacteristic info_char;
99  SingleBuffer<uint8_t> write_buffer{0};
100  int write_throttle = 0;
101  bool write_confirmation_flag = false;
102 
103  void writeAudioInfoCharacteristic(AudioInfo info) override {
104  TRACEI();
105  // send update via BLE
106  info_char.writeValue((uint8_t *)&info, sizeof(AudioInfo));
107  }
108 
109  void writeChannel2Characteristic(const uint8_t *data, size_t len) {
110  if (ch02_char.canWrite()) {
111  ch02_char.writeValue((uint8_t *)data, len, write_confirmation_flag);
112  delay(write_throttle);
113  }
114  }
115 
116  bool readAudioInfoCharacteristic() {
117  if (!info_char.canRead())
118  return false;
119  const uint8_t *str = info_char.value();
120  int len = info_char.valueLength();
121  if (len > 0) {
122  setAudioInfo(str, len);
123  return true;
124  }
125  return false;
126  }
127 
128  static void onInfoUpdated(BLEDevice central,
129  BLECharacteristic characteristic) {
130  selfAudioBLEClient->setAudioInfo(characteristic.value(),
131  characteristic.valueLength());
132  }
133 
134  bool setupBLEClient() {
135  // if we are already connected there is nothing to do
136  if (peripheral.connected()) {
137  return true;
138  }
139 
140  TRACEI();
141 
142  // setup buffer
143  if (write_buffer.size() == 0) {
144  write_buffer.resize(getMTU() - BLE_MTU_OVERHEAD);
145  }
146 
147  peripheral = BLE.available();
148  if (!peripheral) {
149  return false;
150  }
151 
152  BLE.stopScan();
153 
154  if (!peripheral.connect()) {
155  return false;
156  }
157 
158  if (peripheral.discoverAttributes()) {
159  LOGI("Attributes discovered");
160  } else {
161  LOGE("Attribute discovery failed!");
162  peripheral.disconnect();
163  return false;
164  }
165 
166  ch01_char = peripheral.characteristic(BLE_CH1_UUID);
167  if (!ch01_char) {
168  peripheral.disconnect();
169  return false;
170  }
171 
172  ch02_char = peripheral.characteristic(BLE_CH2_UUID);
173  if (!ch02_char) {
174  peripheral.disconnect();
175  return false;
176  }
177 
178  if (is_audio_info_active) {
179  info_char = peripheral.characteristic(BLE_INFO_UUID);
180  info_char.setEventHandler(BLEUpdated, onInfoUpdated);
181  }
182 
183  return true;
184  }
185 };
186 
187 } // namespace audio_tools
A simple BLE client that implements the serial protocol, so that it can be used to send and recevie a...
Definition: AudioBLEClient.h:20
bool begin(const char *localName, int seconds)
starts a BLE client
Definition: AudioBLEClient.h:28
Transmit and receive data via BLE using a Serial API. The following additional experimental features ...
Definition: AudioBLEStream.h:19
void setAudioInfo(AudioInfo info)
Defines the input AudioInfo.
Definition: AudioBLEStream.h:27
T * data()
Provides address of actual data.
Definition: Buffers.h:252
bool write(T sample) override
write add an entry to the buffer
Definition: Buffers.h:194
int available() override
provides the number of entries that are available to read
Definition: Buffers.h:219
bool isFull() override
checks if the buffer is full
Definition: Buffers.h:226
void reset() override
clears the buffer
Definition: Buffers.h:254
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition: AudioConfig.h:821