Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion include/config/extern/configManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ class configManager
void setValuesFromConfig();
bool validateStringNotEmpty(const std::string &value);
void parseConfig();
void parseComplexConfig(std::ifstream &configFile, const std::string &section);

enum class DriveMode
{
Expand Down Expand Up @@ -142,6 +141,12 @@ class configManager

void readMaintenanceData();
void writeMaintenanceData();

// VEX API helper functions
std::string readFileToString(const std::string &filename);
bool writeStringToFile(const std::string &filename, const std::string &content, bool append = false);
bool fileExists(const std::string &filename);
int getFileSize(const std::string &filename);
};

/// @brief Manages configuration settings.
Expand Down
1 change: 0 additions & 1 deletion include/vex.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#include <stdlib.h>
#include <map>

#include "v5_cpp.h"
Expand Down
98 changes: 97 additions & 1 deletion src/config/extern/configManager.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#include "vex.h"
#include <fstream>
#include <memory>

std::array<ControllerButtonInfo, 12> createControllerButtonArray(const vex::controller &controller)
{
Expand Down Expand Up @@ -308,4 +308,100 @@ Log::Level configManager::stringToLogLevel(const std::string &str)
logHandler("configManager::stringToLogLevel", "Invalid log level", Log::Level::Error, 5);
return Log::Level::Info; // Default return to avoid compilation error
}
}

// VEX API helper functions
std::string configManager::readFileToString(const std::string &filename)
{
if (!Brain.SDcard.isInserted())
{
logHandler("readFileToString", "SD card not inserted", Log::Level::Error);
return "";
}

if (!Brain.SDcard.exists(filename.c_str()))
{
logHandler("readFileToString", "File does not exist: " + filename, Log::Level::Warn);
return "";
}

int size = Brain.SDcard.size(filename.c_str());
if (size <= 0)
{
logHandler("readFileToString", "File is empty or invalid size: " + filename, Log::Level::Warn);
return "";
}

// Allocate buffer for file content
std::unique_ptr<char[]> buffer(new char[size + 1]);
if (!buffer)
{
logHandler("readFileToString", "Failed to allocate buffer for file: " + filename, Log::Level::Error);
return "";
}

// Load file into buffer
int bytesRead = Brain.SDcard.loadfile(filename.c_str(), buffer.get(), size);
if (bytesRead <= 0)
{
logHandler("readFileToString", "Failed to read file: " + filename, Log::Level::Error);
return "";
}

// Null terminate the buffer
buffer[bytesRead] = '\0';

return std::string(buffer.get());
}

bool configManager::writeStringToFile(const std::string &filename, const std::string &content, bool append)
{
if (!Brain.SDcard.isInserted())
{
logHandler("writeStringToFile", "SD card not inserted", Log::Level::Error);
return false;
}

int bytesWritten = 0;
if (append)
{
bytesWritten = Brain.SDcard.appendfile(filename.c_str(), const_cast<char*>(content.c_str()), content.length());
}
else
{
bytesWritten = Brain.SDcard.savefile(filename.c_str(), const_cast<char*>(content.c_str()), content.length());
}

if (bytesWritten != static_cast<int>(content.length()))
{
logHandler("writeStringToFile", "Failed to write complete content to file: " + filename, Log::Level::Error);
return false;
}

return true;
}

bool configManager::fileExists(const std::string &filename)
{
if (!Brain.SDcard.isInserted())
{
return false;
}

return Brain.SDcard.exists(filename.c_str());
}

int configManager::getFileSize(const std::string &filename)
{
if (!Brain.SDcard.isInserted())
{
return -1;
}

if (!Brain.SDcard.exists(filename.c_str()))
{
return -1;
}

return Brain.SDcard.size(filename.c_str());
}
131 changes: 63 additions & 68 deletions src/config/extern/sdcard.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#include "vex.h"
#include <fstream>
#include <sstream>

/**
* @brief Resets or initializes the configuration file based on user input.
Expand Down Expand Up @@ -29,14 +29,9 @@ void configManager::resetOrInitializeConfig(std::string_view message)
if (resetcfg == "Yes")
{
primaryController.Screen.print("Resetting config file...");
std::ofstream configFile(configFileName);
if (!configFile)
{
logHandler("resetOrInitializeConfig", "Could not create config.", Log::Level::Warn, 3);
return;
}
// Write default configuration
configFile << R"(

// Create default configuration content
std::string configContent = R"(
# Config File:
MOTOR_CONFIG {
FRONT_LEFT_MOTOR {
Expand Down Expand Up @@ -80,9 +75,13 @@ void configManager::resetOrInitializeConfig(std::string_view message)
DRIVEMODE=Split
LEFTDEADZONE=10
RIGHTDEADZONE=10
VERSION=)" << Version
<< "\n";
configFile.close();
VERSION=)" + Version + "\n";

if (!writeStringToFile(configFileName, configContent))
{
logHandler("resetOrInitializeConfig", "Could not create config.", Log::Level::Warn, 3);
return;
}

logHandler("resetConfig", "Successfully reset config file.", Log::Level::Debug);
}
Expand All @@ -101,14 +100,11 @@ void configManager::resetOrInitializeConfig(std::string_view message)
*/
void configManager::writeMaintenanceData()
{
std::ofstream maintenanceFile(maintenanceFileName);
if (maintenanceFile.is_open())
{
maintenanceFile << "ODOMETER=" << odometer << "\n";
maintenanceFile << "LAST_SERVICE=" << lastService << "\n";
maintenanceFile << "SERVICE_INTERVAL=" << serviceInterval << "\n";
maintenanceFile.close();
}
std::string content = "ODOMETER=" + std::to_string(odometer) + "\n";
content += "LAST_SERVICE=" + std::to_string(lastService) + "\n";
content += "SERVICE_INTERVAL=" + std::to_string(serviceInterval) + "\n";

writeStringToFile(maintenanceFileName, content);
}

