From fc4cdfd9aef728669e76d5d8ced14400abcc8634 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Sun, 17 Oct 2021 12:54:48 +0200 Subject: [PATCH] Implement model backup/restore --- radio/src/dataconstants.h | 4 + radio/src/gui/128x64/model_select.cpp | 23 +-- radio/src/gui/212x64/model_select.cpp | 23 +-- radio/src/sdcard.h | 1 + .../conversions/yaml/dataconstants_220.h | 4 + radio/src/storage/sdcard_common.h | 2 + radio/src/storage/sdcard_yaml.cpp | 132 +++++++++++++++++- radio/src/targets/simu/simufatfs.cpp | 10 +- radio/src/translations.cpp | 2 + radio/src/translations.h | 2 + 10 files changed, 177 insertions(+), 26 deletions(-) diff --git a/radio/src/dataconstants.h b/radio/src/dataconstants.h index d1f4351d7..2b86fc013 100644 --- a/radio/src/dataconstants.h +++ b/radio/src/dataconstants.h @@ -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 diff --git a/radio/src/gui/128x64/model_select.cpp b/radio/src/gui/128x64/model_select.cpp index 38fcbb12f..aeb84ee15 100644 --- a/radio/src/gui/128x64/model_select.cpp +++ b/radio/src/gui/128x64/model_select.cpp @@ -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 } diff --git a/radio/src/gui/212x64/model_select.cpp b/radio/src/gui/212x64/model_select.cpp index 8b48001a0..fee574a8e 100644 --- a/radio/src/gui/212x64/model_select.cpp +++ b/radio/src/gui/212x64/model_select.cpp @@ -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); + } } } diff --git a/radio/src/sdcard.h b/radio/src/sdcard.h index e1ab079e0..18bedfe82 100644 --- a/radio/src/sdcard.h +++ b/radio/src/sdcard.h @@ -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" diff --git a/radio/src/storage/conversions/yaml/dataconstants_220.h b/radio/src/storage/conversions/yaml/dataconstants_220.h index c3bfae1c4..aff0b1468 100644 --- a/radio/src/storage/conversions/yaml/dataconstants_220.h +++ b/radio/src/storage/conversions/yaml/dataconstants_220.h @@ -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 diff --git a/radio/src/storage/sdcard_common.h b/radio/src/storage/sdcard_common.h index adeda50f2..1ce2cfb19 100644 --- a/radio/src/storage/sdcard_common.h +++ b/radio/src/storage/sdcard_common.h @@ -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 diff --git a/radio/src/storage/sdcard_yaml.cpp b/radio/src/storage/sdcard_yaml.cpp index 6067fb2b3..41aae5c1f 100644 --- a/radio/src/storage/sdcard_yaml.cpp +++ b/radio/src/storage/sdcard_yaml.cpp @@ -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 diff --git a/radio/src/targets/simu/simufatfs.cpp b/radio/src/targets/simu/simufatfs.cpp index 72bf9b370..2a176823b 100644 --- a/radio/src/targets/simu/simufatfs.cpp +++ b/radio/src/targets/simu/simufatfs.cpp @@ -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 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 files = listDirectoryFiles(dirName); for(unsigned int i=0; i