move uploadURL as an action

This commit is contained in:
proddy
2024-09-29 11:08:49 +02:00
parent 93066e4836
commit ab040e120e
11 changed files with 70 additions and 67 deletions

View File

@@ -13,7 +13,7 @@ export const updateLogSettings = (data: LogSettings) =>
alovaInstance.Post('/rest/logSettings', data); alovaInstance.Post('/rest/logSettings', data);
export const fetchLogES = () => alovaInstance.Get('/es/log'); export const fetchLogES = () => alovaInstance.Get('/es/log');
// Get versions from github // Get versions from GitHub
export const getStableVersion = () => export const getStableVersion = () =>
alovaInstanceGH.Get('latest', { alovaInstanceGH.Get('latest', {
transform(response: { data: { name: string } }) { transform(response: { data: { name: string } }) {
@@ -34,9 +34,3 @@ export const uploadFile = (file: File) => {
timeout: 60000 // override timeout for uploading firmware - 1 minute 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);

View File

@@ -38,14 +38,17 @@ const Help = () => {
const [customSupportIMG, setCustomSupportIMG] = useState<string | null>(null); const [customSupportIMG, setCustomSupportIMG] = useState<string | null>(null);
const [customSupportHTML, setCustomSupportHTML] = useState<string | null>(null); const [customSupportHTML, setCustomSupportHTML] = useState<string | null>(null);
useRequest(() => callAction({ action: 'customSupport' })).onSuccess( useRequest(() => callAction({ action: 'customSupport' })).onSuccess((event) => {
(event: { data: { img_url: string; html: string[] } }) => { if (event && event.data && Object.keys(event.data).length !== 0) {
if (event.data) { const data = event.data.Support;
setCustomSupportIMG(event.data.img_url); if (data.img_url) {
setCustomSupportHTML(event.data.html.join('<br/>')); setCustomSupportIMG(data.img_url);
}
if (data.html) {
setCustomSupportHTML(data.html.join('<br/>'));
} }
} }
); });
const { send: sendExportAllValues } = useRequest( const { send: sendExportAllValues } = useRequest(
() => callAction({ action: 'export', param: 'allvalues' }), () => callAction({ action: 'export', param: 'allvalues' }),
@@ -97,7 +100,7 @@ const Help = () => {
<Box <Box
component="img" component="img"
sx={{ sx={{
maxHeight: 250 maxHeight: { xs: 100, md: 250 }
}} }}
src={ src={
customSupportIMG customSupportIMG

View File

@@ -19,12 +19,7 @@ import Grid from '@mui/material/Grid2';
import * as SystemApi from 'api/system'; import * as SystemApi from 'api/system';
import { API, callAction } from 'api/app'; import { API, callAction } from 'api/app';
import { import { getDevVersion, getStableVersion } from 'api/system';
checkUpgrade,
getDevVersion,
getStableVersion,
uploadURL
} from 'api/system';
import { dialogStyle } from 'CustomTheme'; import { dialogStyle } from 'CustomTheme';
import { useRequest } from 'alova/client'; import { useRequest } from 'alova/client';
@@ -81,7 +76,7 @@ const DownloadUpload = () => {
} = useRequest(SystemApi.readSystemStatus); } = useRequest(SystemApi.readSystemStatus);
const { send: sendUploadURL } = useRequest( const { send: sendUploadURL } = useRequest(
(data: { url: string }) => uploadURL(data), (url: string) => callAction({ action: 'uploadURL', param: url }),
{ {
immediate: false immediate: false
} }
@@ -143,7 +138,7 @@ const DownloadUpload = () => {
}; };
const installFirmwareURL = async (url: string) => { const installFirmwareURL = async (url: string) => {
await sendUploadURL({ url: url }).catch((error: Error) => { await sendUploadURL(url).catch((error: Error) => {
toast.error(error.message); toast.error(error.message);
}); });
setRestarting(true); setRestarting(true);

View File

@@ -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) { [this](AsyncWebServerRequest * request, const String & filename, size_t index, uint8_t * data, size_t len, bool final) {
handleUpload(request, filename, index, data, len, 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) { 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; _is_firmware = false;
Update.abort(); 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<JsonObject>()) {
// this will keep a copy of the URL, but won't initiate the download yet
emsesp::EMSESP::system_.uploadFirmwareURL(json["url"].as<const char *>());
// end the connection
AsyncWebServerResponse * response = request->beginResponse(200);
request->send(response);
}
}

View File

@@ -12,7 +12,6 @@
#include <array> #include <array>
#define UPLOAD_FILE_PATH "/rest/uploadFile" #define UPLOAD_FILE_PATH "/rest/uploadFile"
#define UPLOAD_URL_PATH "/rest/uploadURL"
#define TEMP_FILENAME_PATH "/tmp_upload" // for uploaded json files #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 handleUpload(AsyncWebServerRequest * request, const String & filename, size_t index, uint8_t * data, size_t len, bool final);
void uploadComplete(AsyncWebServerRequest * request); void uploadComplete(AsyncWebServerRequest * request);
void handleError(AsyncWebServerRequest * request, int code); void handleError(AsyncWebServerRequest * request, int code);
void uploadURL(AsyncWebServerRequest * request, JsonVariant json);
void handleEarlyDisconnect(); void handleEarlyDisconnect();
}; };

View File

@@ -140,19 +140,24 @@ function export_data(type: string) {
// called by Action endpoint // called by Action endpoint
function custom_support() { function custom_support() {
// return {};
return { return {
html: [ type: 'custom_support',
'This product is installed and managed by:', Support: {
'', html: [
'<b>Bosch Installer Example</b>', 'This product is installed and managed by:',
'Nefit Road 12', '',
'1234 AB Amsterdam', '<b>Bosch Installer Example</b>',
'Phone: +31 123 456 789', '',
'email: support@boschinstaller.nl', 'Nefit Road 12',
'', '1234 AB Amsterdam',
"For help and questions please <a target='_blank' href='https://emsesp.org'>contact</a> your installer." 'Phone: +31 123 456 789',
], 'email: support@boschinstaller.nl',
img_url: 'https://emsesp.org/_media/images/designer.png' '',
"For help and questions please <a target='_blank' href='https://emsesp.org'>contact</a> your installer."
],
img_url: 'https://emsesp.org/_media/images/designer.png'
}
}; };
} }
@@ -4581,12 +4586,6 @@ router
return data; return data;
}) })
// upload URL
.post('/rest/uploadURL', () => {
console.log('upload File from URL');
return status(200);
})
// generic action for all /rest/... endpoints // generic action for all /rest/... endpoints
// takes an action and param in JSON // takes an action and param in JSON
.post(EMSESP_ACTION_ENDPOINT, async (request: any) => { .post(EMSESP_ACTION_ENDPOINT, async (request: any) => {
@@ -4602,6 +4601,10 @@ router
} else if (action === 'checkUpgrade') { } else if (action === 'checkUpgrade') {
// check upgrade // check upgrade
return check_upgrade(content.param); 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 return status(404); // cmd not found

View File

@@ -1346,3 +1346,6 @@ zyxwvutsrqponmlkjihgfedcba
Omea Omea
Bolv Bolv
hardwarestatus hardwarestatus
hpcurrpower
hppowerlimit
CUSTOMSUPPORT

View File

@@ -1134,7 +1134,7 @@ bool System::check_restore() {
// it's a custom support file - save it to /config // it's a custom support file - save it to /config
new_file.close(); new_file.close();
if (LittleFS.rename(TEMP_FILENAME_PATH, EMSESP_CUSTOMSUPPORT_FILE)) { 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 return false; // no need to reboot
} else { } else {
LOG_ERROR("Failed to save custom support file"); LOG_ERROR("Failed to save custom support file");

View File

@@ -1 +1 @@
#define EMSESP_APP_VERSION "3.7.0-dev.41" #define EMSESP_APP_VERSION "3.7.0-dev.42"

View File

@@ -24,11 +24,12 @@
namespace emsesp { namespace emsesp {
WebStatusService::WebStatusService(AsyncWebServer * server, SecurityManager * securityManager) { WebStatusService::WebStatusService(AsyncWebServer * server, SecurityManager * securityManager)
: _securityManager(securityManager) {
// GET // GET
server->on(EMSESP_SYSTEM_STATUS_SERVICE_PATH, HTTP_GET, [this](AsyncWebServerRequest * request) { systemStatus(request); }); 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); }); 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(); auto * response = new AsyncJsonResponse();
JsonObject root = response->getRoot(); JsonObject root = response->getRoot();
// get action and optional param // get action and any optional param
std::string action = json["action"]; std::string action = json["action"];
std::string param = json["param"]; // is optional 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; bool ok = true;
if (action == "checkUpgrade") { if (action == "checkUpgrade") {
ok = checkUpgrade(root, param); ok = checkUpgrade(root, param);
@@ -161,6 +166,8 @@ void WebStatusService::action(AsyncWebServerRequest * request, JsonVariant json)
ok = exportData(root, param); ok = exportData(root, param);
} else if (action == "customSupport") { } else if (action == "customSupport") {
ok = customSupport(root); ok = customSupport(root);
} else if (action == "uploadURL" && is_admin) {
ok = uploadURL(param.c_str());
} }
#if defined(EMSESP_UNITY) #if defined(EMSESP_UNITY)
@@ -184,6 +191,7 @@ void WebStatusService::action(AsyncWebServerRequest * request, JsonVariant json)
request->send(response); request->send(response);
} }
// action = checkUpgrade
// returns true if there is an upgrade available // returns true if there is an upgrade available
bool WebStatusService::checkUpgrade(JsonObject root, std::string & latest_version) { bool WebStatusService::checkUpgrade(JsonObject root, std::string & latest_version) {
version::Semver200_version settings_version(EMSESP_APP_VERSION); version::Semver200_version settings_version(EMSESP_APP_VERSION);
@@ -198,6 +206,7 @@ bool WebStatusService::checkUpgrade(JsonObject root, std::string & latest_versio
return true; return true;
} }
// action = allvalues
// output all the devices and the values // output all the devices and the values
void WebStatusService::allvalues(JsonObject output) { void WebStatusService::allvalues(JsonObject output) {
JsonDocument doc; JsonDocument doc;
@@ -226,6 +235,7 @@ void WebStatusService::allvalues(JsonObject output) {
EMSESP::temperaturesensor_.get_value_info(device_output, value); EMSESP::temperaturesensor_.get_value_info(device_output, value);
} }
// action = export
// returns data for a specific feature/settings as a json object // returns data for a specific feature/settings as a json object
bool WebStatusService::exportData(JsonObject root, std::string & type) { bool WebStatusService::exportData(JsonObject root, std::string & type) {
root["type"] = type; root["type"] = type;
@@ -253,7 +263,8 @@ bool WebStatusService::exportData(JsonObject root, std::string & type) {
return true; 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) { bool WebStatusService::customSupport(JsonObject root) {
#ifndef EMSESP_STANDALONE #ifndef EMSESP_STANDALONE
// check if we have custom support file uploaded // check if we have custom support file uploaded
@@ -275,4 +286,12 @@ bool WebStatusService::customSupport(JsonObject root) {
return true; 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 } // namespace emsesp

View File

@@ -12,7 +12,7 @@ class WebStatusService {
public: public:
WebStatusService(AsyncWebServer * server, SecurityManager * securityManager); 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 #ifndef EMSESP_STANDALONE
protected: protected:
#endif #endif
@@ -20,9 +20,14 @@ class WebStatusService {
void action(AsyncWebServerRequest * request, JsonVariant json); void action(AsyncWebServerRequest * request, JsonVariant json);
private: private:
SecurityManager * _securityManager;
// actions
bool checkUpgrade(JsonObject root, std::string & latest_version); bool checkUpgrade(JsonObject root, std::string & latest_version);
bool exportData(JsonObject root, std::string & type); bool exportData(JsonObject root, std::string & type);
bool customSupport(JsonObject root); bool customSupport(JsonObject root);
bool uploadURL(const char * url);
void allvalues(JsonObject output); void allvalues(JsonObject output);
}; };