arduino-audio-tools
All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends Modules Pages
AudioBLEClient.h
1#pragma once
2
3#include "AudioBLEStream.h"
4#include "ConstantsArduino.h"
5#include <ArduinoBLE.h>
6
7namespace audio_tools {
8
9class AudioBLEClient;
10static AudioBLEClient *selfAudioBLEClient = nullptr;
11
21public:
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
94protected:
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
bool write(T sample) override
write add an entry to the buffer
Definition Buffers.h:200
int available() override
provides the number of entries that are available to read
Definition Buffers.h:227
bool isFull() override
checks if the buffer is full
Definition Buffers.h:234
T * data()
Provides address of actual data.
Definition Buffers.h:261
void reset() override
clears the buffer
Definition Buffers.h:263
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition AudioCodecsBase.h:10