diff --git a/interface/src/api/system.ts b/interface/src/api/system.ts index f93ff4853..7df8285e8 100644 --- a/interface/src/api/system.ts +++ b/interface/src/api/system.ts @@ -12,6 +12,10 @@ export function restart(): AxiosPromise { return AXIOS.post('/restart'); } +export function partition(): AxiosPromise { + return AXIOS.post('/partition'); +} + export function factoryReset(): AxiosPromise { return AXIOS.post('/factoryReset'); } diff --git a/interface/src/framework/system/SystemStatusForm.tsx b/interface/src/framework/system/SystemStatusForm.tsx index f8dde19ea..ae4414baf 100644 --- a/interface/src/framework/system/SystemStatusForm.tsx +++ b/interface/src/framework/system/SystemStatusForm.tsx @@ -87,7 +87,19 @@ const SystemStatusForm: FC = () => { setProcessing(true); try { await SystemApi.restart(); - enqueueSnackbar(LL.APPLICATION_RESTARTING(), { variant: 'info' }); + setRestarting(true); + } catch (error) { + enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_LOADING()), { variant: 'error' }); + } finally { + setConfirmRestart(false); + setProcessing(false); + } + }; + + const partition = async () => { + setProcessing(true); + try { + await SystemApi.partition(); setRestarting(true); } catch (error) { enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_LOADING()), { variant: 'error' }); @@ -121,6 +133,17 @@ const SystemStatusForm: FC = () => { > {LL.RESTART()} + {data?.has_loader && ( + + )} ); diff --git a/interface/src/project/SettingsApplication.tsx b/interface/src/project/SettingsApplication.tsx index 85379faf8..f462d7bb6 100644 --- a/interface/src/project/SettingsApplication.tsx +++ b/interface/src/project/SettingsApplication.tsx @@ -25,6 +25,7 @@ import * as EMSESP from './api'; import { Settings, BOARD_PROFILES } from './types'; import { useI18nContext } from '../i18n/i18n-react'; +import RestartMonitor from '../framework/system/RestartMonitor'; export function boardProfileSelectItems() { return Object.keys(BOARD_PROFILES).map((code) => ( @@ -39,6 +40,7 @@ const SettingsApplication: FC = () => { read: EMSESP.readSettings, update: EMSESP.writeSettings }); + const [restarting, setRestarting] = useState(); const { LL } = useI18nContext(); @@ -106,7 +108,7 @@ const SettingsApplication: FC = () => { validateAndSubmit(); try { await EMSESP.restart(); - enqueueSnackbar(LL.APPLICATION_RESTARTING(), { variant: 'info' }); + setRestarting(true); } catch (error) { enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' }); } @@ -617,7 +619,7 @@ const SettingsApplication: FC = () => { return ( - {content()} + {restarting ? : content()} ); }; diff --git a/interface/src/types/system.ts b/interface/src/types/system.ts index d45f735ad..5ad12c59b 100644 --- a/interface/src/types/system.ts +++ b/interface/src/types/system.ts @@ -15,6 +15,7 @@ export interface SystemStatus { free_mem: number; psram_size?: number; free_psram?: number; + has_loader: boolean; } export interface OTASettings { diff --git a/lib/framework/RestartService.cpp b/lib/framework/RestartService.cpp index d5c37e3c4..cb12fc841 100644 --- a/lib/framework/RestartService.cpp +++ b/lib/framework/RestartService.cpp @@ -1,12 +1,27 @@ #include +#include using namespace std::placeholders; // for `_1` etc RestartService::RestartService(AsyncWebServer * server, SecurityManager * securityManager) { server->on(RESTART_SERVICE_PATH, HTTP_POST, securityManager->wrapRequest(std::bind(&RestartService::restart, this, _1), AuthenticationPredicates::IS_ADMIN)); + server->on(PARTITION_SERVICE_PATH, + HTTP_POST, + securityManager->wrapRequest(std::bind(&RestartService::partition, this, _1), AuthenticationPredicates::IS_ADMIN)); } void RestartService::restart(AsyncWebServerRequest * request) { request->onDisconnect(RestartService::restartNow); request->send(200); } + +void RestartService::partition(AsyncWebServerRequest * request) { + const esp_partition_t * factory_partition = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_FACTORY, NULL); + if (!factory_partition) { + request->send(400); // bad request + return; + } + esp_ota_set_boot_partition(factory_partition); + request->onDisconnect(RestartService::restartNow); + request->send(200); +} diff --git a/lib/framework/RestartService.h b/lib/framework/RestartService.h index 9eb558e76..8a010716f 100644 --- a/lib/framework/RestartService.h +++ b/lib/framework/RestartService.h @@ -8,6 +8,7 @@ #include #define RESTART_SERVICE_PATH "/rest/restart" +#define PARTITION_SERVICE_PATH "/rest/partition" class RestartService { public: @@ -21,6 +22,7 @@ class RestartService { private: void restart(AsyncWebServerRequest * request); + void partition(AsyncWebServerRequest * request); }; #endif