Implement model backup/restore
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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[];
|
||||
|
||||
Reference in New Issue
Block a user