Browse Source

Feature: Bluetooth

master
grch101 4 years ago
committed by Torsten Stauder
parent
commit
9c14e86b63
  1. 1
      html/management.html
  2. 2
      platformio.ini
  3. 1
      src/HTMLmanagement.h
  4. 213
      src/main.cpp
  5. 2
      src/settings.h

1
html/management.html

@ -227,6 +227,7 @@
<option value="111">Wiederhole Titel (endlos)</option> <option value="111">Wiederhole Titel (endlos)</option>
<option value="120">Dimme LEDs (Nachtmodus)</option> <option value="120">Dimme LEDs (Nachtmodus)</option>
<option value="130">Aktiviere/deaktive WLAN</option> <option value="130">Aktiviere/deaktive WLAN</option>
<option value="140">Aktiviere/deaktiviere Bluetooth</option>
</select> </select>
</div> </div>
<br> <br>

2
platformio.ini

@ -21,7 +21,7 @@ lib_deps_external =
ESP Async WebServer ESP Async WebServer
https://github.com/me-no-dev/AsyncTCP https://github.com/me-no-dev/AsyncTCP
https://github.com/bblanchon/ArduinoJson.git https://github.com/bblanchon/ArduinoJson.git
; https://github.com/pschatzmann/ESP32-A2DP.git
https://github.com/pschatzmann/ESP32-A2DP.git
[env:common] [env:common]
platform = espressif32 platform = espressif32

1
src/HTMLmanagement.h

@ -227,6 +227,7 @@ static const char management_HTML[] PROGMEM = "<!DOCTYPE html>\
<option value=\"111\">Wiederhole Titel (endlos)</option>\ <option value=\"111\">Wiederhole Titel (endlos)</option>\
<option value=\"120\">Dimme LEDs (Nachtmodus)</option>\ <option value=\"120\">Dimme LEDs (Nachtmodus)</option>\
<option value=\"130\">Aktiviere/deaktive WLAN</option>\ <option value=\"130\">Aktiviere/deaktive WLAN</option>\
<option value=\"140\">Aktiviere/deaktiviere Bluetooth</option>\
</select>\ </select>\
</div>\ </div>\
<br>\ <br>\

213
src/main.cpp

