Skip to content

Commit 0d69ece

Browse files
committed
initial implementation of the bluetooth proxy for divoom devices
1 parent 0ccfac4 commit 0d69ece

24 files changed

+907
-0
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.pio
2+
.vs/**
3+
.vscode/**
4+
config_local.h

platformio.ini

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
; PlatformIO Project Configuration File
2+
;
3+
; Build options: build flags, source filter
4+
; Upload options: custom upload port, speed and extra flags
5+
; Library options: dependencies, extra library storages
6+
; Advanced options: extra scripting
7+
;
8+
; Please visit documentation for the other options and examples
9+
; https://docs.platformio.org/page/projectconf.html
10+
11+
[env:esp32dev]
12+
platform = espressif32
13+
board = esp32dev
14+
board_build.partitions = min_spiffs.csv
15+
framework = arduino
16+
build_type = release
17+
lib_deps = AsyncTCP@>=1.1.1
18+
build_unflags =
19+
-std=gnu++11
20+
build_flags =
21+
-std=gnu++17
22+
-DCONFIG_WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST=1
23+
-DCONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST=1
24+
monitor_speed = 9600

src/config.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#ifndef _CONFIG_H
2+
#define _CONFIG_H
3+
4+
#define BLUETOOTH_NAME "ESP32-Divoom"
5+
6+
#define WIFI_NAME "ESP32-Divoom"
7+
8+
#define WIFISSID1 ""
9+
#define WIFIPASS1 ""
10+
11+
#define WIFISSID2 ""
12+
#define WIFIPASS2 ""
13+
14+
#define TCP_PORT 7777
15+
#define TCP_MAX 5
16+
#endif
17+
18+
#if __has_include("config_local.h")
19+
# include "config_local.h"
20+
#endif

src/divoom/divoom.cpp

Whitespace-only changes.

src/divoom/divoom.h

Whitespace-only changes.

src/hardware/bluetoothctl.cpp

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
2+
#include "bluetoothctl.h"
3+
4+
#include "util.h"
5+
#include "input/base.h"
6+
#include "output/base.h"
7+
8+
/**
9+
* setup functionality
10+
*/
11+
void BluetoothHandler::setup(void) {
12+
serialBT.begin(BLUETOOTH_NAME, true);
13+
serialBT.register_callback(received);
14+
serialBT.discoverAsync(discovered, 500);
15+
}
16+
17+
/**
18+
* loop functionality
19+
*/
20+
void BluetoothHandler::loop(void) {
21+
if (getElapsed(timer) > 15000) {
22+
timer = millis();
23+
24+
check();
25+
}
26+
}
27+
28+
/**
29+
* checks connection and scanning state and keeps background tasks up
30+
*/
31+
bool BluetoothHandler::check() {
32+
if (!isScanning && serialBT.connected(1000)) {
33+
isConnected = true;
34+
return true;
35+
} else {
36+
isConnected = false;
37+
38+
if (isScanning) {
39+
serialBT.discoverAsyncStop();
40+
serialBT.discoverClear();
41+
isScanning = false;
42+
} else {
43+
serialBT.discoverAsync(discovered, 2500);
44+
isScanning = true;
45+
}
46+
47+
return false;
48+
}
49+
}
50+
51+
/**
52+
* connects to the given bluetooth device
53+
*/
54+
bool BluetoothHandler::connect(BTAddress address, uint16_t channel) { return connect(address, channel, nullptr); };
55+
bool BluetoothHandler::connect(BTAddress address, uint16_t channel, const char *pin) {
56+
serialBT.discoverAsyncStop();
57+
serialBT.discoverClear();
58+
59+
if (pin != nullptr) serialBT.setPin(pin);
60+
return serialBT.connect(address, channel);
61+
}
62+
63+
/**
64+
* disconnects from the current bluetooth device
65+
*/
66+
bool BluetoothHandler::disconnect(void) {
67+
return serialBT.disconnect();
68+
}
69+
70+
/**
71+
* callback for when a bluetooth device was discovered
72+
*/
73+
void BluetoothHandler::discovered(BTAdvertisedDevice* device) {
74+
if (!device->haveName()) return;
75+
76+
esp_bd_addr_t* address = device->getAddress().getNative();
77+
std::string name = device->getName();
78+
79+
// pass it into the input handlers for an advertise announcement
80+
BaseInput::advertise((const uint8_t*)address, name.c_str(), name.size());
81+
}
82+
83+
/**
84+
* callback for when some data from a bluetooth device was received
85+
*/
86+
void BluetoothHandler::received(esp_spp_cb_event_t event, esp_spp_cb_param_t *param) {
87+
switch (event) {
88+
case ESP_SPP_DATA_IND_EVT:
89+
size_t available;
90+
uint8_t buffer[64];
91+
while (available = serialBT.available()) {
92+
size_t size = serialBT.readBytes(buffer, available);
93+
94+
// pass it into the output handlers backward channel
95+
BluetoothOutput::backward(buffer, size);
96+
}
97+
break;
98+
}
99+
}
100+
101+
/**
102+
* sends data to the bluetooth device
103+
*/
104+
size_t BluetoothHandler::send(const uint8_t *buffer, size_t size) {
105+
if (!isConnected) return 0;
106+
return serialBT.write(buffer, size);
107+
}

