diff --git a/interface/src/api/endpoints.ts b/interface/src/api/endpoints.ts index 08f5dea0f..c0d2842e6 100644 --- a/interface/src/api/endpoints.ts +++ b/interface/src/api/endpoints.ts @@ -57,7 +57,7 @@ export const alovaInstance = createAlova({ }); export const alovaInstanceGH = createAlova({ - baseURL: 'https://api.github.com/repos/emsesp/EMS-ESP32/releases', + baseURL: process.env.NODE_ENV === 'development' ? '/gh' : 'https://api.github.com/repos/emsesp/EMS-ESP32/releases', statesHook: ReactHook, requestAdapter: xhrRequestAdapter() }); diff --git a/interface/src/app/settings/Version.tsx b/interface/src/app/settings/Version.tsx index 2855c8684..4c9b904ef 100644 --- a/interface/src/app/settings/Version.tsx +++ b/interface/src/app/settings/Version.tsx @@ -1,4 +1,4 @@ -import { useState } from 'react'; +import { useEffect, useState } from 'react'; import { toast } from 'react-toastify'; import CancelIcon from '@mui/icons-material/Cancel'; @@ -36,7 +36,7 @@ const Version = () => { const [upgradeAvailable, setUpgradeAvailable] = useState(false); const { send: sendCheckUpgrade } = useRequest( - (version: string) => callAction({ action: 'checkUpgrade', param: version }), + (versions: string) => callAction({ action: 'checkUpgrade', param: versions }), { immediate: false } @@ -54,27 +54,18 @@ const Version = () => { } ); - // called immediately to get the latest version, on page load - const { data: latestVersion } = useRequest(getStableVersion, { - // uncomment next 2 lines for testing, uses https://github.com/emsesp/EMS-ESP32/releases/download/v3.6.5/EMS-ESP-3_6_5-ESP32-16MB+.bin - // immediate: false, - // initialData: '3.6.5' - }).onSuccess((event) => { - if (!useDev) { - void sendCheckUpgrade(event.data); - } - }); + // called immediately to get the latest versions on page load + const { data: latestVersion } = useRequest(getStableVersion); + const { data: latestDevVersion } = useRequest(getDevVersion); - // called immediately to get the latest version, on page load, then check for upgrade (works for both dev and stable) - const { data: latestDevVersion } = useRequest(getDevVersion, { - // uncomment next 2 lines for testing, uses https://github.com/emsesp/EMS-ESP32/releases/download/latest/EMS-ESP-3_7_0-dev_31-ESP32-16MB+.bin - // immediate: false, - // initialData: '3.7.0-dev.32' - }).onSuccess((event) => { - if (useDev) { - void sendCheckUpgrade(event.data); + useEffect(() => { + if (latestVersion && latestDevVersion) { + console.log("Latest versions, stable: " + latestVersion + " dev: " + latestDevVersion); + sendCheckUpgrade(latestDevVersion + "," + latestVersion).catch((error: Error) => { + console.error("Failed to check upgrade:", error); + }); } - }); + }, [latestVersion, latestDevVersion]); const STABLE_URL = 'https://github.com/emsesp/EMS-ESP32/releases/download/'; const STABLE_RELNOTES_URL = diff --git a/interface/vite.config.ts b/interface/vite.config.ts index faf902d63..5198143d4 100644 --- a/interface/vite.config.ts +++ b/interface/vite.config.ts @@ -20,7 +20,8 @@ export default defineConfig(({ command, mode }) => { changeOrigin: true, secure: false }, - '/rest': 'http://localhost:3080' + '/rest': 'http://localhost:3080', + '/gh': 'http://localhost:3080' // mock for GitHub API } } }; diff --git a/mock-api/rest_server.ts b/mock-api/rest_server.ts index 9b209bba6..c27ffb40e 100644 --- a/mock-api/rest_server.ts +++ b/mock-api/rest_server.ts @@ -21,6 +21,7 @@ const router = AutoRouter({ const REST_ENDPOINT_ROOT = '/rest/'; const API_ENDPOINT_ROOT = '/api/'; +const GH_ENDPOINT_ROOT = '/gh/'; // for mock GitHub API for version checking // HTTP HEADERS for msgpack const headers = { @@ -28,6 +29,13 @@ const headers = { 'Content-type': 'application/msgpack' }; +// Versions - all without the 'v' +const THIS_VERSION = '3.7.0'; +// const THIS_VERSION = '3.6.4'; // for testing +const LATEST_STABLE_VERSION = '3.7.0'; +const LATEST_DEV_VERSION = '3.7.1-dev.4'; +const VERSION_IS_UPGRADEABLE = true; + // GLOBAL VARIABLES let countWifiScanPoll = 0; // wifi network scan let countHardwarePoll = 0; // for during an upload @@ -199,16 +207,18 @@ function custom_support() { function check_upgrade(version: string) { let data = {}; if (version) { - console.log('check upgrade from version', version); + const dev_version = version.split(',')[0]; + const stable_version = version.split(',')[1]; + console.log("latest dev version: " + dev_version + ", latest stable version: " + stable_version); + console.log('Version upgrade check from version ' + THIS_VERSION + ', upgradable: ' + VERSION_IS_UPGRADEABLE); data = { - emsesp_version: VERSION, - // upgradeable: true - upgradeable: false + emsesp_version: THIS_VERSION, + upgradeable: VERSION_IS_UPGRADEABLE }; } else { - console.log('requesting ems-esp version'); + console.log('requesting ems-esp version ('+THIS_VERSION+')'); data = { - emsesp_version: VERSION + emsesp_version: THIS_VERSION }; } return data; @@ -468,11 +478,8 @@ const VERIFY_AUTHORIZATION_ENDPOINT = REST_ENDPOINT_ROOT + 'verifyAuthorization' const SIGN_IN_ENDPOINT = REST_ENDPOINT_ROOT + 'signIn'; const GENERATE_TOKEN_ENDPOINT = REST_ENDPOINT_ROOT + 'generateToken'; -const VERSION = '3.7.0'; -// const VERSION = '3.6.4'; - let system_status = { - emsesp_version: VERSION, + emsesp_version: THIS_VERSION, bus_status: 0, // status: 2, uptime: 77186, @@ -573,7 +580,7 @@ const EMSESP_SYSTEM_INFO_ENDPOINT = API_ENDPOINT_ROOT + 'system/info'; const emsesp_info = { System: { - version: VERSION, + version: THIS_VERSION, uptime: '001+06:40:34.018', 'uptime (seconds)': 110434, freemem: 131, @@ -4878,6 +4885,18 @@ router return status(404); // not found }); +// Mock GitHub API + +router + .get(GH_ENDPOINT_ROOT + '/tags/latest', () => { + console.log('returning latest development version: ' + LATEST_DEV_VERSION); + return { name: 'v'+LATEST_DEV_VERSION }; + }) + .get(GH_ENDPOINT_ROOT + '/latest', () => { + console.log('returning latest stable version: ' + LATEST_STABLE_VERSION); + return { name: 'v'+LATEST_STABLE_VERSION }; + }); + export default router; // use this with cloudflare workers instead diff --git a/src/test/test.cpp b/src/test/test.cpp index 9aa17ae3e..05a3f791b 100644 --- a/src/test/test.cpp +++ b/src/test/test.cpp @@ -1014,22 +1014,22 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const // request.url("/api"); // EMSESP::webAPIService.webAPIService(&request, doc.as()); - char data2[] = "{\"action\":\"customSupport\", \"param\":\"hello\"}"; - deserializeJson(doc, data2); - request.url("/rest/action"); - EMSESP::webStatusService.action(&request, doc.as()); + // char data2[] = "{\"action\":\"customSupport\", \"param\":\"hello\"}"; + // deserializeJson(doc, data2); + // request.url("/rest/action"); + // EMSESP::webStatusService.action(&request, doc.as()); - char data3[] = "{\"action\":\"export\", \"param\":\"schedule\"}"; - deserializeJson(doc, data3); - request.url("/rest/action"); - EMSESP::webStatusService.action(&request, doc.as()); + // char data3[] = "{\"action\":\"export\", \"param\":\"schedule\"}"; + // deserializeJson(doc, data3); + // request.url("/rest/action"); + // EMSESP::webStatusService.action(&request, doc.as()); - char data4[] = "{\"action\":\"export\", \"param\":\"allvalues\"}"; - deserializeJson(doc, data4); - request.url("/rest/action"); - EMSESP::webStatusService.action(&request, doc.as()); + // char data4[] = "{\"action\":\"export\", \"param\":\"allvalues\"}"; + // deserializeJson(doc, data4); + // request.url("/rest/action"); + // EMSESP::webStatusService.action(&request, doc.as()); - char data5[] = "{\"action\":\"checkUpgrade\", \"param\":\"3.7.0-dev.99\"}"; + char data5[] = "{\"action\":\"checkUpgrade\", \"param\":\"3.7.1-dev.99,3.7.0\"}"; deserializeJson(doc, data5); request.url("/rest/action"); EMSESP::webStatusService.action(&request, doc.as()); diff --git a/src/web/WebStatusService.cpp b/src/web/WebStatusService.cpp index 4c15f0227..85999d688 100644 --- a/src/web/WebStatusService.cpp +++ b/src/web/WebStatusService.cpp @@ -203,18 +203,27 @@ void WebStatusService::action(AsyncWebServerRequest * request, JsonVariant json) } // action = checkUpgrade -bool WebStatusService::checkUpgrade(JsonObject root, std::string & latest_version) { - root["emsesp_version"] = EMSESP_APP_VERSION; +bool WebStatusService::checkUpgrade(JsonObject root, std::string & versions) { + root["emsesp_version"] = EMSESP_APP_VERSION; // always send back current version + + // versions holds the latest development version and stable version in one string, comma separated + std::string latest_dev_version = versions.substr(0, versions.find(',')); + std::string latest_stable_version = versions.substr(versions.find(',') + 1); + + if (!versions.empty()) { + version::Semver200_version this_version(EMSESP_APP_VERSION); // current version + bool using_dev_version = !this_version.prerelease().empty(); + version::Semver200_version latest_version(using_dev_version ? latest_dev_version : latest_stable_version); // latest version + + root["upgradeable"] = (latest_version > this_version); - if (!latest_version.empty()) { #if defined(EMSESP_DEBUG) - emsesp::EMSESP::logger().debug("Checking for upgrade: %s < %s", EMSESP_APP_VERSION, latest_version.c_str()); + emsesp::EMSESP::logger().debug("Checking for version upgrade. This version=%s, latest dev=%s, latest stable=%s. Upgradeable=%s", + EMSESP_APP_VERSION, + latest_dev_version.c_str(), + latest_stable_version.c_str(), + root["upgradeable"].as() ? "true" : "false"); #endif - - version::Semver200_version settings_version(EMSESP_APP_VERSION); - version::Semver200_version this_version(latest_version); - - root["upgradeable"] = (this_version > settings_version); } return true; // always ok