not or it but ADD IT? THIS WAS NOT WRITTEN BY AI, THIS IS CLOWN PRODUCTION

This commit is contained in:
2026-01-05 19:30:23 +01:00
parent bfe5a41ea3
commit 8d76a0054f
12 changed files with 401 additions and 581 deletions

View File

@@ -15,7 +15,6 @@ void handleRoot() {
html += "<meta charset=\"UTF-8\">";
html += "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">";
// Add CSS styling
html += "<style>";
html += "body {background-color: rgb(32, 34, 40); color: white; font-family: 'Arial', sans-serif;}";
html += "h1 {text-align: center; margin-top: 20px;font-size: 32px;}";
@@ -39,7 +38,6 @@ void handleRoot() {
html += "</style>";
html += "</head><body>";
// Add logo as a clickable link
html += "<a href=\"https://fmdx.org/\" target=\"_blank\">";
html += "<img src=\"/logo.png\" alt=\"FMDX website\">";
html += "</a>";
@@ -130,7 +128,6 @@ void handleRoot() {
if (endIndex == -1) endIndex = line.length();
String cell = line.substring(startIndex, endIndex);
// Extract PI code and Frequency
if (columnIndex == piCodeIndex) piCode = cell;
if (columnIndex == frequencyIndex) frequency = cell;
@@ -139,23 +136,17 @@ void handleRoot() {
columnIndex++;
}
// Remove " MHz" from Frequency
frequency.replace(" MHz", "");
// Make row clickable
html += "<td><a href =\"https://maps.fmdx.org/#qth=&freq=" + frequency + "&findPi=" + piCode + "\"target=\"_blank\">🌐</a></td>";
html += "</tr>";
}
}
file.close();
} else {
html += "<tr><td colspan=\"100%\" style=\"text-align: center; color: red;\">" + String(textUI(299)) + "</td></tr>";
}
} else html += "<tr><td colspan=\"100%\" style=\"text-align: center; color: red;\">" + String(textUI(299)) + "</td></tr>";
if (!hasData) {
html += "<tr><td colspan=\"100%\" style=\"text-align: center; color: red;\">" + String(textUI(288)) + "</td></tr>";
}
if (!hasData) html += "<tr><td colspan=\"100%\" style=\"text-align: center; color: red;\">" + String(textUI(288)) + "</td></tr>";
html += "</table>";
html += "</body></html>";
@@ -164,45 +155,30 @@ void handleRoot() {
}
void handleDownloadCSV() {
// Attempt to open the CSV file from SPIFFS in read mode
fs::File file = SPIFFS.open("/logbook.csv", "r");
// Check if the file was successfully opened
if (!file) {
// If the file could not be opened, send an error response
webserver.send(500, "text/plain", "Failed to open logbook for download");
return; // Exit the function if the file cannot be opened
return;
}
// Set the headers to specify that the response will be a CSV file for download
webserver.sendHeader("Content-Type", "text/csv"); // Set MIME type for CSV files
webserver.sendHeader("Content-Disposition", "attachment; filename=logbook.csv"); // Suggests the file name for download
webserver.sendHeader("Content-Type", "text/csv");
webserver.sendHeader("Content-Disposition", "attachment; filename=logbook.csv");
// Stream the CSV file content directly to the browser
webserver.streamFile(file, "text/csv");
// Close the file after streaming the content to release resources
file.close();
}
bool handleCreateNewLogbook() {
// Check if the file "logbook.csv" already exists
if (SPIFFS.exists("/logbook.csv")) {
// If it exists, delete the file
if (!SPIFFS.remove("/logbook.csv")) {
return false;
}
if (!SPIFFS.remove("/logbook.csv")) return false;
}
// Create a new "logbook.csv" file in write mode
fs::File file = SPIFFS.open("/logbook.csv", "w");
if (!file) {
return false;
}
if (!file) return false;
// Write the header to the new CSV file
String header = "Date,Time,Frequency,PI,Signal,Stereo,TA,TP,PTY,ECC,PS,Radiotext\n";
file.print(header);
file.print("Date,Time,Frequency,PI,Signal,Stereo,TA,TP,PTY,ECC,PS,Radiotext\n");
file.flush();
file.close();
@@ -215,33 +191,18 @@ bool handleCreateNewLogbook() {
}
byte addRowToCSV() {
// Ensure there is at least 150 bytes of free space in SPIFFS before proceeding
if (SPIFFS.totalBytes() - SPIFFS.usedBytes() < 150 || logcounter > 1500) {
return 2; // Return 2 if insufficient free space is available
}
if (SPIFFS.totalBytes() - SPIFFS.usedBytes() < 150 || logcounter > 1500) return 2;
// Open the "logbook.csv" file in append mode
fs::File file = SPIFFS.open("/logbook.csv", "a");
// Check if the file could not be opened
if (!file) {
return 1; // Return 1 if the file cannot be opened
}
if (!file) return 1;
// Fetch the current date and time as a string
String currentDateTime = getCurrentDateTime(false);
if (currentDateTime == "") currentDateTime = "-,-";
// Use a placeholder ("-,-") if the date and time could not be retrieved
if (currentDateTime == "") {
currentDateTime = "-,-";
}
// Prepare the frequency in a formatted string (e.g., "XX.XX MHz")
int freqInt = (band == BAND_OIRT) ? (int)frequency_OIRT : (int)frequency;
int adjustedFreq = freqInt + (band != BAND_OIRT ? ConverterSet * 100 : 0);
String frequencyFormatted = String(adjustedFreq / 100) + "." +
((adjustedFreq % 100 < 10) ? "0" : "") +
String(adjustedFreq % 100) + " MHz";
String frequencyFormatted = String(adjustedFreq / 100) + "." + ((adjustedFreq % 100 < 10) ? "0" : "") + String(adjustedFreq % 100) + " MHz";
// Calculate signal strength based on the selected unit
int SStatusPrint = 0;
@@ -249,126 +210,87 @@ byte addRowToCSV() {
else if (unit == 1) SStatusPrint = ((SStatus * 100) + 10875) / 100; // dBf
else if (unit == 2) SStatusPrint = round((float(SStatus) / 10.0 - 10.0 * log10(75) - 90.0) * 10.0); // dBm
// Format the signal strength with appropriate decimal places and unit
String signal = String(SStatusPrint / 10) + "." + String(abs(SStatusPrint % 10));
if (unit == 0) signal += " dBμV";
else if (unit == 1) signal += " dBf";
else if (unit == 2) signal += " dBm";
// Prepare the radio text with station information, including enhanced options if available
String radioText = String(radio.rds.stationText + " " + radio.rds.stationText32);
if (radio.rds.hasEnhancedRT) {
radioText += " eRT: " + String(radio.rds.enhancedRTtext);
}
if (radio.rds.hasEnhancedRT) radioText += " eRT: " + String(radio.rds.enhancedRTtext);
// Replace commas in the station name and radio text to avoid CSV conflicts
String stationName = radio.rds.stationName;
String radioTextModified = (scanhold > 4 ? radioText : "");
stationName.replace(",", " "); // Replace commas in station name
radioTextModified.replace(",", " "); // Replace commas in radio text
stationName.replace(",", " ");
radioTextModified.replace(",", " ");
// Handle ECC, PTY, TA, TP, and Stereo flag
String TA = radio.rds.hasTA ? "" : " ";
String TP = radio.rds.hasTP ? "" : " ";
String TP = radio.rds.TP ? "" : " ";
String Stereo = radio.getStereoStatus() ? "" : " ";
String pty = String(radio.rds.stationTypeCode);
String pty = String(radio.rds.PTY);
String ECC = "--";
if (radio.rds.hasECC) {
char eccBuffer[3]; // Buffer to hold 2-digit hex value + null terminator
char eccBuffer[3];
snprintf(eccBuffer, sizeof(eccBuffer), "%02X", radio.rds.ECC); // Format ECC as uppercase 2-digit hex
ECC = String(eccBuffer);
}
// Construct the CSV row data
String row = currentDateTime + "," +
frequencyFormatted + "," +
String(radio.rds.picode).substring(0, 4) + "," +
signal + "," +
Stereo + "," +
TA + "," +
TP + "," +
pty + "," +
ECC + "," +
stationName + "," +
radioTextModified + "\n";
String row = currentDateTime + "," + frequencyFormatted + "," + String(radio.rds.picode).substring(0, 4) + "," + signal + "," + Stereo + "," + TA + "," + TP + "," + pty + "," + ECC + "," + stationName + "," + radioTextModified + "\n";
// Write the row to the file and close it
if (file.print(row)) {
file.close(); // Successfully wrote to the file
file.close();
logcounter++;
EEPROM.writeUInt(EE_UINT16_LOGCOUNTER, logcounter);
EEPROM.commit();
return 0; // Return 0 to indicate success
return 0;
} else {
file.close(); // Close the file if writing fails
return 1; // Return 1 to indicate failure
file.close();
return 1;
}
}
String getCurrentDateTime(bool inUTC) {
// Check if the RTC has been set
if (!rtcset) {
return "-,-"; // Return placeholder when the RTC is not set
}
if (!rtcset) return "-,-";
// Use the ESP32's time functions to retrieve the current time
struct tm timeInfo;
if (!getLocalTime(&timeInfo)) {
return "-,-"; // Return placeholder if local time is unavailable
}
if (!getLocalTime(&timeInfo)) return "-,-";
// Convert struct tm to time_t format
time_t currentEpoch = mktime(&timeInfo);
// Determine UTC offset as a number
int utcOffsetHours = 0;
if (!inUTC) {
// Adjust for time zone offset and DST if not in UTC
currentEpoch += (NTPupdated ? NTPoffset * 3600 : radio.rds.offset); // Apply GMT offset if NTPupdated, else RDS offset
// Apply DST adjustment if NTPupdated and autoDST are true
if (NTPupdated && autoDST) {
struct tm tempTimeInfo;
localtime_r(&currentEpoch, &tempTimeInfo); // Convert to struct tm for DST calculation
if (isDST(mktime(&tempTimeInfo))) { // Check if DST is in effect
currentEpoch += 3600; // Add 1-hour DST offset
}
localtime_r(&currentEpoch, &tempTimeInfo);
if (isDST(mktime(&tempTimeInfo))) currentEpoch += 3600;
}
} else utcOffsetHours = (NTPupdated ? NTPoffset : radio.rds.offset / 3600);
// Convert adjusted (or original) time back to struct tm format
localtime_r(&currentEpoch, &timeInfo);
// Buffer for formatted date-time string
char buf[20];
if (clockampm) {
// USA format: MM/DD/YYYY, HH:MM:SS AM/PM
strftime(buf, sizeof(buf), "%m/%d/%Y", &timeInfo); // Format as MM/DD/YYYY
strftime(buf, sizeof(buf), "%m/%d/%Y", &timeInfo);
// Format time in 12-hour format with AM/PM
int hour = timeInfo.tm_hour;
String ampm = (hour >= 12) ? "PM" : "AM"; // Determine AM or PM
if (hour == 0) hour = 12; // Convert 0 hour to 12 AM
else if (hour > 12) hour -= 12; // Convert to 12-hour format for PM
String ampm = (hour >= 12) ? "PM" : "AM";
if (hour == 0) hour = 12;
else if (hour > 12) hour -= 12;
String timeWithAMPM = String(hour) + ":" + (timeInfo.tm_min < 10 ? "0" : "") + String(timeInfo.tm_min) + ":" + (timeInfo.tm_sec < 10 ? "0" : "") + String(timeInfo.tm_sec) + " " + ampm;
// Append UTC offset if inUTC
if (inUTC) {
String utcOffsetStr = ", " + String(utcOffsetHours) + ",";
return String(buf) + "," + timeWithAMPM + utcOffsetStr;
}
// Return the final formatted date and time for the USA region
return String(buf) + "," + timeWithAMPM;
} else {
// European format: DD-MM-YYYY, HH:MM:SS
strftime(buf, sizeof(buf), "%d-%m-%Y", &timeInfo); // Format as DD-MM-YYYY
strftime(buf, sizeof(buf), "%d-%m-%Y", &timeInfo);
String timeEuropean = String(timeInfo.tm_hour) + ":" + (timeInfo.tm_min < 10 ? "0" : "") + String(timeInfo.tm_min) + ":" + (timeInfo.tm_sec < 10 ? "0" : "") + String(timeInfo.tm_sec); // Format time with leading zero if needed
// Append UTC offset if inUTC
if (inUTC) {
String utcOffsetStr = ", " + String(utcOffsetHours) + ",";
return String(buf) + "," + timeEuropean + utcOffsetStr;
@@ -380,33 +302,24 @@ String getCurrentDateTime(bool inUTC) {
bool isDST(time_t t) {
struct tm timeInfo;
localtime_r(&t, &timeInfo); // Convert time_t to struct tm
localtime_r(&t, &timeInfo);
int month = timeInfo.tm_mon + 1; // tm_mon is 0-based, so add 1
int day = timeInfo.tm_mday; // tm_mday is the day of the month
int hour = timeInfo.tm_hour; // tm_hour is the hour of the day
int weekday = timeInfo.tm_wday; // tm_wday is the day of the week (0 = Sunday)
int month = timeInfo.tm_mon + 1;
int day = timeInfo.tm_mday;
int hour = timeInfo.tm_hour;
int weekday = timeInfo.tm_wday;
// DST starts last Sunday in March at 2:00 AM
if (month == 3) {
int lastSunday = 31 - ((weekday + 31 - day) % 7);
if (day > lastSunday || (day == lastSunday && hour >= 2)) {
return true;
}
if (day > lastSunday || (day == lastSunday && hour >= 2)) return true;
}
// DST ends last Sunday in October at 3:00 AM
if (month == 10) {
int lastSunday = 31 - ((weekday + 31 - day) % 7);
if (day < lastSunday || (day == lastSunday && hour < 3)) {
return false;
}
if (day < lastSunday || (day == lastSunday && hour < 3)) return false;
}
// DST is active from April to September
if (month > 3 && month < 10) {
return true;
}
if (month > 3 && month < 10) return true;
return false;
}
@@ -422,48 +335,34 @@ void handleLogo() {
}
void printLogbookCSV() {
// Attempt to open the CSV file stored in SPIFFS
fs::File file = SPIFFS.open("/logbook.csv", "r");
// Check if the file was successfully opened
if (!file) {
Serial.println("Failed to open logbook!");
return;
}
// Print a message indicating the start of the file content
Serial.println("===== Start of logbook.csv =====");
// Read and print the contents of the file line by line
while (file.available()) {
String line = file.readStringUntil('\n'); // Read one line at a time
Serial.println(line); // Print the line to the Serial Monitor
String line = file.readStringUntil('\n');
Serial.println(line);
}
// Close the file after reading
file.close();
// Print a message indicating the end of the file content
Serial.println("===== End of logbook.csv =====");
}
void sendUDPlog() {
// Get the current date and time as a string
String currentDateTime = getCurrentDateTime(true);
// Use a placeholder if the date and time could not be retrieved
if (currentDateTime == "") {
currentDateTime = "-,-";
}
if (currentDateTime == "") currentDateTime = "-,-";
// Format the frequency, adjusting based on the band and converter settings
int freqInt = (band == BAND_OIRT) ? (int)frequency_OIRT : (int)frequency;
int adjustedFreq = freqInt + (band != BAND_OIRT ? ConverterSet * 100 : 0);
String frequencyFormatted = String(adjustedFreq / 100) + "." +
((adjustedFreq % 100 < 10) ? "0" : "") +
String(adjustedFreq % 100);
String frequencyFormatted = String(adjustedFreq / 100) + "." + ((adjustedFreq % 100 < 10) ? "0" : "") + String(adjustedFreq % 100);
// Calculate signal strength and format it with the selected unit
int SStatusPrint = 0;
if (unit == 0) SStatusPrint = SStatus; // dBμV
else if (unit == 1) SStatusPrint = ((SStatus * 100) + 10875) / 100; // dBf
@@ -474,19 +373,14 @@ void sendUDPlog() {
else if (unit == 1) signal += " dBf";
else if (unit == 2) signal += " dBm";
// Prepare the radio text with RDS station information and enhanced options
String radioText = String(radio.rds.stationText + " " + radio.rds.stationText32);
if (radio.rds.hasEnhancedRT) {
radioText += " eRT: " + String(radio.rds.enhancedRTtext);
}
if (radio.rds.hasEnhancedRT) radioText += " eRT: " + String(radio.rds.enhancedRTtext);
// Replace commas in the station name and radio text to avoid conflicts in the CSV format
String stationName = radio.rds.stationName;
stationName.replace(",", " ");
String radioTextModified = radioText;
radioTextModified.replace(",", " ");
// Extract and format ECC (Extended Country Code) if available
String ECC = "";
if (radio.rds.hasECC) {
char eccBuffer[3];
@@ -494,16 +388,13 @@ void sendUDPlog() {
ECC = String(eccBuffer);
}
// Format the list of Alternative Frequencies (AF) if available
String AF = "";
if (radio.rds.hasAF && radio.af_counter > 0) {
for (byte i = 0; i < radio.af_counter; i++) {
AF += String(radio.af[i].frequency / 100) + "." + String((radio.af[i].frequency % 100) / 10) +
(i == radio.af_counter - 1 ? "" : ";");
AF += String(radio.af[i].frequency / 100) + "." + String((radio.af[i].frequency % 100) / 10) + (i == radio.af_counter - 1 ? "" : ";");
}
}
// Format Enhanced Other Networks (EON) data if available
String EON = "";
if (radio.eon_counter > 0) {
for (byte i = 0; i < radio.eon_counter; i++) {
@@ -516,7 +407,6 @@ void sendUDPlog() {
}
}
// set Chipmodel
String CHIP = "";
switch (chipmodel) {
case 0: CHIP = "TEF6686"; break;
@@ -525,11 +415,8 @@ void sendUDPlog() {
case 3: CHIP = "TEF6689"; break;
}
// Extract RT+ (RadioText Plus) content if available
String RTPLUS = "";
if (radio.rds.hasRDSplus) {
RTPLUS += radio.rds.RTContent1 + ";" + radio.rds.RTContent2;
}
if (radio.rds.hasRTplus) RTPLUS += radio.rds.RTContent1 + ";" + radio.rds.RTContent2;
// Construct the data row to send via UDP
String row = CHIP + "," +
@@ -541,9 +428,9 @@ void sendUDPlog() {
signal + "," +
String(radio.getStereoStatus()) + "," +
String(radio.rds.hasTA) + "," +
String(radio.rds.hasTP) + "," +
String(radio.rds.TP) + "," +
String(radio.rds.hasTMC) + "," +
String(radio.rds.stationTypeCode) + "," +
String(radio.rds.PTY) + "," +
ECC + "," +
stationName + "," +
radioTextModified + "," +