src/hardware/bluetoothctl.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
2+
#ifndef _BLUETOOTH_H
3+
#define _BLUETOOTH_H
4+
5+
#include "config.h"
6+
7+
#include "Arduino.h"
8+
#include "BluetoothSerial.h"
9+
10+
class BluetoothHandler {
11+
public:
12+
static void setup(void);
13+
static void loop(void);
14+
static bool check(void);
15+
16+
static bool connect(BTAddress address, uint16_t channel, const char *pin);
17+
static bool connect(BTAddress address, uint16_t channel);
18+
static bool disconnect(void);
19+
20+
static size_t send(const uint8_t *buffer, size_t size);
21+
22+
private:
23+
inline static bool isConnected;
24+
inline static bool isScanning;
25+
inline static unsigned long timer;
26+
inline static BluetoothSerial serialBT;
27+
28+
static void discovered(BTAdvertisedDevice* device);
29+
static void received(esp_spp_cb_event_t event, esp_spp_cb_param_t *param);
30+
};
31+
#endif

src/hardware/wifictl.cpp

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
2+
#include "util.h"
3+
#include "wifictl.h"
4+
5+
WifiHandler::WifiHandler() {
6+
timer = millis();
7+
}
8+
9+
/**
10+
* setup functionality
11+
*/
12+
void WifiHandler::setup(void) {
13+
WiFi.disconnect(true);
14+
WiFi.persistent(true);
15+
WiFi.setAutoConnect(true);
16+
WiFi.setAutoReconnect(true);
17+
WiFi.setHostname(WIFI_NAME);
18+
WiFi.onEvent(scanned, WiFiEvent_t::ARDUINO_EVENT_WIFI_SCAN_DONE);
19+
WiFi.onEvent(connected, WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_GOT_IP);
20+
WiFi.onEvent(disconnected, WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_DISCONNECTED);
21+
WiFi.scanNetworks(true, false, false, 250);
22+
}
23+
24+
/**
25+
* loop functionality
26+
*/
27+
void WifiHandler::loop(void) {
28+
if (getElapsed(timer) > 15000) {
29+
timer = millis();
30+
31+
check();
32+
}
33+
}
34+
35+
/**
36+
* checks connection and scanning state and keeps background tasks up
37+
*/
38+
bool WifiHandler::check(void) {
39+
if (WiFi.status() == WL_CONNECTED)
40+
{
41+
isConnected = true;
42+
return true;
43+
}
44+
else
45+
{
46+
isConnected = false;
47+
48+
int8_t wifiStatus = WiFi.status();
49+
int8_t scanStatus = WiFi.scanComplete();
50+
if ((wifiStatus == WL_IDLE_STATUS ||
51+
wifiStatus == WL_NO_SSID_AVAIL ||
52+
wifiStatus == WL_CONNECT_FAILED ||
53+
wifiStatus == WL_DISCONNECTED) && scanStatus != -1) {
54+
WiFi.scanNetworks(true, false, false, 500);
55+
}
56+
57+
return WiFi.status() == WL_CONNECTED;
58+
}
59+
}
60+
61+
/**
62+
* connects to one of the scanned wifi networks
63+
*/
64+
void WifiHandler::connect(void) {
65+
if (WiFi.status() == WL_CONNECTED) return;
66+
67+
int16_t count = WiFi.scanComplete();
68+
for (uint8_t i = 0; i < count && i < 99; i++) {
69+
auto ssid = WiFi.SSID(i);
70+
if (ssid == NULL || ssid.length() == 0) continue;
71+
72+
if (ssid == WIFISSID1) { WiFi.begin(WIFISSID1, WIFIPASS1); break; }
73+
if (ssid == WIFISSID2) { WiFi.begin(WIFISSID2, WIFIPASS2); break; }
74+
}
75+
76+
WiFi.scanDelete();
77+
}
78+
79+
/**
80+
* callback for when the scan finished
81+
*/
82+
void WifiHandler::scanned(WiFiEvent_t event, WiFiEventInfo_t info) {
83+
if (info.wifi_scan_done.number > 0) connect();
84+
}
85+
86+
/**
87+
* callback for when we connected to a network
88+
*/
89+
void WifiHandler::connected(WiFiEvent_t event, WiFiEventInfo_t info) {
90+
isConnected = true;
91+
92+
WiFi.setTxPower(WIFI_POWER_15dBm);
93+
WiFi.setAutoConnect(true);
94+
WiFi.setAutoReconnect(true);
95+
WiFi.setHostname(WIFI_NAME);
96+
WiFi.persistent(true);
97+
}
98+
99+
/**
100+
* callback for when we disconnected from a network
101+
*/
102+
void WifiHandler::disconnected(WiFiEvent_t event, WiFiEventInfo_t info) {
103+
isConnected = false;
104+
}

