Cleanups. Delete+Move works now.

This commit is contained in:
2025-07-27 22:16:35 +02:00
parent 9361bd333f
commit ce4ef44dcd
10 changed files with 118 additions and 439 deletions

View File

@@ -1,4 +1,5 @@
#include "DirectoryNode.h"
#include "globals.h"
DirectoryNode::DirectoryNode(const String &nodeName)
: name(nodeName), currentPlaying(nullptr)
@@ -465,7 +466,7 @@ String DirectoryNode::getCurrentPlayingFilePath() const
{
if (currentPlaying != nullptr)
{
String filePath = "/" + name;
String filePath = name;
if (!filePath.endsWith("/"))
{
filePath += "/";

View File

@@ -5,7 +5,7 @@
#include <vector>
const String sys_dir = "system";

View File

@@ -1,68 +0,0 @@
// HTML web page
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
<title>HannaBox</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta charset="UTF-8">
<link rel='stylesheet' href='/style.css' type='text/css' media='all' />
</head>
<body>
<h1>🎵 HannaBox 🎵</h1>
<span id="state"></span><br/><br/>
<span id="voltage"></span><br/>
<span id="uid"></span><br/>
<span id="heap"></span><br/>
<div>
<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>
<div class="slidecontainer">
<input name="progress" type="range" min="0" max="100" value="0" class="slider" id="progressSlider"
onchange="postValue('progress',document.getElementById('progressSlider').value);lastChange = Date.now();userIsInteracting = false;"
oninput="userIsInteracting = true;"
>
<label for="progress" id="progressLabel"></label>
</div>
<div class="slidecontainer">
<input name="volume" type="range" min="0" max="15" value="7" class="slider" id="volumeSlider"
onchange="postValue('volume',document.getElementById('volumeSlider').value);lastChange = Date.now()"
>
<label for="volume">Vol</label>
</div>
<!--
<button onmouseup="simpleGetCall('stop');" ontouchend="simpleGetCall('stop');">Stop</button>&nbsp;
-->
<p class="playlist-container">
<h2>🎶 Playlist 🎶</h2>
%DIRECTORY%
</p>
<form id="uploadForm" method="POST" action="/upload" enctype="multipart/form-data">
<input type="file" name="data" id="uploadFile" accept=".mp3,.wav,.flac,.m4a,.ogg"/>
<input type="submit" name="upload" value="Upload" title="Upload Audio File" id="uploadButton"/>
<div id="uploadStatus"></div>
<div id="uploadProgress" style="display: none;">
<div class="progress-bar">
<div class="progress-fill" id="progressFill"></div>
</div>
<span id="progressText">0%</span>
</div>
</form>
<h2>Edit RFID Mapping</h2>
<form id="editMappingForm">
<label for="rfid">RFID:</label>
<input type="text" id="rfid" name="rfid" required><br>
<label for="song">Song:</label>
<input type="text" id="song" name="song" required><br>
<button type="button" onclick="editMapping()">Update Mapping</button>
</form>
<script src="/script.js"></script>
</body>
</html>)rawliteral";

View File

@@ -1,3 +0,0 @@
// CSS content moved to SD card at /system/style.css
// This saves approximately 4KB of flash memory
const char css[] PROGMEM = "";

View File

@@ -1,93 +1,23 @@
#ifndef GLOBALS_H_
#define GLOBALS_H_
void stop();
void start();
bool playFile(const char* filename, uint32_t resumeFilePos = 0);
void loop2(void* parameter);
void id_song_action(AsyncWebServerRequest *request);
void progress_action(AsyncWebServerRequest *request);
void volume_action(AsyncWebServerRequest *request);
boolean buttonPressed(const uint8_t pin);
/**
* Helper routine to dump a byte array as hex values to Serial.
*/
void dump_byte_array(byte *buffer, byte bufferSize)
{
for (byte i = 0; i < bufferSize; i++)
{
Serial.print(buffer[i] < 0x10 ? " 0" : " ");
Serial.print(buffer[i], HEX);
}
}
String getRFIDString(byte uidByte[10])
{
String uidString = String(uidByte[0]) + " " + String(uidByte[1]) + " " +
String(uidByte[2]) + " " + String(uidByte[3]);
return uidString;
}
void writeFile(fs::FS &fs, const char * path, const char * message){
Serial.printf("Writing file: %s\n", path);
File file = fs.open(path, FILE_WRITE);
if(!file){
Serial.println("Failed to open file for writing");
return;
}
if(file.print(message)){
Serial.println("File written");
} else {
Serial.println("Write failed");
}
file.close();
}
unsigned long lastStart = 0;
unsigned long lastInteraction = 0;
boolean sleepSoundPlayed = false;
boolean startupSoundPlayed = false;
boolean continuousMode = false;
uint8_t buttontoignore = 0;
uint32_t lastVoltage = 0;
uint loopCounter = 0;
String lastUid = "";
uint16_t currentSongId = 0;
uint32_t currentSongSeconds = 0;
boolean continuePlaying = false;
boolean prepareSleepMode = false;
const String sys_dir = "system";
const String sleep_sound = "sleep.mp3";
const String startup_sound = "start.mp3";
const String mapping_file = "/mapping.txt";
const String mapping_file = "mapping.txt";
const String progress_file = "progress.txt";
std::map<String, String> rfid_map;
/*
const long sleepMessageDelay = 28000;

View File

@@ -47,14 +47,9 @@
#define MAX_VOL 15
#include "globals.h"
#include "WebContent.h"
#include "main.h"
#include "DirectoryNode.h"
#define SOUND_STARTUP "start.mp3"
#define SOUND_SLEEP "sleep.mp3"
File root;
File mp3File;
@@ -280,7 +275,7 @@ void handleDeleteFile(AsyncWebServerRequest *request) {
String filename = request->arg("filename");
if (SD.exists(filename)) {
SD.remove(filename.c_str());
SD.remove(filename);
Serial.println("Deleted file: " + filename);
request->send(200, "text/plain", "File deleted successfully.");
} else {
@@ -492,7 +487,7 @@ String getState()
}
// Function to save the rfid_map to the mapping file
void saveMappingToFile(const char *filename) {
void saveMappingToFile(const String filename) {
File file = SD.open(filename, FILE_WRITE);
if (file) {
for (const auto &pair : rfid_map) {
@@ -511,7 +506,7 @@ void editMapping(AsyncWebServerRequest *request) {
String rfid = request->getParam("rfid", true)->value();
String song = request->getParam("song", true)->value();
rfid_map[rfid] = song;
saveMappingToFile(mapping_file.c_str());
saveMappingToFile(getSysDir(mapping_file));
request->send(200, "text/plain", "Mapping updated");
} else {
request->send(400, "text/plain", "Invalid parameters");
@@ -752,7 +747,7 @@ void setup()
String progressPath = "/"+sys_dir+"/"+progress_file;
String progressPath = getSysDir(progress_file);
continuePlaying = readSongProgress(progressPath.c_str());
@@ -824,14 +819,14 @@ void setup()
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request)
{
webrequestActive = true;
String htmlPath = "/system/index.html";
String htmlPath = getSysDir("index.html");
if (SD.exists(htmlPath)) {
AsyncWebServerResponse *response = request->beginResponse(SD, htmlPath, "text/html", false, processor);
response->addHeader("Content-Type", "text/html; charset=UTF-8");
request->send(response);
} else {
// Fallback: serve minimal error if file not found
request->send(200, "text/plain", "ERROR: /system/index.html on SD Card not found!");
request->send(404, "text/plain", "ERROR: /system/index.html on SD Card not found!");
}
webrequestActive = false;
@@ -840,12 +835,12 @@ void setup()
server.on("/style.css", HTTP_GET, [](AsyncWebServerRequest *request)
{
webrequestActive = true;
String cssPath = "/system/style.css";
String cssPath = getSysDir("style.css");
if (SD.exists(cssPath)) {
request->send(SD, cssPath, "text/css");
} else {
// Fallback: serve minimal CSS if file not found
request->send(200, "text/css", "body{font-family:Arial;text-align:center;padding:20px;}");
request->send(404, "text/plain", "ERROR: /system/style.css on SD Card not found!");
}
webrequestActive = false;
@@ -856,12 +851,12 @@ void setup()
webrequestActive = true;
deactivateRFID();
activateSD();
String jsPath = "/system/script.js";
String jsPath = getSysDir("script.js");
if (SD.exists(jsPath)) {
request->send(SD, jsPath, "application/javascript");
} else {
// Fallback: serve minimal JS if file not found
request->send(200, "application/javascript", "console.log('JavaScript file not found on SD card');");
request->send(404, "text/plain", "ERROR: /system/script.js on SD Card not found!");
}
webrequestActive = false;
@@ -990,9 +985,9 @@ void volume_action(AsyncWebServerRequest *request)
request->send_P(200, "text/plain", "ok");
}
String getStartupSoundDir() {
static String tempPath = "/"+sys_dir+"/"+startup_sound;
return tempPath;
const String getSysDir(const String filename) {
return "/"+sys_dir+"/"+filename;
}
void loop()
@@ -1022,7 +1017,7 @@ void loop()
playSongById(currentSongId,currentSongSeconds);
} else if (!startupSoundPlayed) {
startupSoundPlayed = true;
playSongByPath(getStartupSoundDir().c_str());
playSongByPath(getSysDir(startup_sound));
}
@@ -1034,12 +1029,12 @@ void loop()
sleepSoundPlayed = true;
prepareSleepMode = true;
if (currentNode != NULL) {
String progressPath = "/"+sys_dir+"/"+progress_file;
String progressPath = getSysDir(progress_file);
writeSongProgress(progressPath.c_str(),currentNode->getCurrentPlayingId(),currentNode->getSecondsPlayed());
}
String tempPath = "/"+sys_dir+"/"+sleep_sound;
String tempPath = getSysDir(sleep_sound);
playSongByPath(tempPath.c_str());
}
@@ -1067,7 +1062,7 @@ void loop()
vol++;
}
audio.setVolume(vol);
playSongByPath(getStartupSoundDir().c_str());
playSongByPath(getSysDir(startup_sound));
}
@@ -1083,7 +1078,7 @@ void loop()
vol--;
}
audio.setVolume(vol);
playSongByPath(getStartupSoundDir().c_str());
playSongByPath(getSysDir(startup_sound));
}
}

85
src/main.h Normal file
View File

@@ -0,0 +1,85 @@
#ifndef MAIN_H_
#define MAIN_H_
void stop();
void start();
bool playFile(const char* filename, uint32_t resumeFilePos = 0);
void loop2(void* parameter);
void id_song_action(AsyncWebServerRequest *request);
void progress_action(AsyncWebServerRequest *request);
void volume_action(AsyncWebServerRequest *request);
boolean buttonPressed(const uint8_t pin);
const String getSysDir(const String filename);
/**
* Helper routine to dump a byte array as hex values to Serial.
*/
void dump_byte_array(byte *buffer, byte bufferSize)
{
for (byte i = 0; i < bufferSize; i++)
{
Serial.print(buffer[i] < 0x10 ? " 0" : " ");
Serial.print(buffer[i], HEX);
}
}
String getRFIDString(byte uidByte[10])
{
String uidString = String(uidByte[0]) + " " + String(uidByte[1]) + " " +
String(uidByte[2]) + " " + String(uidByte[3]);
return uidString;
}
void writeFile(fs::FS &fs, const char * path, const char * message){
Serial.printf("Writing file: %s\n", path);
File file = fs.open(path, FILE_WRITE);
if(!file){
Serial.println("Failed to open file for writing");
return;
}
if(file.print(message)){
Serial.println("File written");
} else {
Serial.println("Write failed");
}
file.close();
}
unsigned long lastStart = 0;
unsigned long lastInteraction = 0;
boolean sleepSoundPlayed = false;
boolean startupSoundPlayed = false;
boolean continuousMode = false;
uint8_t buttontoignore = 0;
uint32_t lastVoltage = 0;
uint loopCounter = 0;
String lastUid = "";
uint16_t currentSongId = 0;
uint32_t currentSongSeconds = 0;
boolean continuePlaying = false;
boolean prepareSleepMode = false;
std::map<String, String> rfid_map;
#endif