@ -23,6 +23,7 @@
#include "ESP32FtpServer.h" #include "ESP32FtpServer.h"
#endif #endif
#ifdef BLUETOOTH_ENABLE #ifdef BLUETOOTH_ENABLE
#include "esp_bt.h"
#include "BluetoothA2DPSink.h" #include "BluetoothA2DPSink.h"
#endif #endif
#include "Audio.h" #include "Audio.h"
@ -88,7 +89,7 @@ char *logBuf = (char*) calloc(serialLoglength, sizeof(char)); // Buffer for all
#endif #endif
#ifdef BLUETOOTH_ENABLE #ifdef BLUETOOTH_ENABLE
BluetoothA2DPSink a2dp_sink;
BluetoothA2DPSink *a2dp_sink;
#endif #endif
#ifdef MEASURE_BATTERY_VOLTAGE #ifdef MEASURE_BATTERY_VOLTAGE
@ -103,6 +104,10 @@ char *logBuf = (char*) calloc(serialLoglength, sizeof(char)); // Buffer for all
bool recoverLastRfid = true; bool recoverLastRfid = true;
#endif #endif
// Operation Mode
#define OPMODE_NORMAL 0 // Normal mode
#define OPMODE_BLUETOOTH 1 // Bluetooth mode. WiFi is deactivated. Music from SD can't be played.
// Track-Control // Track-Control
#define STOP 1 // Stop play #define STOP 1 // Stop play
#define PLAY 2 // Start play (currently not used) #define PLAY 2 // Start play (currently not used)
@ -138,6 +143,7 @@ char *logBuf = (char*) calloc(serialLoglength, sizeof(char)); // Buffer for all
#define REPEAT_TRACK 111 // Changes active playmode to endless-loop (for a single track) #define REPEAT_TRACK 111 // Changes active playmode to endless-loop (for a single track)
#define DIMM_LEDS_NIGHTMODE 120 // Changes LED-brightness #define DIMM_LEDS_NIGHTMODE 120 // Changes LED-brightness
#define TOGGLE_WIFI_STATUS 130 // Toggles WiFi-status #define TOGGLE_WIFI_STATUS 130 // Toggles WiFi-status
#define TOGGLE_BLUETOOTH_MODE 140 // Toggles Normal/Bluetooth Mode
// Repeat-Modes // Repeat-Modes
#define NO_REPEAT 0 // No repeat #define NO_REPEAT 0 // No repeat
@ -170,6 +176,9 @@ typedef struct {
char nvsEntry[275]; char nvsEntry[275];
} nvs_t; } nvs_t;
// Operation Mode
volatile uint8_t operationMode;
// Configuration of initial values (for the first start) goes here.... // Configuration of initial values (for the first start) goes here....
// There's no need to change them here as they can be configured via webinterface // There's no need to change them here as they can be configured via webinterface
// Neopixel // Neopixel
@ -408,6 +417,9 @@ void volumeHandler(const int32_t _minVolume, const int32_t _maxVolume);
void volumeToQueueSender(const int32_t _newVolume); void volumeToQueueSender(const int32_t _newVolume);
wl_status_t wifiManager(void); wl_status_t wifiManager(void);
bool writeWifiStatusToNVS(bool wifiStatus); bool writeWifiStatusToNVS(bool wifiStatus);
void bluetoothHandler(void);
uint8_t readOperationModeFromNVS(void);
bool setOperationMode(uint8_t operationMode);
/* Wrapper-function for serial-logging (with newline) /* Wrapper-function for serial-logging (with newline)
@ -1849,7 +1861,7 @@ void showLed(void *parameter) {
static unsigned long lastSwitchTimestamp = 0; static unsigned long lastSwitchTimestamp = 0;
static bool redrawProgress = false; static bool redrawProgress = false;
static uint8_t lastLedBrightness = ledBrightness; static uint8_t lastLedBrightness = ledBrightness;
static CRGB::HTMLColorCode idleColor;
static CRGB leds[NUM_LEDS]; static CRGB leds[NUM_LEDS];
FastLED.addLeds<CHIPSET , LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection( TypicalSMD5050 ); FastLED.addLeds<CHIPSET , LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection( TypicalSMD5050 );
FastLED.setBrightness(ledBrightness); FastLED.setBrightness(ledBrightness);
@ -2075,19 +2087,32 @@ void showLed(void *parameter) {
switch (playProperties.playMode) { switch (playProperties.playMode) {
case NO_PLAYLIST: // If no playlist is active (idle) case NO_PLAYLIST: // If no playlist is active (idle)
#ifdef BLUETOOTH_ENABLE
if(operationMode == OPMODE_BLUETOOTH ) {
idleColor = CRGB::Blue;
} else {
#endif
if(wifiManager() == WL_CONNECTED) {
idleColor = CRGB::White;
} else {
idleColor = CRGB::Green;
}
#ifdef BLUETOOTH_ENABLE
}
#endif
if (hlastVolume == currentVolume && lastLedBrightness == ledBrightness) { if (hlastVolume == currentVolume && lastLedBrightness == ledBrightness) {
for (uint8_t i=0; i<NUM_LEDS; i++) { for (uint8_t i=0; i<NUM_LEDS; i++) {
FastLED.clear(); FastLED.clear();
if (ledAddress(i) == 0) { // White if Wifi is enabled and blue if not if (ledAddress(i) == 0) { // White if Wifi is enabled and blue if not
leds[0] = (wifiManager() == WL_CONNECTED) ? CRGB::White : CRGB::Blue;
leds[NUM_LEDS/4] = (wifiManager() == WL_CONNECTED) ? CRGB::White : CRGB::Blue;
leds[NUM_LEDS/2] = (wifiManager() == WL_CONNECTED) ? CRGB::White : CRGB::Blue;
leds[NUM_LEDS/4*3] = (wifiManager() == WL_CONNECTED) ? CRGB::White : CRGB::Blue;
leds[0] = idleColor;
leds[NUM_LEDS/4] = idleColor;
leds[NUM_LEDS/2] = idleColor;
leds[NUM_LEDS/4*3] = idleColor;
} else { } else {
leds[ledAddress(i) % NUM_LEDS] = (wifiManager() == WL_CONNECTED) ? CRGB::White : CRGB::Blue;
leds[(ledAddress(i)+NUM_LEDS/4) % NUM_LEDS] = (wifiManager() == WL_CONNECTED) ? CRGB::White : CRGB::Blue;
leds[(ledAddress(i)+NUM_LEDS/2) % NUM_LEDS] = (wifiManager() == WL_CONNECTED) ? CRGB::White : CRGB::Blue;
leds[(ledAddress(i)+NUM_LEDS/4*3) % NUM_LEDS] = (wifiManager() == WL_CONNECTED) ? CRGB::White : CRGB::Blue;
leds[ledAddress(i) % NUM_LEDS] = idleColor;
leds[(ledAddress(i)+NUM_LEDS/4) % NUM_LEDS] = idleColor;
leds[(ledAddress(i)+NUM_LEDS/2) % NUM_LEDS] = idleColor;
leds[(ledAddress(i)+NUM_LEDS/4*3) % NUM_LEDS] = idleColor;
} }
FastLED.show(); FastLED.show();
for (uint8_t i=0; i<=50; i++) { for (uint8_t i=0; i<=50; i++) {
@ -2886,7 +2911,25 @@ void doRfidCardModifications(const uint32_t mod) {
} }
break; break;
#ifdef BLUETOOTH_ENABLE
case TOGGLE_BLUETOOTH_MODE:
if (readOperationModeFromNVS() == OPMODE_NORMAL) {
#ifdef NEOPIXEL_ENABLE
showLedOk = true;
#endif
setOperationMode(OPMODE_BLUETOOTH);
} else if (readOperationModeFromNVS() == OPMODE_BLUETOOTH) {
#ifdef NEOPIXEL_ENABLE
showLedOk = true;
#endif
setOperationMode(OPMODE_NORMAL);
} else {
#ifdef NEOPIXEL_ENABLE
showLedError = true;
#endif
}
break;
#endif
default: default:
snprintf(logBuf, serialLoglength, "%s %d !", (char *) FPSTR(modificatorDoesNotExist), mod); snprintf(logBuf, serialLoglength, "%s %d !", (char *) FPSTR(modificatorDoesNotExist), mod);
loggerNl(serialDebug, logBuf, LOGLEVEL_ERROR); loggerNl(serialDebug, logBuf, LOGLEVEL_ERROR);
@ -2955,6 +2998,14 @@ void rfidPreferenceLookupHandler (void) {
#ifdef MQTT_ENABLE #ifdef MQTT_ENABLE
publishMqtt((char *) FPSTR(topicRfidState), currentRfidTagId, false); publishMqtt((char *) FPSTR(topicRfidState), currentRfidTagId, false);
#endif #endif
#ifdef BLUETOOTH_ENABLE
// if music rfid was read, go back to normal mode
if(operationMode == OPMODE_BLUETOOTH) {
setOperationMode(OPMODE_NORMAL);
}
#endif
trackQueueDispatcher(_file, _lastPlayPos, _playMode, _trackLastPlayed); trackQueueDispatcher(_file, _lastPlayPos, _playMode, _trackLastPlayed);
} }
} }
@ -3045,6 +3096,20 @@ bool writeWifiStatusToNVS(bool wifiStatus) {
return true; return true;
} }
uint8_t readOperationModeFromNVS(void) {
return prefsSettings.getUChar("operationMode", OPMODE_NORMAL);
}
bool setOperationMode(uint8_t newOperationMode) {
uint8_t currentOperationMode = prefsSettings.getUChar("operationMode", OPMODE_NORMAL);
if(currentOperationMode != newOperationMode) {
if (prefsSettings.putUChar("operationMode", newOperationMode)) {
ESP.restart();
}
}
return true;
}
// Creates FTP-instance only when requested // Creates FTP-instance only when requested
#ifdef FTP_ENABLE #ifdef FTP_ENABLE
@ -4206,17 +4271,6 @@ void setup() {
headphoneLastDetectionState = digitalRead(HP_DETECT); headphoneLastDetectionState = digitalRead(HP_DETECT);
#endif #endif
#ifdef BLUETOOTH_ENABLE
i2s_pin_config_t pin_config = {
.bck_io_num = I2S_BCLK,
.ws_io_num = I2S_LRC,
.data_out_num = I2S_DOUT,
.data_in_num = I2S_PIN_NO_CHANGE
};
a2dp_sink.set_pin_config(pin_config);
a2dp_sink.start("ESPuino");
#endif
// Create queues // Create queues
volumeQueue = xQueueCreate(1, sizeof(int)); volumeQueue = xQueueCreate(1, sizeof(int));
if (volumeQueue == NULL) { if (volumeQueue == NULL) {
@ -4456,17 +4510,6 @@ void setup() {
0 /* Core where the task should run */ 0 /* Core where the task should run */
); );
xTaskCreatePinnedToCore(
playAudio, /* Function to implement the task */
"mp3play", /* Name of the task */
11000, /* Stack size in words */
NULL, /* Task input parameter */
2 | portPRIVILEGE_BIT, /* Priority of the task */
&mp3Play, /* Task handle. */
1 /* Core where the task should run */
);
// Activate internal pullups for all buttons // Activate internal pullups for all buttons
pinMode(DREHENCODER_BUTTON, INPUT_PULLUP); pinMode(DREHENCODER_BUTTON, INPUT_PULLUP);
pinMode(PAUSEPLAY_BUTTON, INPUT_PULLUP); pinMode(PAUSEPLAY_BUTTON, INPUT_PULLUP);
@ -4486,8 +4529,36 @@ void setup() {
} }
#endif #endif
operationMode = readOperationModeFromNVS();
wifiEnabled = getWifiEnableStatusFromNVS(); wifiEnabled = getWifiEnableStatusFromNVS();
wifiManager();
#ifdef BLUETOOTH_ENABLE
if(operationMode == OPMODE_BLUETOOTH) {
a2dp_sink = new BluetoothA2DPSink();
i2s_pin_config_t pin_config = {
.bck_io_num = I2S_BCLK,
.ws_io_num = I2S_LRC,
.data_out_num = I2S_DOUT,
.data_in_num = I2S_PIN_NO_CHANGE
};
a2dp_sink->set_pin_config(pin_config);
a2dp_sink->start("ESPuino");
} else {
esp_bt_mem_release(ESP_BT_MODE_BTDM);
#endif
xTaskCreatePinnedToCore(
playAudio, /* Function to implement the task */
"mp3play", /* Name of the task */
11000, /* Stack size in words */
NULL, /* Task input parameter */
2 | portPRIVILEGE_BIT, /* Priority of the task */
&mp3Play, /* Task handle. */
1 /* Core where the task should run */
);
wifiManager();
#ifdef BLUETOOTH_ENABLE
}
#endif
lastTimeActiveTimestamp = millis(); // initial set after boot lastTimeActiveTimestamp = millis(); // initial set after boot
@ -4498,49 +4569,71 @@ void setup() {
Serial.printf("PSRAM: %u bytes\n", ESP.getPsramSize()); Serial.printf("PSRAM: %u bytes\n", ESP.getPsramSize());
} }
#ifdef BLUETOOTH_ENABLE
void bluetoothHandler(void) {
esp_a2d_audio_state_t state = a2dp_sink->get_audio_state();
// Reset Sleep Timer when audio is playing
if(state == ESP_A2D_AUDIO_STATE_STARTED) {
lastTimeActiveTimestamp = millis();
}
}
#endif
void loop() { void loop() {
webserverStart();
#ifdef FTP_ENABLE
ftpManager();
#ifdef BLUETOOTH_ENABLE
if(operationMode == OPMODE_BLUETOOTH) {
bluetoothHandler();
} else {
#endif #endif
webserverStart();
#ifdef FTP_ENABLE
ftpManager();
#endif
volumeHandler(minVolume, maxVolume);
if (wifiManager() == WL_CONNECTED) {
#ifdef MQTT_ENABLE
if (enableMqtt) {
reconnect();
MQTTclient.loop();
postHeartbeatViaMqtt();
}
#endif
#ifdef FTP_ENABLE
if (ftpEnableLastStatus && ftpEnableCurrentStatus) {
ftpSrv->handleFTP();
}
#endif
}
#ifdef FTP_ENABLE
if (ftpEnableLastStatus && ftpEnableCurrentStatus) {
if (ftpSrv->isConnected()) {
lastTimeActiveTimestamp = millis(); // Re-adjust timer while client is connected to avoid ESP falling asleep
}
}
#endif
ws.cleanupClients();
#ifdef BLUETOOTH_ENABLE
}
#endif
#ifdef HEADPHONE_ADJUST_ENABLE #ifdef HEADPHONE_ADJUST_ENABLE
headphoneVolumeManager(); headphoneVolumeManager();
#endif #endif
#ifdef MEASURE_BATTERY_VOLTAGE #ifdef MEASURE_BATTERY_VOLTAGE
batteryVoltageTester(); batteryVoltageTester();
#endif #endif
volumeHandler(minVolume, maxVolume);
buttonHandler(); buttonHandler();
doButtonActions(); doButtonActions();
sleepHandler(); sleepHandler();
deepSleepManager(); deepSleepManager();
rfidPreferenceLookupHandler(); rfidPreferenceLookupHandler();
if (wifiManager() == WL_CONNECTED) {
#ifdef MQTT_ENABLE
if (enableMqtt) {
reconnect();
MQTTclient.loop();
postHeartbeatViaMqtt();
}
#endif
#ifdef FTP_ENABLE
if (ftpEnableLastStatus && ftpEnableCurrentStatus) {
ftpSrv->handleFTP();
}
#endif
}
#ifdef FTP_ENABLE
if (ftpEnableLastStatus && ftpEnableCurrentStatus) {
if (ftpSrv->isConnected()) {
lastTimeActiveTimestamp = millis(); // Re-adjust timer while client is connected to avoid ESP falling asleep
}
}
#endif
#ifdef PLAY_LAST_RFID_AFTER_REBOOT #ifdef PLAY_LAST_RFID_AFTER_REBOOT
recoverLastRfidPlayed(); recoverLastRfidPlayed();
#endif #endif
ws.cleanupClients();
} }

2
src/settings.h

@ -29,7 +29,7 @@
//#define PLAY_LAST_RFID_AFTER_REBOOT // When restarting ESPuino, the last RFID that was active before, is recalled and played //#define PLAY_LAST_RFID_AFTER_REBOOT // When restarting ESPuino, the last RFID that was active before, is recalled and played
//#define USE_LAST_VOLUME_AFTER_REBOOT // Remembers the volume used at last shutdown after reboot //#define USE_LAST_VOLUME_AFTER_REBOOT // Remembers the volume used at last shutdown after reboot
//#define BLUETOOTH_ENABLE // Doesn't work currently (so don't enable) as there's not enough DRAM available
#define BLUETOOTH_ENABLE // Doesn't work currently (so don't enable) as there's not enough DRAM available
//################## select SD card mode ############################# //################## select SD card mode #############################

Loading…
Cancel
Save