src/hardware/wifictl.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
2+
#ifndef _WIFI_H
3+
#define _WIFI_H
4+
5+
#include "config.h"
6+
7+
#include "Arduino.h"
8+
#include "WiFi.h"
9+
10+
class WifiHandler {
11+
public:
12+
WifiHandler();
13+
static void setup(void);
14+
static void loop(void);
15+
static bool check(void);
16+
static void connect(void);
17+
18+
private:
19+
inline static bool isConnected;
20+
inline static unsigned long timer;
21+
22+
static void scanned(WiFiEvent_t event, WiFiEventInfo_t info);
23+
static void connected(WiFiEvent_t event, WiFiEventInfo_t info);
24+
static void disconnected(WiFiEvent_t event, WiFiEventInfo_t info);
25+
};
26+
#endif

src/input/base.cpp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
2+
#include "base.h"
3+
4+
/**
5+
* setup functionality
6+
*/
7+
void BaseInput::setup() {
8+
TcpInput::setup();
9+
SerialInput::setup();
10+
}
11+
12+
/**
13+
* loop functionality
14+
*/
15+
void BaseInput::loop() {
16+
TcpInput::loop();
17+
SerialInput::loop();
18+
}
19+
20+
/**
21+
* the forward channel for a bluetooth connection
22+
*/
23+
void BaseInput::forward(const char *address, uint16_t port) {
24+
TcpInput::forward(address, port);
25+
SerialInput::forward(address, port);
26+
}
27+
28+
/**
29+
* the forward channel for bluetooth data
30+
*/
31+
void BaseInput::forward(const uint8_t *buffer, size_t size) {
32+
TcpInput::forward(buffer, size);
33+
SerialInput::forward(buffer, size);
34+
}
35+
36+
/**
37+
* the backward channel for bluetooth data
38+
*/
39+
void BaseInput::backward(const uint8_t *buffer, size_t size) {
40+
TcpInput::backward(buffer, size);
41+
SerialInput::backward(buffer, size);
42+
}
43+
44+
/**
45+
* the channel for an advertised bluetooth device
46+
*/
47+
void BaseInput::advertise(const uint8_t* address, const char* name, size_t size) {
48+
TcpInput::advertise(address, name, size);
49+
SerialInput::advertise(address, name, size);
50+
}

0 commit comments

Comments
 (0)