Previous, low voltage sleep

This commit is contained in:
Stefan Ostermann 2023-12-03 20:03:18 +01:00
parent 5814a73f50
commit 83b5e1c5e9
4 changed files with 151 additions and 42 deletions

View File

@ -1,11 +1,11 @@
#include "DirectoryNode.h"
DirectoryNode::DirectoryNode(const String &nodeName)
: name(nodeName), currentPlaying(nullptr) {
id = DirectoryNode::idCounter;
DirectoryNode::idCounter++;
}
: name(nodeName), currentPlaying(nullptr)
{
id = DirectoryNode::idCounter;
DirectoryNode::idCounter++;
}
DirectoryNode::~DirectoryNode()
{
@ -15,7 +15,6 @@ DirectoryNode::~DirectoryNode()
}
}
const uint16_t DirectoryNode::getId() const
{
return id;
@ -39,8 +38,10 @@ const std::vector<String> &DirectoryNode::getMP3Files() const
void DirectoryNode::setCurrentPlaying(const String *mp3File)
{
currentPlaying = mp3File;
for (int i=0;i<mp3Files.size();i++) {
if (mp3Files[i] == *mp3File && ids.size()>i) {
for (int i = 0; i < mp3Files.size(); i++)
{
if (mp3Files[i] == *mp3File && ids.size() > i)
{
currentPlayingId = ids[i];
}
}
@ -56,7 +57,8 @@ const uint16_t DirectoryNode::getCurrentPlayingId() const
return currentPlayingId;
}
uint16_t DirectoryNode::getNextId() {
uint16_t DirectoryNode::getNextId()
{
uint16_t next = DirectoryNode::idCounter;
DirectoryNode::idCounter++;
return next;
@ -70,14 +72,16 @@ void DirectoryNode::addSubdirectory(DirectoryNode *subdirectory)
void DirectoryNode::addMP3File(const String &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;
}
uint32_t DirectoryNode::getSecondsPlayed() {
uint32_t DirectoryNode::getSecondsPlayed()
{
return secondsPlayed;
}
@ -92,7 +96,7 @@ void DirectoryNode::buildDirectoryTree(const char *currentPath)
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());
subdirectories.push_back(newNode);
@ -153,20 +157,23 @@ DirectoryNode *DirectoryNode::findFirstDirectoryWithMP3s()
return nullptr;
}
void DirectoryNode::advanceToFirstMP3InThisNode() {
if (mp3Files.size()>0) {
void DirectoryNode::advanceToFirstMP3InThisNode()
{
if (mp3Files.size() > 0)
{
setCurrentPlaying(&mp3Files[0]);
}
}
DirectoryNode* DirectoryNode::advanceToMP3(const uint16_t id) {
for (auto subdir : subdirectories)
DirectoryNode *DirectoryNode::advanceToMP3(const uint16_t id)
{
for (auto subdir : subdirectories)
{
if (subdir->getId()==id) {
if (subdir->getId() == id)
{
subdir->advanceToFirstMP3InThisNode();
return subdir;
}
}
// Have each subdirectory advance its song
for (size_t i = 0; i < subdir->ids.size(); i++)
@ -179,8 +186,7 @@ for (auto subdir : subdirectories)
subdir->currentPlaying = &subdir->mp3Files[i];
subdir->currentPlayingId = id;
return subdir;
}
}
}
}
}
@ -191,14 +197,15 @@ for (auto subdir : subdirectories)
return this;
}
DirectoryNode* DirectoryNode::advanceToMP3(const String* currentGlobal) {
DirectoryNode *DirectoryNode::advanceToMP3(const String *currentGlobal)
{
for (auto subdir : subdirectories)
{
if (subdir->getName()==*currentGlobal) {
if (subdir->getName() == *currentGlobal)
{
subdir->advanceToFirstMP3InThisNode();
return subdir;
}
}
// Have each subdirectory advance its song
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]);
return subdir;
}
}
}
}
}
@ -222,7 +228,50 @@ DirectoryNode* DirectoryNode::advanceToMP3(const String* currentGlobal) {
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;
Serial.println(currentGlobal->c_str());
@ -230,7 +279,7 @@ DirectoryNode* DirectoryNode::advanceToNextMP3(const String* currentGlobal)
{
for (size_t i = 0; i < mp3Files.size(); i++)
{
if (*currentGlobal==mp3Files[i])
if (*currentGlobal == mp3Files[i])
{
// Found the current playing MP3 file
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.
// Therefore, we need to recursively look in our subdirectories.
for (auto subdir : subdirectories)
{
if (useFirst && subdir->mp3Files.size()>0) {
if (useFirst && subdir->mp3Files.size() > 0)
{
subdir->setCurrentPlaying(&subdir->mp3Files[0]);
return subdir;
}
@ -268,7 +317,9 @@ DirectoryNode* DirectoryNode::advanceToNextMP3(const String* currentGlobal)
// Advance to the next MP3 file in the same directory
subdir->setCurrentPlaying(&subdir->mp3Files[i + 1]);
return subdir;
} else {
}
else
{
useFirst = true;
}
// Reached the end of the MP3 files in the directory
@ -287,24 +338,27 @@ String DirectoryNode::getDirectoryStructureHTML() const
{
String html;
html.reserve(1024); // Reserve memory for better performance
if (name=="/") {
if (name == "/")
{
html += "<ul>\n";
}
if (name!="/") {
html += "<li data-id=\""+String(id)+"\"><b>" + name + "</b></li>\n";
if (name != "/")
{
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)
{
html += childNode->getDirectoryStructureHTML();
}
if (name=="/") {
if (name == "/")
{
html += "</ul>\n";
}

View File

@ -49,6 +49,7 @@ public:
void printDirectoryTree(int level = 0) const;
DirectoryNode* advanceToMP3(const String* currentGlobal);
DirectoryNode* advanceToNextMP3(const String* currentGlobal);
DirectoryNode* goToPreviousMP3(uint32_t thresholdSeconds = 3);
DirectoryNode* advanceToMP3(const uint16_t id);
void advanceToFirstMP3InThisNode();
String getDirectoryStructureHTML() const;

View File

@ -14,7 +14,7 @@ const char index_html[] PROGMEM = R"rawliteral(
<span id="uid"></span><br/>
<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="next-button" onclick="simpleGetCall('next');"></button><br/><br/>
</div>

View File

@ -37,6 +37,8 @@
#define VOLTAGE_LOOP_INTERVAL 5000
#define VOLTAGE_THRESHOLD 3800
#include "globals.h"
#include "WebContent.h"
#include "css.h"
@ -82,6 +84,8 @@ bool asyncNext = 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"},
{"67 175 148 160", "068-Der_Schatz_im_Bergsee"}};
@ -360,6 +364,37 @@ void next()
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)
{
Serial.println("audio file ended.");
@ -511,6 +546,12 @@ void setup()
request->send(200, "text/plain", "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("/progress", HTTP_POST, progress_action);
@ -663,7 +704,8 @@ void loop()
else if (asyncPrev)
{
asyncPrev = false;
Serial.println("Previous not yet implemented!");
Serial.println("Previous");
previous();
}
@ -682,6 +724,18 @@ void loop()
if (loopCounter % VOLTAGE_LOOP_INTERVAL == 0)
{
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++;