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