/**
Expand All @@ -129,28 +125,25 @@ void configManager::setDriveMode(const configManager::DriveMode &mode)
driveMode = mode; // Update in-memory

// Also write to config file
std::ofstream configFile(configFileName, std::ios::app);
if (configFile.is_open())
std::string content = "DRIVEMODE=";
switch (mode)
{
configFile << "DRIVEMODE=";
switch (mode)
{
case DriveMode::LeftArcade:
configFile << "LeftArcade";
break;
case DriveMode::RightArcade:
configFile << "RightArcade";
break;
case DriveMode::SplitArcade:
configFile << "SplitArcade";
break;
case DriveMode::Tank:
configFile << "Tank";
break;
}
configFile << "\n";
configFile.close();
case DriveMode::LeftArcade:
content += "LeftArcade";
break;
case DriveMode::RightArcade:
content += "RightArcade";
break;
case DriveMode::SplitArcade:
content += "SplitArcade";
break;
case DriveMode::Tank:
content += "Tank";
break;
}
content += "\n";

writeStringToFile(configFileName, content, true); // append = true
}

/**
Expand All @@ -169,31 +162,33 @@ void configManager::setDriveMode(const configManager::DriveMode &mode)
*/
void configManager::readMaintenanceData()
{
std::ifstream maintenanceFile(maintenanceFileName);
if (maintenanceFile.is_open())
std::string fileContent = readFileToString(maintenanceFileName);
if (fileContent.empty())
{
return; // File doesn't exist or is empty
}

std::istringstream stream(fileContent);
std::string line;
while (std::getline(stream, line))
{
std::string line;
while (std::getline(maintenanceFile, line))
std::istringstream iss(line);
std::string key, value;
if (std::getline(iss, key, '=') && std::getline(iss, value))
{
std::istringstream iss(line);
std::string key, value;
if (std::getline(iss, key, '=') && std::getline(iss, value))
if (key == "ODOMETER")
{
if (key == "ODOMETER")
{
odometer = stringToNumber<int>(value);
}
else if (key == "LAST_SERVICE")
{
lastService = stringToNumber<long>(value);
}
else if (key == "SERVICE_INTERVAL")
{
serviceInterval = stringToNumber<long>(value);
}
odometer = stringToNumber<int>(value);
}
else if (key == "LAST_SERVICE")
{
lastService = stringToNumber<long>(value);
}
else if (key == "SERVICE_INTERVAL")
{
serviceInterval = stringToNumber<long>(value);
}
}
maintenanceFile.close();
}
}

Expand Down Expand Up @@ -318,15 +313,16 @@ T configManager::stringToNumber(std::string_view str)
*/
void configManager::setValuesFromConfig()
{
std::ifstream configFile(configFileName);
if (!configFile)
std::string fileContent = readFileToString(configFileName);
if (fileContent.empty())
{
logHandler("setValForConfig", "Could not open config file. Reason Unknown.", Log::Level::Warn, 4);
return;
}

std::istringstream stream(fileContent);
std::string configLine;
while (std::getline(configFile, configLine))
while (std::getline(stream, configLine))
{
if (configLine.empty() || configLine[0] == ';' || configLine[0] == '#')
{
Expand Down Expand Up @@ -419,18 +415,18 @@ void configManager::setValuesFromConfig()
else if (key == "MOTOR_CONFIG" || key == "INERTIAL" || key == "TRIPORT_CONFIG")
{
std::string section = key;
while (std::getline(configFile, configLine) && configLine != "}")
while (std::getline(stream, configLine) && configLine != "}")
{
if (configLine.empty() || configLine.starts_with(';') || configLine.starts_with('#'))
{
continue; // Skip empty lines and comments
}

std::string name = configLine;
std::getline(configFile, configLine); // Skip the opening brace
std::getline(stream, configLine); // Skip the opening brace

std::string port, gearRatio, reversedStr;
while (std::getline(configFile, configLine) && configLine != "}")
while (std::getline(stream, configLine) && configLine != "}")
{
std::istringstream iss(configLine);
std::string configKey, configValue;
Expand Down Expand Up @@ -472,7 +468,6 @@ void configManager::setValuesFromConfig()
resetOrInitializeConfig(std::format("Invalid line in config file: {}. Do you want to reset the config?", configLine));
}
}
configFile.close();
}

// Method to parse the config file
Expand Down Expand Up @@ -504,7 +499,7 @@ void configManager::parseConfig()

if (Brain.SDcard.isInserted())
{
if (!Brain.SDcard.exists(configFileName.c_str()))
if (!fileExists(configFileName))
{
resetOrInitializeConfig("Missing config file. Create it?");
}
Expand Down
Loading