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 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_SWITCH_NAME 3
#define LEN_ANA_NAME 3 #define LEN_ANA_NAME 3
#define LEN_MODEL_FILENAME 16 #define LEN_MODEL_FILENAME 16
+15 -8
View File
@@ -56,11 +56,19 @@ void onModelSelectMenu(const char * result)
#if defined(SDCARD) #if defined(SDCARD)
else if (result == STR_BACKUP_MODEL) { else if (result == STR_BACKUP_MODEL) {
storageCheck(true); // force writing of current model data before this is changed storageCheck(true); // force writing of current model data before this is changed
// TODO POPUP_WARNING(backupModel(sub));
//POPUP_WARNING(eeBackupModel(sub));
} }
else if (result == STR_RESTORE_MODEL || result == STR_UPDATE_LIST) { 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); POPUP_MENU_START(onModelSelectMenu);
else else
POPUP_WARNING(STR_NO_MODELS_ON_SD); POPUP_WARNING(STR_NO_MODELS_ON_SD);
@@ -74,11 +82,10 @@ void onModelSelectMenu(const char * result)
else if (result != STR_EXIT) { else if (result != STR_EXIT) {
// The user choosed a file on SD to restore // The user choosed a file on SD to restore
storageCheck(true); storageCheck(true);
// TODO POPUP_WARNING(restoreModel(sub, (char *)result));
//POPUP_WARNING(eeRestoreModel(sub, (char *)result)); if (!warningText && g_eeGeneral.currModel == sub) {
//if (!warningText && g_eeGeneral.currModel == sub) { loadModel(sub);
// eeLoadModel(sub); }
//}
} }
#endif #endif
} }
+15 -8
View File
@@ -46,11 +46,19 @@ void onModelSelectMenu(const char * result)
} }
else if (result == STR_BACKUP_MODEL) { else if (result == STR_BACKUP_MODEL) {
storageCheck(true); // force writing of current model data before this is changed storageCheck(true); // force writing of current model data before this is changed
//TODO POPUP_WARNING(backupModel(sub));
//POPUP_WARNING(eeBackupModel(sub));
} }
else if (result == STR_RESTORE_MODEL || result == STR_UPDATE_LIST) { 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); POPUP_MENU_START(onModelSelectMenu);
else else
POPUP_WARNING(STR_NO_MODELS_ON_SD); POPUP_WARNING(STR_NO_MODELS_ON_SD);
@@ -64,11 +72,10 @@ void onModelSelectMenu(const char * result)
else if (result != STR_EXIT) { else if (result != STR_EXIT) {
// The user choosed a file on SD to restore // The user choosed a file on SD to restore
storageCheck(true); storageCheck(true);
// TODO POPUP_WARNING(restoreModel(sub, (char *)result));
// POPUP_WARNING(eeRestoreModel(sub, (char *)result)); if (!warningText && g_eeGeneral.currModel == sub) {
// if (!warningText && g_eeGeneral.currModel == sub) { loadModel(sub);
// eeLoadModel(sub); }
// }
} }
} }
+1
View File
@@ -41,6 +41,7 @@
#define FIRMWARES_PATH ROOT_PATH "FIRMWARE" #define FIRMWARES_PATH ROOT_PATH "FIRMWARE"
#define AUTOUPDATE_FILENAME FIRMWARES_PATH PATH_SEPARATOR "autoupdate.frsk" #define AUTOUPDATE_FILENAME FIRMWARES_PATH PATH_SEPARATOR "autoupdate.frsk"
#define EEPROMS_PATH ROOT_PATH "EEPROM" #define EEPROMS_PATH ROOT_PATH "EEPROM"
#define BACKUP_PATH ROOT_PATH "BACKUP"
#define SCRIPTS_PATH ROOT_PATH "SCRIPTS" #define SCRIPTS_PATH ROOT_PATH "SCRIPTS"
#define WIZARD_PATH SCRIPTS_PATH PATH_SEPARATOR "WIZARD" #define WIZARD_PATH SCRIPTS_PATH PATH_SEPARATOR "WIZARD"
#define THEMES_PATH ROOT_PATH "THEMES" #define THEMES_PATH ROOT_PATH "THEMES"
@@ -327,6 +327,10 @@ enum UartModes {
UART_MODE_MAX = UART_MODE_COUNT-1 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_SWITCH_NAME 3
#define LEN_ANA_NAME 3 #define LEN_ANA_NAME 3
#define LEN_MODEL_FILENAME 16 #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); bool copyModel(uint8_t dst, uint8_t src);
void swapModels(uint8_t id1, uint8_t id2); void swapModels(uint8_t id1, uint8_t id2);
int8_t deleteModel(uint8_t idx); 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); uint8_t findEmptyModel(uint8_t id, bool down);
#endif #endif
+126 -4
View File
@@ -301,19 +301,141 @@ bool copyModel(uint8_t dst, uint8_t src)
return sdCopyFile(fname_src, fname_dst); 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) 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) int8_t deleteModel(uint8_t idx)
{ {
char model_idx[MODELIDX_STRLEN]; char model_idx[MODELIDX_STRLEN];
getModelNumberStr(idx, model_idx); getModelNumberStr(idx, model_idx);
GET_FILENAME(fname, MODELS_PATH, model_idx, YAML_EXT);
GET_FILENAME(fname, MODELS_PATH PATH_SEPARATOR MODEL_FILENAME_PREFIX, if (f_unlink(fname) != FR_OK) {
model_idx, YAML_EXT); return -1;
}
return f_unlink(fname) == FR_OK ? 0 : -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 #endif
+5 -5
View File
@@ -160,7 +160,7 @@ std::string convertToSimuPath(const char * path)
else { else {
result = std::string(path); result = std::string(path);
} }
TRACE_SIMPGMSPACE("convertToSimuPath(): %s -> %s", path, result.c_str()); // TRACE_SIMPGMSPACE("convertToSimuPath(): %s -> %s", path, result.c_str());
return result; return result;
} }
@@ -179,7 +179,7 @@ std::string convertFromSimuPath(const char * path)
result = "/" + result; result = "/" + result;
} }
} }
TRACE_SIMPGMSPACE("convertFromSimuPath(): %s -> %s", path, result.c_str()); // TRACE_SIMPGMSPACE("convertFromSimuPath(): %s -> %s", path, result.c_str());
return result; return result;
} }
@@ -269,12 +269,12 @@ std::vector<std::string> listDirectoryFiles(const std::string & dirName)
std::string findTrueFileName(const std::string & path) std::string findTrueFileName(const std::string & path)
{ {
TRACE_SIMPGMSPACE("findTrueFileName(%s)", path.c_str()); // TRACE_SIMPGMSPACE("findTrueFileName(%s)", path.c_str());
std::string result; std::string result;
filemap_t::iterator i = fileMap.find(path); filemap_t::iterator i = fileMap.find(path);
if (i != fileMap.end()) { if (i != fileMap.end()) {
result = i->second; result = i->second;
TRACE_SIMPGMSPACE("\tfound in map: %s", result.c_str()); // TRACE_SIMPGMSPACE("\tfound in map: %s", result.c_str());
return result; return result;
} }
else { else {
@@ -285,7 +285,7 @@ std::string findTrueFileName(const std::string & path)
std::vector<std::string> files = listDirectoryFiles(dirName); std::vector<std::string> files = listDirectoryFiles(dirName);
for(unsigned int i=0; i<files.size(); ++i) { for(unsigned int i=0; i<files.size(); ++i) {
if (!strcasecmp(files[i].c_str(), path.c_str())) { 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])); fileMap.insert(filemap_t::value_type(path, files[i]));
return 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_LOGS_EXT[] = LOGS_EXT;
const char STR_MODELS_PATH[] = MODELS_PATH; const char STR_MODELS_PATH[] = MODELS_PATH;
const char STR_MODELS_EXT[] = MODELS_EXT; 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_WARNING[] = TR_TEST_WARNING;
const char STR_TEST_NOTSAFE[] = TR_TEST_NOTSAFE; 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_LOGS_EXT[];
extern const char STR_MODELS_PATH[]; extern const char STR_MODELS_PATH[];
extern const char STR_MODELS_EXT[]; extern const char STR_MODELS_EXT[];
extern const char STR_BACKUP_PATH[];
extern const char STR_YAML_EXT[];
#define STR_UPDATE_LIST STR_DELAYDOWN #define STR_UPDATE_LIST STR_DELAYDOWN
extern const char STR_NEEDS_FILE[]; extern const char STR_NEEDS_FILE[];