8000 feat: detect setups without ota partition setup · marcelkottmann/esp32-javascript@f19e533 · GitHub
[go: up one dir, main page]

Skip to content

Commit f19e533

Browse files
feat: detect setups without ota partition setup
1 parent 953d870 commit f19e533

File tree

11 files changed

+76
-26
lines changed

11 files changed

+76
-26
lines changed

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,13 @@ If you need more than this, you can create your own esp-idf component below `./c
9292
Additionally you have to set your component name in the top level `./CMakeLists.txt`. Refer to the documentation next to the setting `ESP32_JS_PROJECT_NAME`.
9393
See [ESP Build System](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/build-system.html) for information on how to create a component with the esp-idf build system.
9494
95+
### Native OTA
96+
97+
You can perform a native firmware OTA upgrade by calling the URL /setup . There is a section called "Native OTA" where you can provide two urls to the new images: One for the actual firmware image (normally named esp32-javascript.bin in your build directory) and the other for the JS modules image (normally named modules.bin in your build directory).
98+
99+
The upgrade is performed in the background. You can check the upgrade status either by staying on the upgrade page, which is reloaded automatically every ~20 seconds or click on "Upgrade status" in the setup page.
100+
101+
After upgrade has finished you have to restart the device to load the new firmware.
95102
### Clean
96103
97104
You can clean the project by executing

components/esp32-javascript/esp32-javascript.c

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -822,6 +822,24 @@ duk_ret_t el_partition_write(duk_context *ctx)
822822
}
823823
}
824824

825+
bool isNativeOtaSupported()
826+
{
827+
if (esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_OTA, "otadata") == NULL)
828+
{
829+
return false;
830+
}
831+
else
832+
{
833+
return true;
834+
}
835+
}
836+
837+
duk_ret_t el_is_native_ota_supported(duk_context *ctx)
838+
{
839+
duk_push_boolean(ctx, isNativeOtaSupported());
840+
return 1;
841+
}
842+
825843
duk_ret_t el_readAndFreeString(duk_context *ctx)
826844
{
827845
char *str = duk_to_int(ctx, 0);
@@ -919,20 +937,26 @@ void duktape_task(void *ignore)
919937
duk_push_c_function(ctx, atob, 1 /*nargs*/);
920938
duk_put_global_string(ctx, "atob");
921939

922-
duk_push_c_function(ctx, el_ota_begin, 0 /*nargs*/);
923-
duk_put_global_string(ctx, "el_ota_begin");
940+
if (isNativeOtaSupported())
941+
{
942+
duk_push_c_function(ctx, el_ota_begin, 0 /*nargs*/);
943+
duk_put_global_string(ctx, "el_ota_begin");
944+
945+
duk_push_c_function(ctx, el_ota_write, 2 /*nargs*/);
946+
duk_put_global_string(ctx, "el_ota_write");
924947

925-
duk_push_c_function(ctx, el_ota_write, 2 /*nargs*/);
926-
duk_put_global_string(ctx, "el_ota_write");
948+
duk_push_c_function(ctx, el_ota_end, 1 /*nargs*/);
949+
duk_put_global_string(ctx, "el_ota_end");
927950

928-
duk_push_c_function(ctx, el_ota_end, 1 /*nargs*/);
929-
duk_put_global_string(ctx, "el_ota_end");
951+
duk_push_c_function(ctx, el_ota_switch_boot_partition, 0 /*nargs*/);
952+
duk_put_global_string(ctx, "el_ota_switch_boot_partition");
930953

931-
duk_push_c_function(ctx, el_ota_switch_boot_partition, 0 /*nargs*/);
932-
duk_put_global_string(ctx, "el_ota_switch_boot_partition");
954+
duk_push_c_function(ctx, el_ota_find_next_modules_partition, 0 /*nargs*/);
955+
duk_put_global_string(ctx, "el_ota_find_next_modules_partition");
956+
}
933957

934-
duk_push_c_function(ctx, el_ota_find_next_modules_partition, 0 /*nargs*/);
935-
duk_put_global_string(ctx, "el_ota_find_next_modules_partition");
958+
duk_push_c_function(ctx, el_is_native_ota_supported, 0 /*nargs*/);
959+
duk_put_global_string(ctx, "el_is_native_ota_supported");
936960

937961
duk_push_c_function(ctx, el_partition_erase, 1 /*nargs*/);
938962
duk_put_global_string(ctx, "el_partition_erase");

components/esp32-javascript/include/esp32-javascript.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ extern "C"
6767
void loadJS(duk_context *ctx, const char *name, char *start, char *end);
6868

6969
int esp32_javascript_init();
70+
bool isNativeOtaSupported();
7071

7172
#ifdef __cplusplus
7273
}

components/esp32-javascript/modules/esp32-javascript/config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ function reloadConfig() {
3434
}
3535
catch (error) {
3636
exports.config = firmware_config_1.default;
37-
console.error("An error ocurred while accessing config. Maybe it does not exist.");
37+
console.error("Using default config. Seems like you never changed the config.");
3838
}
3939
}
4040
exports.reloadConfig = reloadConfig;

components/esp32-javascript/modules/esp32-javascript/config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ export function reloadConfig(): void {
4949
} catch (error) {
5050
config = firmwareConfig;
5151
console.error(
52-
"An error ocurred while accessing config. Maybe it does not exist."
52+
"Using default config. Seems like you never changed the config."
5353
);
5454
}
5555
}

components/esp32-javascript/modules/esp32-javascript/configserver.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -220,9 +220,11 @@ function startConfigServer() {
220220
.map(function (e) {
221221
return e.filename + " (" + (e.size === undefined ? "?" : Math.floor(e.size / 1024)) + " kB) <form action=\"/viewlog\" method=\"post\" class=\"inline-form\"><button class=\"input\" type=\"submit\" name=\"file\" value=\"" + filelogging_1.FILE_LOGGING_DIRECTORY + "/" + e.filename + "\">View</button></form> <form action=\"/deletelog\" method=\"post\" class=\"inline-form\"><button class=\"input\" type=\"submit\" name=\"file\" value=\"" + filelogging_1.FILE_LOGGING_DIRECTORY + "/" + e.filename + "\">Delete</button></form><br />";
222222
})
223-
.join("") + "\n </form>\n </div>\n \n <h2>Native OTA Upgrade</h2>\n <form action=\"/native-ota\" method=\"post\" class=\"formpad\">\n <div class=\"formpad\"><label for=\"appbin\" class=\"formlabel\">URL to app binary</label><input type=\"text\" name=\"appbin\" class=\"fill input\" value=\"\" /></div>\n <div class=\"formpad\"><label for=\"modulesbin\" class=\"formlabel\">URL to modules binary</label><input type=\"text\" name=\"modulesbin\" class=\"fill input\" value=\"\" /></div>\n <div class=\"formpad\"><input type=\"submit\" value=\"Upgrade\" class=\"formpad input\" " + (upgradeStatus.status === "inprogress" ? "disabled" : "") + "/> " + (upgradeStatus.status !== "idle"
224-
? '<a href="/native-ota">Upgrade status</a>'
225-
: "") + "</div>\n </form>\n\n <h2>Request restart</h2>\n <form action=\"/restart\" method=\"post\"><div class=\"formpad\"><input type=\"submit\" value=\"Restart\" class=\"formpad input\"/></div></form>\n <h2>Uptime</h2>\n <div class=\"formpad\">\n Boot time: " + boot_1.getBootTime() + "\n </div>\n <div class=\"formpad\">\n Uptime (hours): " + Math.floor((Date.now() - boot_1.getBootTime().getTime()) / 10 / 60 / 60) /
223+
.join("") + "\n </form>\n </div>\n \n " + (el_is_native_ota_supported()
224+
? "<h2>Native OTA Upgrade</h2>\n <form action=\"/native-ota\" method=\"post\" class=\"formpad\">\n <div class=\"formpad\"><label for=\"appbin\" class=\"formlabel\">URL to app binary</label><input type=\"text\" name=\"appbin\" class=\"fill input\" value=\"\" /></div>\n <div class=\"formpad\"><label for=\"modulesbin\" class=\"formlabel\">URL to modules binary</label><input type=\"text\" name=\"modulesbin\" class=\"fill input\" value=\"\" /></div>\n <div class=\"formpad\"><input type=\"submit\" value=\"Upgrade\" class=\"formpad input\" " + (upgradeStatus.status === "inprogress" ? "disabled" : "") + "/> " + (upgradeStatus.status !== "idle"
225+
? '<a href="/native-ota">Upgrade status</a>'
226+
: "") + "</div>\n </form>"
227+
: "") + "\n\n <h2>Request restart</h2>\n <form action=\"/restart\" method=\"post\"><div class=\"formpad\"><input type=\"submit\" value=\"Restart\" class=\"formpad input\"/></div></form>\n <h2>Uptime</h2>\n <div class=\"formpad\">\n Boot time: " + boot_1.getBootTime() + "\n </div>\n <div class=\"formpad\">\n Uptime (hours): " + Math.floor((Date.now() - boot_1.getBootTime().getTime()) / 10 / 60 / 60) /
226228
100 + "<br />\n </div>\n <div class=\"formpad\">\n Boot time is only available if a valid 'JS file url' is configured, otherwise it starts at unix epoch (1970).\n </div>");
227229
successMessage = "";
228230
errorMessage = "";

components/esp32-javascript/modules/esp32-javascript/configserver.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -341,18 +341,22 @@ export function startConfigServer(): void {
341341
</form>
342342
</div>
343343
344-
<h2>Native OTA Upgrade</h2>
344+
${
345+
el_is_native_ota_supported()
346+
? `<h2>Native OTA Upgrade</h2>
345347
<form action="/native-ota" method="post" class="formpad">
346348
<div class="formpad"><label for="appbin" class="formlabel">URL to app binary</label><input type="text" name="appbin" class="fill input" value="" /></div>
347349
<div class="formpad"><label for="modulesbin" class="formlabel">URL to modules binary</label><input type="text" name="modulesbin" class="fill input" value="" /></div>
348350
<div class="formpad"><input type="submit" value="Upgrade" class="formpad input" ${
349351
upgradeStatus.status === "inprogress" ? "disabled" : ""
350352
}/> ${
351-
upgradeStatus.status !== "idle"
352-
? '<a href="/native-ota">Upgrade status</a>'
353+
upgradeStatus.status !== "idle"
354+
? '<a href="/native-ota">Upgrade status</a>'
355+
: ""
356+
}</div>
357+
</form>`
353358
: ""
354-
}</div>
355-
</form>
359+
}
356360
357361
<h2>Request restart</h2>
358362
<form action="/restart" method="post"><div class="formpad"><input type="submit" value="Restart" class="formpad input"/></div></form>

components/esp32-javascript/modules/esp32-javascript/esp32-javascript.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ declare function listDir(path: string): string[];
9494
declare function mkdir(path: string): void;
9595

9696
// ota
97+
declare function el_is_native_ota_supported(): boolean;
9798
declare function el_ota_begin(): number;
9899
declare function el_ota_write F438 (handle: number, data: Uint8Array): number;
99100
declare function el_ota_end(handle: number): number;

components/esp32-javascript/modules/esp32-javascript/native-ota.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,10 @@ function upgradeModules(partition, modulesImageUrl, submitSuccess, submitError)
100100
return client;
101101
}
102102
exports.upgrade = function (appImageUrl, modulesImageUrl, onError, onFinish) {
103+
if (!el_is_native_ota_supported()) {
104+
onError && onError("Native OTA is not supported.");
105+
return;
106+
}
103107
console.log("Start native firmware upgrade:");
104108
console.log("App image: " + appImageUrl);
105109
console.log("Modules image: " + modulesImageUrl);

components/esp32-javascript/modules/esp32-javascript/native-ota.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,11 @@ export const upgrade = (
138138
onError: (message: string) => void,
139139
onFinish: () => void
140140
): void => {
141+
if (!el_is_native_ota_supported()) {
142+
onError && onError("Native OTA is not supported.");
143+
return;
144+
}
145+
141146
console.log(`Start native firmware upgrade:`);
142147
console.log(`App image: ${appImageUrl}`);
143148
console.log(`Modules image: ${modulesImageUrl}`);

components/spiffs-events/spiffs-events.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ char *readFile(const char *path)
103103
FILE *f = fopen(path, "r");
104104
if (f == NULL)
105105
{
106-
jslog(ERROR, "Failed to open file for reading");
106+
jslog(ERROR, "Failed to open file '%s' for reading.", path);
107107
return NULL;
108108
}
109109

@@ -132,7 +132,7 @@ int writeFile(const char *path, const char *content)
132132
FILE *f = fopen(path, "w");
133133
if (f == NULL)
134134
{
135-
jslog(ERROR, "Failed to open file '%s'for writing, errno %i", path, errno);
135+
jslog(ERROR, "Failed to open file '%s' for writing, errno %i", path, errno);
136136
return -1;
137137
}
138138
int result = fputs(content, f);
@@ -278,14 +278,16 @@ void registerBindings(duk_context *ctx)
278278
duk_put_global_string(ctx, "fileSize");
279279
duk_push_c_function(ctx, el_listDir, 1);
280280
duk_put_global_string(ctx, "listDir");
281-
// duk_push_c_function(ctx, el_mkdir, 1);
282-
// duk_put_global_string(ctx, "mkdir");
283281
}
284282

285283
void initSpiffs(duk_context *ctx)
286284
{
287-
esp_partition_t *partition = esp_ota_get_boot_partition();
288-
const char *modulesLabel = strcmp(partition->label, "ota_1") == 0 ? "modules_1" : "modules";
285+
const char *modulesLabel = "modules";
286+
if (isNativeOtaSupported())
287+
{
288+
esp_partition_t *partition = esp_ota_get_boot_partition();
289+
modulesLabel = partition != NULL && strcmp(partition->label, "ota_1") == 0 ? "modules_1" : "modules";
290+
}
289291
initFilesystem(modulesLabel, "/modules");
290292

291293
initFilesystem("data", "/data");

0 commit comments

Comments
 (0)
0