diff --git a/interface/src/api/system.ts b/interface/src/api/system.ts index b1d4298e0..02b8b0dff 100644 --- a/interface/src/api/system.ts +++ b/interface/src/api/system.ts @@ -13,7 +13,7 @@ export const updateLogSettings = (data: LogSettings) => alovaInstance.Post('/rest/logSettings', data); export const fetchLogES = () => alovaInstance.Get('/es/log'); -// Get versions from github +// Get versions from GitHub export const getStableVersion = () => alovaInstanceGH.Get('latest', { transform(response: { data: { name: string } }) { @@ -34,9 +34,3 @@ export const uploadFile = (file: File) => { timeout: 60000 // override timeout for uploading firmware - 1 minute }); }; - -export const uploadURL = (data: { url: string }) => - alovaInstance.Post('/rest/uploadURL', data); - -export const checkUpgrade = (data: { version: string }) => - alovaInstance.Post('/rest/checkUpgrade', data); diff --git a/interface/src/app/main/Help.tsx b/interface/src/app/main/Help.tsx index e8bd18d22..a592ddd02 100644 --- a/interface/src/app/main/Help.tsx +++ b/interface/src/app/main/Help.tsx @@ -38,14 +38,17 @@ const Help = () => { const [customSupportIMG, setCustomSupportIMG] = useState(null); const [customSupportHTML, setCustomSupportHTML] = useState(null); - useRequest(() => callAction({ action: 'customSupport' })).onSuccess( - (event: { data: { img_url: string; html: string[] } }) => { - if (event.data) { - setCustomSupportIMG(event.data.img_url); - setCustomSupportHTML(event.data.html.join('
')); + useRequest(() => callAction({ action: 'customSupport' })).onSuccess((event) => { + if (event && event.data && Object.keys(event.data).length !== 0) { + const data = event.data.Support; + if (data.img_url) { + setCustomSupportIMG(data.img_url); + } + if (data.html) { + setCustomSupportHTML(data.html.join('
')); } } - ); + }); const { send: sendExportAllValues } = useRequest( () => callAction({ action: 'export', param: 'allvalues' }), @@ -97,7 +100,7 @@ const Help = () => { { } = useRequest(SystemApi.readSystemStatus); const { send: sendUploadURL } = useRequest( - (data: { url: string }) => uploadURL(data), + (url: string) => callAction({ action: 'uploadURL', param: url }), { immediate: false } @@ -143,7 +138,7 @@ const DownloadUpload = () => { }; const installFirmwareURL = async (url: string) => { - await sendUploadURL({ url: url }).catch((error: Error) => { + await sendUploadURL(url).catch((error: Error) => { toast.error(error.message); }); setRestarting(true); diff --git a/lib/framework/UploadFileService.cpp b/lib/framework/UploadFileService.cpp index a1ce63bb7..0a71854a4 100644 --- a/lib/framework/UploadFileService.cpp +++ b/lib/framework/UploadFileService.cpp @@ -24,11 +24,6 @@ UploadFileService::UploadFileService(AsyncWebServer * server, SecurityManager * [this](AsyncWebServerRequest * request, const String & filename, size_t index, uint8_t * data, size_t len, bool final) { handleUpload(request, filename, index, data, len, final); }); - - // upload from a URL - server->on(UPLOAD_URL_PATH, - securityManager->wrapCallback([this](AsyncWebServerRequest * request, JsonVariant json) { uploadURL(request, json); }, - AuthenticationPredicates::IS_AUTHENTICATED)); } void UploadFileService::handleUpload(AsyncWebServerRequest * request, const String & filename, size_t index, uint8_t * data, size_t len, bool final) { @@ -171,15 +166,3 @@ void UploadFileService::handleEarlyDisconnect() { _is_firmware = false; Update.abort(); } - -// upload firmware from a URL, like GitHub Release assets, Cloudflare R2 or Amazon S3 -void UploadFileService::uploadURL(AsyncWebServerRequest * request, JsonVariant json) { - if (json.is()) { - // this will keep a copy of the URL, but won't initiate the download yet - emsesp::EMSESP::system_.uploadFirmwareURL(json["url"].as()); - - // end the connection - AsyncWebServerResponse * response = request->beginResponse(200); - request->send(response); - } -} diff --git a/lib/framework/UploadFileService.h b/lib/framework/UploadFileService.h index 04a19a2c9..5afcb3028 100644 --- a/lib/framework/UploadFileService.h +++ b/lib/framework/UploadFileService.h @@ -12,7 +12,6 @@ #include #define UPLOAD_FILE_PATH "/rest/uploadFile" -#define UPLOAD_URL_PATH "/rest/uploadURL" #define TEMP_FILENAME_PATH "/tmp_upload" // for uploaded json files @@ -28,7 +27,6 @@ class UploadFileService { void handleUpload(AsyncWebServerRequest * request, const String & filename, size_t index, uint8_t * data, size_t len, bool final); void uploadComplete(AsyncWebServerRequest * request); void handleError(AsyncWebServerRequest * request, int code); - void uploadURL(AsyncWebServerRequest * request, JsonVariant json); void handleEarlyDisconnect(); }; diff --git a/mock-api/rest_server.ts b/mock-api/rest_server.ts index c2e449bd4..38e9a0474 100644 --- a/mock-api/rest_server.ts +++ b/mock-api/rest_server.ts @@ -140,19 +140,24 @@ function export_data(type: string) { // called by Action endpoint function custom_support() { + // return {}; return { - html: [ - 'This product is installed and managed by:', - '', - 'Bosch Installer Example', - 'Nefit Road 12', - '1234 AB Amsterdam', - 'Phone: +31 123 456 789', - 'email: support@boschinstaller.nl', - '', - "For help and questions please contact your installer." - ], - img_url: 'https://emsesp.org/_media/images/designer.png' + type: 'custom_support', + Support: { + html: [ + 'This product is installed and managed by:', + '', + 'Bosch Installer Example', + '', + 'Nefit Road 12', + '1234 AB Amsterdam', + 'Phone: +31 123 456 789', + 'email: support@boschinstaller.nl', + '', + "For help and questions please contact your installer." + ], + img_url: 'https://emsesp.org/_media/images/designer.png' + } }; } @@ -4581,12 +4586,6 @@ router return data; }) - // upload URL - .post('/rest/uploadURL', () => { - console.log('upload File from URL'); - return status(200); - }) - // generic action for all /rest/... endpoints // takes an action and param in JSON .post(EMSESP_ACTION_ENDPOINT, async (request: any) => { @@ -4602,6 +4601,10 @@ router } else if (action === 'checkUpgrade') { // check upgrade return check_upgrade(content.param); + } else if (action === 'uploadURL') { + // upload URL + console.log('upload File from URL', content.param); + return status(200); } } return status(404); // cmd not found diff --git a/project-words.txt b/project-words.txt index d1ea72cb8..834361ef3 100644 --- a/project-words.txt +++ b/project-words.txt @@ -1345,4 +1345,7 @@ zulufttemp zyxwvutsrqponmlkjihgfedcba Omea Bolv -hardwarestatus \ No newline at end of file +hardwarestatus +hpcurrpower +hppowerlimit +CUSTOMSUPPORT \ No newline at end of file diff --git a/src/system.cpp b/src/system.cpp index dd506cc6c..f37af24dd 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -1134,7 +1134,7 @@ bool System::check_restore() { // it's a custom support file - save it to /config new_file.close(); if (LittleFS.rename(TEMP_FILENAME_PATH, EMSESP_CUSTOMSUPPORT_FILE)) { - LOG_INFO("Custom support information loaded"); + LOG_DEBUG("Custom support information found"); return false; // no need to reboot } else { LOG_ERROR("Failed to save custom support file"); diff --git a/src/version.h b/src/version.h index b78c093ae..e0e7948ea 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define EMSESP_APP_VERSION "3.7.0-dev.41" +#define EMSESP_APP_VERSION "3.7.0-dev.42" diff --git a/src/web/WebStatusService.cpp b/src/web/WebStatusService.cpp index 642a82f6e..f630b3252 100644 --- a/src/web/WebStatusService.cpp +++ b/src/web/WebStatusService.cpp @@ -24,11 +24,12 @@ namespace emsesp { -WebStatusService::WebStatusService(AsyncWebServer * server, SecurityManager * securityManager) { +WebStatusService::WebStatusService(AsyncWebServer * server, SecurityManager * securityManager) + : _securityManager(securityManager) { // GET server->on(EMSESP_SYSTEM_STATUS_SERVICE_PATH, HTTP_GET, [this](AsyncWebServerRequest * request) { systemStatus(request); }); - // generic action - POST + // POST - generic action handler server->on(EMSESP_ACTION_SERVICE_PATH, [this](AsyncWebServerRequest * request, JsonVariant json) { action(request, json); }); } @@ -150,10 +151,14 @@ void WebStatusService::action(AsyncWebServerRequest * request, JsonVariant json) auto * response = new AsyncJsonResponse(); JsonObject root = response->getRoot(); - // get action and optional param + // get action and any optional param std::string action = json["action"]; std::string param = json["param"]; // is optional + // check if we're authenticated for admin tasks, some actions are only for admins + Authentication authentication = _securityManager->authenticateRequest(request); + bool is_admin = AuthenticationPredicates::IS_ADMIN(authentication); + bool ok = true; if (action == "checkUpgrade") { ok = checkUpgrade(root, param); @@ -161,6 +166,8 @@ void WebStatusService::action(AsyncWebServerRequest * request, JsonVariant json) ok = exportData(root, param); } else if (action == "customSupport") { ok = customSupport(root); + } else if (action == "uploadURL" && is_admin) { + ok = uploadURL(param.c_str()); } #if defined(EMSESP_UNITY) @@ -184,6 +191,7 @@ void WebStatusService::action(AsyncWebServerRequest * request, JsonVariant json) request->send(response); } +// action = checkUpgrade // returns true if there is an upgrade available bool WebStatusService::checkUpgrade(JsonObject root, std::string & latest_version) { version::Semver200_version settings_version(EMSESP_APP_VERSION); @@ -198,6 +206,7 @@ bool WebStatusService::checkUpgrade(JsonObject root, std::string & latest_versio return true; } +// action = allvalues // output all the devices and the values void WebStatusService::allvalues(JsonObject output) { JsonDocument doc; @@ -226,6 +235,7 @@ void WebStatusService::allvalues(JsonObject output) { EMSESP::temperaturesensor_.get_value_info(device_output, value); } +// action = export // returns data for a specific feature/settings as a json object bool WebStatusService::exportData(JsonObject root, std::string & type) { root["type"] = type; @@ -253,7 +263,8 @@ bool WebStatusService::exportData(JsonObject root, std::string & type) { return true; } -// custom support +// action = customSupport +// reads any upload customSupport.json file and sends to to Help page to be shown as Guest bool WebStatusService::customSupport(JsonObject root) { #ifndef EMSESP_STANDALONE // check if we have custom support file uploaded @@ -275,4 +286,12 @@ bool WebStatusService::customSupport(JsonObject root) { return true; } +// action = uploadURL +// uploads a firmware file from a URL +bool WebStatusService::uploadURL(const char * url) { + // this will keep a copy of the URL, but won't initiate the download yet + emsesp::EMSESP::system_.uploadFirmwareURL(url); + return true; +} + } // namespace emsesp diff --git a/src/web/WebStatusService.h b/src/web/WebStatusService.h index bc887156c..703464589 100644 --- a/src/web/WebStatusService.h +++ b/src/web/WebStatusService.h @@ -12,7 +12,7 @@ class WebStatusService { public: WebStatusService(AsyncWebServer * server, SecurityManager * securityManager); -// make all functions public so we can test in the debug and standalone mode +// make action function public so we can test in the debug and standalone mode #ifndef EMSESP_STANDALONE protected: #endif @@ -20,9 +20,14 @@ class WebStatusService { void action(AsyncWebServerRequest * request, JsonVariant json); private: + SecurityManager * _securityManager; + + // actions bool checkUpgrade(JsonObject root, std::string & latest_version); bool exportData(JsonObject root, std::string & type); bool customSupport(JsonObject root); + bool uploadURL(const char * url); + void allvalues(JsonObject output); };