Implement model backup/restore

This commit is contained in:
Raphael Coeffic
2021-11-10 11:07:01 +01:00
parent 8d04e373b6
commit fc4cdfd9ae
10 changed files with 177 additions and 26 deletions
+4
View File
@@ -253,6 +253,10 @@ enum UartModes {
UART_MODE_MAX = UART_MODE_COUNT-1
};
#if defined(CLI) || defined(DEBUG)
#define UART_MODE_NONE UART_MODE_DEBUG
#endif
#define LEN_SWITCH_NAME 3
#define LEN_ANA_NAME 3
#define LEN_MODEL_FILENAME 16
+15 -8
View File
@@ -56,11 +56,19 @@ void onModelSelectMenu(const char * result)
#if defined(SDCARD)
else if (result == STR_BACKUP_MODEL) {
storageCheck(true); // force writing of current model data before this is changed
// TODO
//POPUP_WARNING(eeBackupModel(sub));
POPUP_WARNING(backupModel(sub));
}
else if (result == STR_RESTORE_MODEL || result == STR_UPDATE_LIST) {
if (sdListFiles(MODELS_PATH, MODELS_EXT, MENU_LINE_LENGTH-1, nullptr))
const char* ext = nullptr;
const char* path = nullptr;
#if defined(SDCARD_YAML)
ext = STR_YAML_EXT;
path = STR_BACKUP_PATH;
#else
ext = STR_MODELS_EXT;
path = STR_MODELS_PATH;
#endif
if (sdListFiles(path, ext, MENU_LINE_LENGTH-1, nullptr))
POPUP_MENU_START(onModelSelectMenu);
else
POPUP_WARNING(STR_NO_MODELS_ON_SD);
@@ -74,11 +82,10 @@ void onModelSelectMenu(const char * result)
else if (result != STR_EXIT) {
// The user choosed a file on SD to restore
storageCheck(true);
// TODO
//POPUP_WARNING(eeRestoreModel(sub, (char *)result));
//if (!warningText && g_eeGeneral.currModel == sub) {
// eeLoadModel(sub);
//}
POPUP_WARNING(restoreModel(sub, (char *)result));
if (!warningText && g_eeGeneral.currModel == sub) {
loadModel(sub);
}
}
#endif
}
+15 -8
View File
@@ -46,11 +46,19 @@ void onModelSelectMenu(const char * result)
}
else if (result == STR_BACKUP_MODEL) {
storageCheck(true); // force writing of current model data before this is changed
//TODO
//POPUP_WARNING(eeBackupModel(sub));
POPUP_WARNING(backupModel(sub));
}
else if (result == STR_RESTORE_MODEL || result == STR_UPDATE_LIST) {
if (sdListFiles(MODELS_PATH, MODELS_EXT, MENU_LINE_LENGTH-1, nullptr))
const char* ext = nullptr;
const char* path = nullptr;
#if defined(SDCARD_YAML)
ext = STR_YAML_EXT;
path = STR_BACKUP_PATH;
#else
ext = STR_MODELS_EXT;
path = STR_MODELS_PATH;
#endif
if (sdListFiles(path, ext, MENU_LINE_LENGTH-1, nullptr))
POPUP_MENU_START(onModelSelectMenu);
else
POPUP_WARNING(STR_NO_MODELS_ON_SD);
@@ -64,11 +72,10 @@ void onModelSelectMenu(const char * result)
else if (result != STR_EXIT) {
// The user choosed a file on SD to restore
storageCheck(true);
// TODO
// POPUP_WARNING(eeRestoreModel(sub, (char *)result));
// if (!warningText && g_eeGeneral.currModel == sub) {
// eeLoadModel(sub);
// }
POPUP_WARNING(restoreModel(sub, (char *)result));
if (!warningText && g_eeGeneral.currModel == sub) {
loadModel(sub);
}
}
}
+1
View File
@@ -41,6 +41,7 @@
#define FIRMWARES_PATH ROOT_PATH "FIRMWARE"
#define AUTOUPDATE_FILENAME FIRMWARES_PATH PATH_SEPARATOR "autoupdate.frsk"
#define EEPROMS_PATH ROOT_PATH "EEPROM"
#define BACKUP_PATH ROOT_PATH "BACKUP"
#define SCRIPTS_PATH ROOT_PATH "SCRIPTS"
#define WIZARD_PATH SCRIPTS_PATH PATH_SEPARATOR "WIZARD"
#define THEMES_PATH ROOT_PATH "THEMES"
@@ -327,6 +327,10 @@ enum UartModes {
UART_MODE_MAX = UART_MODE_COUNT-1
};
#if defined(CLI) || defined(DEBUG)
#define UART_MODE_NONE UART_MODE_DEBUG
#endif
#define LEN_SWITCH_NAME 3
#define LEN_ANA_NAME 3
#define LEN_MODEL_FILENAME 16
+2
View File
@@ -70,6 +70,8 @@ bool modelExists(uint8_t idx);
bool copyModel(uint8_t dst, uint8_t src);
void swapModels(uint8_t id1, uint8_t id2);
int8_t deleteModel(uint8_t idx);
const char* backupModel(uint8_t idx);
const char * restoreModel(uint8_t idx, char *model_name);
uint8_t findEmptyModel(uint8_t id, bool down);
#endif
+127 -5
View File
@@ -301,19 +301,141 @@ bool copyModel(uint8_t dst, uint8_t src)
return sdCopyFile(fname_src, fname_dst);
}
static void swapModelHeaders(uint8_t id1, uint8_t id2)
{
char tmp[sizeof(g_model.header)];
memcpy(tmp, &modelHeaders[id1], sizeof(ModelHeader));
memcpy(&modelHeaders[id1], &modelHeaders[id2], sizeof(ModelHeader));
memcpy(&modelHeaders[id2], tmp, sizeof(ModelHeader));
}
void swapModels(uint8_t id1, uint8_t id2)
{
//TODO
char model_idx_1[MODELIDX_STRLEN];
char model_idx_2[MODELIDX_STRLEN];
getModelNumberStr(id1, model_idx_1);
getModelNumberStr(id2, model_idx_2);
GET_FILENAME(fname1, MODELS_PATH, model_idx_1, YAML_EXT);
GET_FILENAME(fname1_tmp, MODELS_PATH, model_idx_1, ".tmp");
GET_FILENAME(fname2, MODELS_PATH, model_idx_2, YAML_EXT);
FILINFO fno;
if (f_stat(fname2,&fno) != FR_OK) {
if (f_stat(fname1,&fno) == FR_OK) {
if (f_rename(fname1, fname2) == FR_OK)
swapModelHeaders(id1,id2);
}
return;
}
if (f_stat(fname1,&fno) != FR_OK) {
f_rename(fname2, fname1);
return;
}
// just in case...
f_unlink(fname1_tmp);
if (f_rename(fname1, fname1_tmp) != FR_OK) {
TRACE("Error renaming 1");
return;
}
if (f_rename(fname2, fname1) != FR_OK) {
TRACE("Error renaming 2");
return;
}
if (f_rename(fname1_tmp, fname2) != FR_OK) {
TRACE("Error renaming 1 tmp");
return;
}
swapModelHeaders(id1,id2);
}
int8_t deleteModel(uint8_t idx)
{
char model_idx[MODELIDX_STRLEN];
getModelNumberStr(idx, model_idx);
GET_FILENAME(fname, MODELS_PATH PATH_SEPARATOR MODEL_FILENAME_PREFIX,
model_idx, YAML_EXT);
GET_FILENAME(fname, MODELS_PATH, model_idx, YAML_EXT);
return f_unlink(fname) == FR_OK ? 0 : -1;
if (f_unlink(fname) != FR_OK) {
return -1;
}
modelHeaders[idx].name[0] = '\0';
return 0;
}
const char * backupModel(uint8_t idx)
{
char * buf = reusableBuffer.modelsel.mainname;
// check and create folder here
const char * error = sdCheckAndCreateDirectory(STR_BACKUP_PATH);
if (error) {
return error;
}
strncpy(buf, modelHeaders[idx].name, sizeof(g_model.header.name));
buf[sizeof(g_model.header.name)] = '\0';
int8_t i = sizeof(g_model.header.name)-1;
uint8_t len = 0;
while (i > 0) {
if (!len && buf[i])
len = i+1;
if (len) {
if (!buf[i])
buf[i] = '_';
}
i--;
}
if (len == 0) {
uint8_t num = idx + 1;
strcpy(buf, STR_MODEL);
buf[PSIZE(TR_MODEL)] = (char)((num / 10) + '0');
buf[PSIZE(TR_MODEL) + 1] = (char)((num % 10) + '0');
len = PSIZE(TR_MODEL) + 2;
}
#if defined(RTCLOCK)
char * tmp = strAppendDate(&buf[len]);
len = tmp - buf;
#endif
strcpy(&buf[len], STR_YAML_EXT);
#ifdef SIMU
TRACE("SD-card backup filename=%s", buf);
#endif
char model_idx[MODELIDX_STRLEN + sizeof(YAML_EXT)];
getModelNumberStr(idx, model_idx);
strcat(model_idx, STR_YAML_EXT);
return sdCopyFile(model_idx, STR_MODELS_PATH, buf, STR_BACKUP_PATH);
}
const char * restoreModel(uint8_t idx, char *model_name)
{
char * buf = reusableBuffer.modelsel.mainname;
strcpy(buf, model_name);
strcpy(&buf[strlen(buf)], STR_YAML_EXT);
char model_idx[MODELIDX_STRLEN + sizeof(YAML_EXT)];
getModelNumberStr(idx, model_idx);
strcat(model_idx, STR_YAML_EXT);
const char* error = sdCopyFile(buf, STR_BACKUP_PATH, model_idx, STR_MODELS_PATH);
if (!error) {
loadModelHeader(idx, &modelHeaders[idx]);
}
return error;
}
#endif
+5 -5
View File
@@ -160,7 +160,7 @@ std::string convertToSimuPath(const char * path)
else {
result = std::string(path);
}
TRACE_SIMPGMSPACE("convertToSimuPath(): %s -> %s", path, result.c_str());
// TRACE_SIMPGMSPACE("convertToSimuPath(): %s -> %s", path, result.c_str());
return result;
}
@@ -179,7 +179,7 @@ std::string convertFromSimuPath(const char * path)
result = "/" + result;
}
}
TRACE_SIMPGMSPACE("convertFromSimuPath(): %s -> %s", path, result.c_str());
// TRACE_SIMPGMSPACE("convertFromSimuPath(): %s -> %s", path, result.c_str());
return result;
}
@@ -269,12 +269,12 @@ std::vector<std::string> listDirectoryFiles(const std::string & dirName)
std::string findTrueFileName(const std::string & path)
{
TRACE_SIMPGMSPACE("findTrueFileName(%s)", path.c_str());
// TRACE_SIMPGMSPACE("findTrueFileName(%s)", path.c_str());
std::string result;
filemap_t::iterator i = fileMap.find(path);
if (i != fileMap.end()) {
result = i->second;
TRACE_SIMPGMSPACE("\tfound in map: %s", result.c_str());
// TRACE_SIMPGMSPACE("\tfound in map: %s", result.c_str());
return result;
}
else {
@@ -285,7 +285,7 @@ std::string findTrueFileName(const std::string & path)
std::vector<std::string> files = listDirectoryFiles(dirName);
for(unsigned int i=0; i<files.size(); ++i) {
if (!strcasecmp(files[i].c_str(), path.c_str())) {
TRACE_SIMPGMSPACE("\tfound: %s", files[i].c_str());
// TRACE_SIMPGMSPACE("\tfound: %s", files[i].c_str());
fileMap.insert(filemap_t::value_type(path, files[i]));
return files[i];
}
+2
View File
@@ -905,6 +905,8 @@ const char STR_LOGS_PATH[] = LOGS_PATH;
const char STR_LOGS_EXT[] = LOGS_EXT;
const char STR_MODELS_PATH[] = MODELS_PATH;
const char STR_MODELS_EXT[] = MODELS_EXT;
const char STR_BACKUP_PATH[] = BACKUP_PATH;
const char STR_YAML_EXT[] = YAML_EXT;
const char STR_TEST_WARNING[] = TR_TEST_WARNING;
const char STR_TEST_NOTSAFE[] = TR_TEST_NOTSAFE;
+2
View File
@@ -598,6 +598,8 @@ extern const char STR_LOGS_PATH[];
extern const char STR_LOGS_EXT[];
extern const char STR_MODELS_PATH[];
extern const char STR_MODELS_EXT[];
extern const char STR_BACKUP_PATH[];
extern const char STR_YAML_EXT[];
#define STR_UPDATE_LIST STR_DELAYDOWN
extern const char STR_NEEDS_FILE[];