Previous, low voltage sleep
This commit is contained in:
parent
5814a73f50
commit
83b5e1c5e9
|
|
@ -1,11 +1,11 @@
|
||||||
#include "DirectoryNode.h"
|
#include "DirectoryNode.h"
|
||||||
|
|
||||||
|
|
||||||
DirectoryNode::DirectoryNode(const String &nodeName)
|
DirectoryNode::DirectoryNode(const String &nodeName)
|
||||||
: name(nodeName), currentPlaying(nullptr) {
|
: name(nodeName), currentPlaying(nullptr)
|
||||||
id = DirectoryNode::idCounter;
|
{
|
||||||
DirectoryNode::idCounter++;
|
id = DirectoryNode::idCounter;
|
||||||
}
|
DirectoryNode::idCounter++;
|
||||||
|
}
|
||||||
|
|
||||||
DirectoryNode::~DirectoryNode()
|
DirectoryNode::~DirectoryNode()
|
||||||
{
|
{
|
||||||
|
|
@ -15,7 +15,6 @@ DirectoryNode::~DirectoryNode()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const uint16_t DirectoryNode::getId() const
|
const uint16_t DirectoryNode::getId() const
|
||||||
{
|
{
|
||||||
return id;
|
return id;
|
||||||
|
|
@ -39,8 +38,10 @@ const std::vector<String> &DirectoryNode::getMP3Files() const
|
||||||
void DirectoryNode::setCurrentPlaying(const String *mp3File)
|
void DirectoryNode::setCurrentPlaying(const String *mp3File)
|
||||||
{
|
{
|
||||||
currentPlaying = mp3File;
|
currentPlaying = mp3File;
|
||||||
for (int i=0;i<mp3Files.size();i++) {
|
for (int i = 0; i < mp3Files.size(); i++)
|
||||||
if (mp3Files[i] == *mp3File && ids.size()>i) {
|
{
|
||||||
|
if (mp3Files[i] == *mp3File && ids.size() > i)
|
||||||
|
{
|
||||||
currentPlayingId = ids[i];
|
currentPlayingId = ids[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -56,7 +57,8 @@ const uint16_t DirectoryNode::getCurrentPlayingId() const
|
||||||
return currentPlayingId;
|
return currentPlayingId;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t DirectoryNode::getNextId() {
|
uint16_t DirectoryNode::getNextId()
|
||||||
|
{
|
||||||
uint16_t next = DirectoryNode::idCounter;
|
uint16_t next = DirectoryNode::idCounter;
|
||||||
DirectoryNode::idCounter++;
|
DirectoryNode::idCounter++;
|
||||||
return next;
|
return next;
|
||||||
|
|
@ -70,14 +72,16 @@ void DirectoryNode::addSubdirectory(DirectoryNode *subdirectory)
|
||||||
void DirectoryNode::addMP3File(const String &mp3File)
|
void DirectoryNode::addMP3File(const String &mp3File)
|
||||||
{
|
{
|
||||||
mp3Files.push_back(mp3File);
|
mp3Files.push_back(mp3File);
|
||||||
ids.push_back(getNextId());
|
ids.push_back(getNextId());
|
||||||
}
|
}
|
||||||
|
|
||||||
void DirectoryNode::setSecondsPlayed(const uint32_t seconds) {
|
void DirectoryNode::setSecondsPlayed(const uint32_t seconds)
|
||||||
|
{
|
||||||
secondsPlayed = seconds;
|
secondsPlayed = seconds;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t DirectoryNode::getSecondsPlayed() {
|
uint32_t DirectoryNode::getSecondsPlayed()
|
||||||
|
{
|
||||||
return secondsPlayed;
|
return secondsPlayed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -92,7 +96,7 @@ void DirectoryNode::buildDirectoryTree(const char *currentPath)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entry.isDirectory() && entry.name()[0] != '.' && strcmp(entry.name(),sys_dir.c_str()))
|
if (entry.isDirectory() && entry.name()[0] != '.' && strcmp(entry.name(), sys_dir.c_str()))
|
||||||
{
|
{
|
||||||
DirectoryNode *newNode = new DirectoryNode(entry.name());
|
DirectoryNode *newNode = new DirectoryNode(entry.name());
|
||||||
subdirectories.push_back(newNode);
|
subdirectories.push_back(newNode);
|
||||||
|
|
@ -153,20 +157,23 @@ DirectoryNode *DirectoryNode::findFirstDirectoryWithMP3s()
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DirectoryNode::advanceToFirstMP3InThisNode() {
|
void DirectoryNode::advanceToFirstMP3InThisNode()
|
||||||
if (mp3Files.size()>0) {
|
{
|
||||||
|
if (mp3Files.size() > 0)
|
||||||
|
{
|
||||||
setCurrentPlaying(&mp3Files[0]);
|
setCurrentPlaying(&mp3Files[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DirectoryNode *DirectoryNode::advanceToMP3(const uint16_t id)
|
||||||
DirectoryNode* DirectoryNode::advanceToMP3(const uint16_t id) {
|
{
|
||||||
for (auto subdir : subdirectories)
|
for (auto subdir : subdirectories)
|
||||||
{
|
{
|
||||||
if (subdir->getId()==id) {
|
if (subdir->getId() == id)
|
||||||
|
{
|
||||||
subdir->advanceToFirstMP3InThisNode();
|
subdir->advanceToFirstMP3InThisNode();
|
||||||
return subdir;
|
return subdir;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Have each subdirectory advance its song
|
// Have each subdirectory advance its song
|
||||||
for (size_t i = 0; i < subdir->ids.size(); i++)
|
for (size_t i = 0; i < subdir->ids.size(); i++)
|
||||||
|
|
@ -179,8 +186,7 @@ for (auto subdir : subdirectories)
|
||||||
subdir->currentPlaying = &subdir->mp3Files[i];
|
subdir->currentPlaying = &subdir->mp3Files[i];
|
||||||
subdir->currentPlayingId = id;
|
subdir->currentPlayingId = id;
|
||||||
return subdir;
|
return subdir;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -191,14 +197,15 @@ for (auto subdir : subdirectories)
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DirectoryNode *DirectoryNode::advanceToMP3(const String *currentGlobal)
|
||||||
DirectoryNode* DirectoryNode::advanceToMP3(const String* currentGlobal) {
|
{
|
||||||
for (auto subdir : subdirectories)
|
for (auto subdir : subdirectories)
|
||||||
{
|
{
|
||||||
if (subdir->getName()==*currentGlobal) {
|
if (subdir->getName() == *currentGlobal)
|
||||||
|
{
|
||||||
subdir->advanceToFirstMP3InThisNode();
|
subdir->advanceToFirstMP3InThisNode();
|
||||||
return subdir;
|
return subdir;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Have each subdirectory advance its song
|
// Have each subdirectory advance its song
|
||||||
for (size_t i = 0; i < subdir->mp3Files.size(); i++)
|
for (size_t i = 0; i < subdir->mp3Files.size(); i++)
|
||||||
|
|
@ -210,8 +217,7 @@ DirectoryNode* DirectoryNode::advanceToMP3(const String* currentGlobal) {
|
||||||
{
|
{
|
||||||
subdir->setCurrentPlaying(&subdir->mp3Files[i]);
|
subdir->setCurrentPlaying(&subdir->mp3Files[i]);
|
||||||
return subdir;
|
return subdir;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -222,7 +228,50 @@ DirectoryNode* DirectoryNode::advanceToMP3(const String* currentGlobal) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
DirectoryNode* DirectoryNode::advanceToNextMP3(const String* currentGlobal)
|
/**
|
||||||
|
* Moves to the previous MP3 file in the directory.
|
||||||
|
* If the current song has been playing for more than a specific threshold, restarts the current song.
|
||||||
|
* If the current song has just started, or it's the first song, moves to the previous song in the directory.
|
||||||
|
*
|
||||||
|
* @param thresholdSeconds The number of seconds to decide whether to restart the current song or go to the previous song.
|
||||||
|
* @return A pointer to the DirectoryNode where the new current song is located, or nullptr if there's no previous song.
|
||||||
|
*/
|
||||||
|
DirectoryNode *DirectoryNode::goToPreviousMP3(uint32_t thresholdSeconds)
|
||||||
|
{
|
||||||
|
if (secondsPlayed > thresholdSeconds || currentPlaying == nullptr)
|
||||||
|
{
|
||||||
|
// Restart the current song if it's been playing for more than thresholdSeconds
|
||||||
|
// Or if there is no current song (at the start of the list)
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Find the previous song
|
||||||
|
for (size_t i = 0; i < mp3Files.size(); i++)
|
||||||
|
{
|
||||||
|
if (currentPlaying != nullptr && *currentPlaying == mp3Files[i] && i > 0)
|
||||||
|
{
|
||||||
|
// Move to the previous song
|
||||||
|
setCurrentPlaying(&mp3Files[i - 1]);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the first song in the directory or no song was playing, move to the previous directory, if any
|
||||||
|
for (auto subdir : subdirectories)
|
||||||
|
{
|
||||||
|
DirectoryNode *previousNode = subdir->goToPreviousMP3(thresholdSeconds);
|
||||||
|
if (previousNode != nullptr)
|
||||||
|
{
|
||||||
|
return previousNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// No previous song available
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
DirectoryNode *DirectoryNode::advanceToNextMP3(const String *currentGlobal)
|
||||||
{
|
{
|
||||||
bool useFirst = false;
|
bool useFirst = false;
|
||||||
Serial.println(currentGlobal->c_str());
|
Serial.println(currentGlobal->c_str());
|
||||||
|
|
@ -230,7 +279,7 @@ DirectoryNode* DirectoryNode::advanceToNextMP3(const String* currentGlobal)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < mp3Files.size(); i++)
|
for (size_t i = 0; i < mp3Files.size(); i++)
|
||||||
{
|
{
|
||||||
if (*currentGlobal==mp3Files[i])
|
if (*currentGlobal == mp3Files[i])
|
||||||
{
|
{
|
||||||
// Found the current playing MP3 file
|
// Found the current playing MP3 file
|
||||||
if (i < mp3Files.size() - 1)
|
if (i < mp3Files.size() - 1)
|
||||||
|
|
@ -245,14 +294,14 @@ DirectoryNode* DirectoryNode::advanceToNextMP3(const String* currentGlobal)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// We are either not playing, or we've exhausted all the MP3 files in this directory.
|
// We are either not playing, or we've exhausted all the MP3 files in this directory.
|
||||||
// Therefore, we need to recursively look in our subdirectories.
|
// Therefore, we need to recursively look in our subdirectories.
|
||||||
for (auto subdir : subdirectories)
|
for (auto subdir : subdirectories)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (useFirst && subdir->mp3Files.size()>0) {
|
if (useFirst && subdir->mp3Files.size() > 0)
|
||||||
|
{
|
||||||
subdir->setCurrentPlaying(&subdir->mp3Files[0]);
|
subdir->setCurrentPlaying(&subdir->mp3Files[0]);
|
||||||
return subdir;
|
return subdir;
|
||||||
}
|
}
|
||||||
|
|
@ -268,7 +317,9 @@ DirectoryNode* DirectoryNode::advanceToNextMP3(const String* currentGlobal)
|
||||||
// Advance to the next MP3 file in the same directory
|
// Advance to the next MP3 file in the same directory
|
||||||
subdir->setCurrentPlaying(&subdir->mp3Files[i + 1]);
|
subdir->setCurrentPlaying(&subdir->mp3Files[i + 1]);
|
||||||
return subdir;
|
return subdir;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
useFirst = true;
|
useFirst = true;
|
||||||
}
|
}
|
||||||
// Reached the end of the MP3 files in the directory
|
// Reached the end of the MP3 files in the directory
|
||||||
|
|
@ -287,24 +338,27 @@ String DirectoryNode::getDirectoryStructureHTML() const
|
||||||
{
|
{
|
||||||
String html;
|
String html;
|
||||||
html.reserve(1024); // Reserve memory for better performance
|
html.reserve(1024); // Reserve memory for better performance
|
||||||
if (name=="/") {
|
if (name == "/")
|
||||||
|
{
|
||||||
html += "<ul>\n";
|
html += "<ul>\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name!="/") {
|
if (name != "/")
|
||||||
html += "<li data-id=\""+String(id)+"\"><b>" + name + "</b></li>\n";
|
{
|
||||||
|
html += "<li data-id=\"" + String(id) + "\"><b>" + name + "</b></li>\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i=0;i<mp3Files.size();i++)
|
for (int i = 0; i < mp3Files.size(); i++)
|
||||||
{
|
{
|
||||||
html += "<li data-id=\""+String(ids[i])+"\">" + mp3Files[i] + "</li>\n";
|
html += "<li data-id=\"" + String(ids[i]) + "\">" + mp3Files[i] + "</li>\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
for (DirectoryNode *childNode : subdirectories)
|
for (DirectoryNode *childNode : subdirectories)
|
||||||
{
|
{
|
||||||
html += childNode->getDirectoryStructureHTML();
|
html += childNode->getDirectoryStructureHTML();
|
||||||
}
|
}
|
||||||
if (name=="/") {
|
if (name == "/")
|
||||||
|
{
|
||||||
html += "</ul>\n";
|
html += "</ul>\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@ public:
|
||||||
void printDirectoryTree(int level = 0) const;
|
void printDirectoryTree(int level = 0) const;
|
||||||
DirectoryNode* advanceToMP3(const String* currentGlobal);
|
DirectoryNode* advanceToMP3(const String* currentGlobal);
|
||||||
DirectoryNode* advanceToNextMP3(const String* currentGlobal);
|
DirectoryNode* advanceToNextMP3(const String* currentGlobal);
|
||||||
|
DirectoryNode* goToPreviousMP3(uint32_t thresholdSeconds = 3);
|
||||||
DirectoryNode* advanceToMP3(const uint16_t id);
|
DirectoryNode* advanceToMP3(const uint16_t id);
|
||||||
void advanceToFirstMP3InThisNode();
|
void advanceToFirstMP3InThisNode();
|
||||||
String getDirectoryStructureHTML() const;
|
String getDirectoryStructureHTML() const;
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ const char index_html[] PROGMEM = R"rawliteral(
|
||||||
<span id="uid"></span><br/>
|
<span id="uid"></span><br/>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<button class="prev-button" onclick="simpleGetCall('prev');""></button>
|
<button class="prev-button" onclick="simpleGetCall('previous');""></button>
|
||||||
<button class="play-button" onclick="simpleGetCall('toggleplaypause');"></button>
|
<button class="play-button" onclick="simpleGetCall('toggleplaypause');"></button>
|
||||||
<button class="next-button" onclick="simpleGetCall('next');"></button><br/><br/>
|
<button class="next-button" onclick="simpleGetCall('next');"></button><br/><br/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
56
src/main.cpp
56
src/main.cpp
|
|
@ -37,6 +37,8 @@
|
||||||
|
|
||||||
#define VOLTAGE_LOOP_INTERVAL 5000
|
#define VOLTAGE_LOOP_INTERVAL 5000
|
||||||
|
|
||||||
|
#define VOLTAGE_THRESHOLD 3800
|
||||||
|
|
||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
#include "WebContent.h"
|
#include "WebContent.h"
|
||||||
#include "css.h"
|
#include "css.h"
|
||||||
|
|
@ -82,6 +84,8 @@ bool asyncNext = false;
|
||||||
|
|
||||||
bool asyncPrev = false;
|
bool asyncPrev = false;
|
||||||
|
|
||||||
|
uint16_t voltage_threshold_counter = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
std::map<String, String> rfid_map{{"67 152 204 14", "01-The_Box_Tops-The_Letter.mp3"},
|
std::map<String, String> rfid_map{{"67 152 204 14", "01-The_Box_Tops-The_Letter.mp3"},
|
||||||
{"67 175 148 160", "068-Der_Schatz_im_Bergsee"}};
|
{"67 175 148 160", "068-Der_Schatz_im_Bergsee"}};
|
||||||
|
|
@ -360,6 +364,37 @@ void next()
|
||||||
lastInteraction = millis();
|
lastInteraction = millis();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void previous()
|
||||||
|
{
|
||||||
|
if (currentNode != nullptr) {
|
||||||
|
|
||||||
|
const String* curr = currentNode->getCurrentPlaying();
|
||||||
|
DirectoryNode* newNode = currentNode->goToPreviousMP3();
|
||||||
|
|
||||||
|
if (newNode != nullptr) {
|
||||||
|
if (curr == newNode->getCurrentPlaying()) {
|
||||||
|
// reset to 0 seconds playtime:
|
||||||
|
audio.setAudioPlayPosition(0);
|
||||||
|
} else {
|
||||||
|
// Update the current node and start playing the previous song
|
||||||
|
Serial.println("");
|
||||||
|
Serial.print("Playing previous song: ");
|
||||||
|
Serial.println(currentNode->getCurrentPlayingFilePath());
|
||||||
|
currentNode = newNode;
|
||||||
|
stop();
|
||||||
|
deactivateRFID();
|
||||||
|
activateSD();
|
||||||
|
playSongByPath(currentNode->getCurrentPlayingFilePath());
|
||||||
|
deactivateSD();
|
||||||
|
activateRFID();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lastInteraction = millis();
|
||||||
|
}
|
||||||
|
|
||||||
void audio_eof_mp3(const char *info)
|
void audio_eof_mp3(const char *info)
|
||||||
{
|
{
|
||||||
Serial.println("audio file ended.");
|
Serial.println("audio file ended.");
|
||||||
|
|
@ -511,6 +546,12 @@ void setup()
|
||||||
request->send(200, "text/plain", "next");
|
request->send(200, "text/plain", "next");
|
||||||
next(); });
|
next(); });
|
||||||
|
|
||||||
|
server.on("/previous", HTTP_GET, [](AsyncWebServerRequest *request)
|
||||||
|
{
|
||||||
|
|
||||||
|
request->send(200, "text/plain", "previous");
|
||||||
|
previous(); });
|
||||||
|
|
||||||
server.on("/playbyid", HTTP_GET, id_song_action);
|
server.on("/playbyid", HTTP_GET, id_song_action);
|
||||||
|
|
||||||
server.on("/progress", HTTP_POST, progress_action);
|
server.on("/progress", HTTP_POST, progress_action);
|
||||||
|
|
@ -663,7 +704,8 @@ void loop()
|
||||||
else if (asyncPrev)
|
else if (asyncPrev)
|
||||||
{
|
{
|
||||||
asyncPrev = false;
|
asyncPrev = false;
|
||||||
Serial.println("Previous not yet implemented!");
|
Serial.println("Previous");
|
||||||
|
previous();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -682,6 +724,18 @@ void loop()
|
||||||
if (loopCounter % VOLTAGE_LOOP_INTERVAL == 0)
|
if (loopCounter % VOLTAGE_LOOP_INTERVAL == 0)
|
||||||
{
|
{
|
||||||
lastVoltage = getBatteryVoltageMv();
|
lastVoltage = getBatteryVoltageMv();
|
||||||
|
if (lastVoltage<VOLTAGE_THRESHOLD) {
|
||||||
|
if (voltage_threshold_counter>3) {
|
||||||
|
Serial.println("entering deep sleep due to low voltage...");
|
||||||
|
lastInteraction = millis() - sleepMessageDelay;
|
||||||
|
voltage_threshold_counter = 0;
|
||||||
|
} else {
|
||||||
|
voltage_threshold_counter++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
voltage_threshold_counter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
loopCounter++;
|
loopCounter++;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue