214 lines
5.0 KiB
C++
214 lines
5.0 KiB
C++
#include "RobotConfig.h"
|
|
#include <FFat.h>
|
|
|
|
uint16_t RobotConfig::getMotorPosition(uint8_t motorID) const {
|
|
for (const Motor& motor : motors) {
|
|
if (motor.motorID == motorID) {
|
|
return motor.position;
|
|
}
|
|
}
|
|
// Return 0 if motor not found
|
|
return 2047;
|
|
}
|
|
|
|
uint8_t RobotConfig::getMotorModel(uint8_t motorID) {
|
|
for (const Motor& motor : motors) {
|
|
if (motor.motorID == motorID) {
|
|
return motor.servoModel.minor;
|
|
}
|
|
}
|
|
// Return 0 if motor not found
|
|
return 5;
|
|
}
|
|
|
|
bool RobotConfig::setMotorPosition(uint8_t motorID, uint16_t newPosition) {
|
|
for (Motor& motor : motors) {
|
|
if (motor.motorID == motorID) {
|
|
motor.position = newPosition;
|
|
return true;
|
|
}
|
|
}
|
|
// Return false if motor not found
|
|
return false;
|
|
}
|
|
|
|
bool RobotConfig::setMotorEnabled(uint8_t motorID, bool enable) {
|
|
for (Motor& motor : motors) {
|
|
if (motor.motorID == motorID) {
|
|
if (motor.isEnabled != enable) {
|
|
motor.isEnabled = enable;
|
|
return true; // ✅ Only return true if the value changed
|
|
}
|
|
return false; // ❌ No change
|
|
}
|
|
}
|
|
return false; // ❌ Motor not found
|
|
}
|
|
|
|
|
|
bool RobotConfig::isMotorEnabled(uint8_t motorID) {
|
|
for (Motor& motor : motors) {
|
|
if (motor.motorID == motorID) {
|
|
return motor.isEnabled;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void RobotConfig::enableAllMotors() {
|
|
for (Motor& motor : motors) {
|
|
motor.isEnabled = true;
|
|
}
|
|
}
|
|
|
|
String RobotConfig::serializeJSON() const {
|
|
String output = "{";
|
|
output += "\"deviceName\":\"" + deviceName + "\",";
|
|
output += "\"firmwareVersion\":{\"major\":" + String(firmwareVersion.major) + ",\"minor\":" + String(firmwareVersion.minor) + "},";
|
|
|
|
output += "\"motors\":[";
|
|
|
|
for (size_t i = 0; i < motors.size(); ++i) {
|
|
const Motor& m = motors[i];
|
|
output += "{";
|
|
output += "\"motorID\":" + String(m.motorID) + ",";
|
|
output += "\"name\":\"" + m.name + "\",";
|
|
output += "\"model\":" + String(m.servoModel.minor);
|
|
output += "}";
|
|
|
|
if (i < motors.size() - 1) {
|
|
output += ",";
|
|
}
|
|
}
|
|
|
|
output += "]}";
|
|
return output;
|
|
}
|
|
|
|
std::vector<uint8_t> RobotConfig::serializeToBytes() const {
|
|
std::vector<uint8_t> buffer;
|
|
|
|
// Encode deviceName length + characters
|
|
uint8_t nameLen = deviceName.length();
|
|
buffer.push_back(nameLen);
|
|
for (uint8_t i = 0; i < nameLen; ++i) {
|
|
buffer.push_back(deviceName[i]);
|
|
}
|
|
|
|
// Encode firmwareVersion (int32_t → 4 bytes)
|
|
buffer.push_back(firmwareVersion.major);
|
|
buffer.push_back(firmwareVersion.minor);
|
|
|
|
|
|
// Encode number of motors
|
|
uint8_t motorCount = motors.size();
|
|
buffer.push_back(motorCount);
|
|
|
|
// Encode each motor
|
|
for (const Motor& m : motors) {
|
|
// motorID
|
|
buffer.push_back(m.motorID);
|
|
|
|
// name length + characters
|
|
uint8_t motorNameLen = m.name.length();
|
|
buffer.push_back(motorNameLen);
|
|
for (uint8_t i = 0; i < motorNameLen; ++i) {
|
|
buffer.push_back(m.name[i]);
|
|
}
|
|
|
|
// position (uint16_t → 2 bytes)
|
|
buffer.push_back((m.position >> 8) & 0xFF);
|
|
buffer.push_back(m.position & 0xFF);
|
|
}
|
|
|
|
return buffer;
|
|
}
|
|
|
|
bool RobotConfig::saveToFFat(const char* path) const {
|
|
File file = FFat.open(path, FILE_WRITE);
|
|
if (!file) return false;
|
|
|
|
uint8_t nameLen = deviceName.length();
|
|
file.write(nameLen);
|
|
file.write((const uint8_t*)deviceName.c_str(), nameLen);
|
|
|
|
file.write(firmwareVersion.major);
|
|
file.write(firmwareVersion.minor);
|
|
|
|
uint8_t motorCount = motors.size();
|
|
file.write(motorCount);
|
|
|
|
for (const Motor& m : motors) {
|
|
file.write(m.servoModel.major);
|
|
file.write(m.servoModel.minor);
|
|
file.write(m.motorID & 0xFF);
|
|
file.write((m.motorID >> 8) & 0xFF);
|
|
|
|
uint8_t nameLen = m.name.length();
|
|
file.write(nameLen);
|
|
file.write((const uint8_t*)m.name.c_str(), nameLen);
|
|
}
|
|
|
|
file.close();
|
|
return true;
|
|
}
|
|
|
|
bool RobotConfig::loadFromFFat(const char* path) {
|
|
File file = FFat.open(path, FILE_READ);
|
|
if (!file) return false;
|
|
|
|
motors.clear();
|
|
|
|
uint8_t nameLen = file.read();
|
|
char nameBuf[64] = { 0 };
|
|
file.readBytes(nameBuf, nameLen);
|
|
deviceName = String(nameBuf);
|
|
|
|
firmwareVersion.major = file.read();
|
|
firmwareVersion.minor = file.read();
|
|
|
|
uint8_t motorCount = file.read();
|
|
|
|
for (uint8_t i = 0; i < motorCount; ++i) {
|
|
ServoModel model;
|
|
model.major = file.read();
|
|
model.minor = file.read();
|
|
|
|
uint16_t id = file.read();
|
|
id |= (file.read() << 8);
|
|
|
|
uint8_t motorNameLen = file.read();
|
|
char motorNameBuf[64] = { 0 };
|
|
file.readBytes(motorNameBuf, motorNameLen);
|
|
|
|
Motor m;
|
|
m.motorID = id;
|
|
m.servoModel = model;
|
|
m.name = String(motorNameBuf);
|
|
m.position = 0;
|
|
m.isEnabled = true;
|
|
|
|
motors.push_back(m);
|
|
}
|
|
|
|
file.close();
|
|
return true;
|
|
}
|
|
|
|
bool RobotConfig::loadOrCreateDefault(const char* path) {
|
|
if (FFat.exists(path)) {
|
|
Serial.println("Loading robot config from FFat...");
|
|
return loadFromFFat(path);
|
|
}
|
|
|
|
Serial.println("No config found. Creating default config...");
|
|
|
|
// 🔧 Define your default config here
|
|
deviceName = "DefaultBot";
|
|
firmwareVersion = { 1, 0 };
|
|
|
|
motors.clear();
|
|
|
|
return saveToFFat(path);
|
|
}
|