Skip to content

Commit bc23fcc

Browse files
committed
Initial Upload
0 parents  commit bc23fcc

File tree

7 files changed

+1372
-0
lines changed

7 files changed

+1372
-0
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
sdkconfig.old
2+
build
3+
*~

CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
cmake_minimum_required(VERSION 3.5)
2+
3+
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
4+
project(esp32-softap-ota)

compile_and_flash.sh

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#!/bin/bash
2+
3+
killall -SIGUSR2 gtkterm
4+
. /opt/esp32/esp-idf/export.sh > /dev/null 2>&1
5+
idf.py app
6+
idf.py -p /dev/ttyUSB1 flash -b 921600
7+
killall -SIGUSR1 gtkterm

main/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
idf_component_register(SRCS "main.c"
2+
INCLUDE_DIRS "."
3+
EMBED_TXTFILES web/index.html
4+
)

main/main.c

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
#include <string.h>
2+
3+
#include <freertos/FreeRTOS.h>
4+
#include <esp_http_server.h>
5+
#include <freertos/task.h>
6+
#include <esp_ota_ops.h>
7+
#include <esp_system.h>
8+
#include <nvs_flash.h>
9+
#include <sys/param.h>
10+
#include <esp_wifi.h>
11+
12+
#define WIFI_SSID "ESP32 OTA Update"
13+
14+
/*
15+
* Serve OTA update portal (index.html)
16+
*/
17+
extern const uint8_t index_html_start[] asm("_binary_index_html_start");
18+
extern const uint8_t index_html_end[] asm("_binary_index_html_end");
19+
20+
esp_err_t index_get_handler(httpd_req_t *req)
21+
{
22+
httpd_resp_send(req, (const char *) index_html_start, index_html_end - index_html_start);
23+
return ESP_OK;
24+
}
25+
26+
/*
27+
* Handle OTA file upload
28+
*/
29+
esp_err_t update_post_handler(httpd_req_t *req)
30+
{
31+
char buf[1000];
32+
esp_ota_handle_t ota_handle;
33+
int remaining = req->content_len;
34+
35+
const esp_partition_t *ota_partition = esp_ota_get_next_update_partition(NULL);
36+
ESP_ERROR_CHECK(esp_ota_begin(ota_partition, OTA_SIZE_UNKNOWN, &ota_handle));
37+
38+
while (remaining > 0) {
39+
int recv_len = httpd_req_recv(req, buf, MIN(remaining, sizeof(buf)));
40+
41+
// Timeout Error: Just retry
42+
if (recv_len == HTTPD_SOCK_ERR_TIMEOUT) {
43+
continue;
44+
45+
// Serious Error: Abort OTA
46+
} else if (recv_len <= 0) {
47+
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Protocol Error");
48+
return ESP_FAIL;
49+
}
50+
51+
// Successful Upload: Flash firmware chunk
52+
if (esp_ota_write(ota_handle, (const void *)buf, recv_len) != ESP_OK) {
53+
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Flash Error");
54+
return ESP_FAIL;
55+
}
56+
57+
remaining -= recv_len;
58+
}
59+
60+
// Validate and switch to new OTA image and reboot
61+
if (esp_ota_end(ota_handle) != ESP_OK || esp_ota_set_boot_partition(ota_partition) != ESP_OK) {
62+
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Validation / Activation Error");
63+
return ESP_FAIL;
64+
}
65+
66+
httpd_resp_sendstr(req, "Firmware update complete, rebooting now!");
67+
68+
vTaskDelay(500 / portTICK_PERIOD_MS);
69+
esp_restart();
70+
71+
return ESP_OK;
72+
}
73+
74+
/*
75+
* HTTP Server
76+
*/
77+
httpd_uri_t index_get = {
78+
.uri = "/",
79+
.method = HTTP_GET,
80+
.handler = index_get_handler,
81+
.user_ctx = NULL
82+
};
83+
84+
httpd_uri_t update_post = {
85+
.uri = "/update",
86+
.method = HTTP_POST,
87+
.handler = update_post_handler,
88+
.user_ctx = NULL
89+
};
90+
91+
static esp_err_t http_server_init(void)
92+
{
93+
static httpd_handle_t http_server = NULL;
94+
95+
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
96+
97+
if (httpd_start(&http_server, &config) == ESP_OK) {
98+
httpd_register_uri_handler(http_server, &index_get);
99+
httpd_register_uri_handler(http_server, &update_post);
100+
}
101+
102+
return http_server == NULL ? ESP_FAIL : ESP_OK;
103+
}
104+
105+
/*
106+
* WiFi configuration
107+
*/
108+
static esp_err_t softap_init(void)
109+
{
110+
esp_err_t res = ESP_OK;
111+
112+
res |= esp_netif_init();
113+
res |= esp_event_loop_create_default();
114+
esp_netif_create_default_wifi_ap();
115+
116+
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
117+
res |= esp_wifi_init(&cfg);
118+
119+
wifi_config_t wifi_config = {
120+
.ap = {
121+
.ssid = WIFI_SSID,
122+
.ssid_len = strlen(WIFI_SSID),
123+
.channel = 6,
124+
.authmode = WIFI_AUTH_OPEN,
125+
.max_connection = 3
126+
},
127+
};
128+
129+
res |= esp_wifi_set_mode(WIFI_MODE_AP);
130+
res |= esp_wifi_set_config(ESP_IF_WIFI_AP, &wifi_config);
131+
res |= esp_wifi_start();
132+
133+
return res;
134+
}
135+
136+
void app_main(void) {
137+
esp_err_t ret = nvs_flash_init();
138+
139+
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
140+
ESP_ERROR_CHECK(nvs_flash_erase());
141+
ret = nvs_flash_init();
142+
}
143+
144+
ESP_ERROR_CHECK(ret);
145+
ESP_ERROR_CHECK(softap_init());
146+
ESP_ERROR_CHECK(http_server_init());
147+
148+
/* Mark current app as valid */
149+
const esp_partition_t *partition = esp_ota_get_running_partition();
150+
printf("Currently running partition: %s\r\n", partition->label);
151+
152+
esp_ota_img_states_t ota_state;
153+
if (esp_ota_get_state_partition(partition, &ota_state) == ESP_OK) {
154+
if (ota_state == ESP_OTA_IMG_PENDING_VERIFY) {
155+
esp_ota_mark_app_valid_cancel_rollback();
156+
}
157+
}
158+
159+
while(1) vTaskDelay(10);
160+
}

main/web/index.html

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<!DOCTYPE html>
2+
3+
<html>
4+
<head>
5+
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
6+
<title>ESP32 OTA Update</title>
7+
<script>
8+
function startUpload() {
9+
var otafile = document.getElementById("otafile").files;
10+
11+
if (otafile.length == 0) {
12+
alert("No file selected!");
13+
} else {
14+
document.getElementById("otafile").disabled = true;
15+
document.getElementById("upload").disabled = true;
16+
17+
var file = otafile[0];
18+
var xhr = new XMLHttpRequest();
19+
xhr.onreadystatechange = function() {
20+
if (xhr.readyState == 4) {
21+
if (xhr.status == 200) {
22+
document.open();
23+
document.write(xhr.responseText);
24+
document.close();
25+
} else if (xhr.status == 0) {
26+
alert("Server closed the connection abruptly!");
27+
location.reload()
28+
} else {
29+
alert(xhr.status + " Error!\n" + xhr.responseText);
30+
location.reload()
31+
}
32+
}
33+
};
34+
35+
xhr.upload.onprogress = function (e) {
36+
var progress = document.getElementById("progress");
37+
progress.textContent = "Progress: " + (e.loaded / e.total * 100).toFixed(0) + "%";
38+
};
39+
xhr.open("POST", "/update", true);
40+
xhr.send(file);
41+
}
42+
}
43+
</script>
44+
</head>
45+
<body>
46+
<h1>ESP32 OTA Firmware Update</h1>
47+
<div>
48+
<label for="otafile">Firmware file:</label>
49+
<input type="file" id="otafile" name="otafile" />
50+
</div>
51+
<div>
52+
<button id="upload" type="button" onclick="startUpload()">Upload</button>
53+
</div>
54+
<div id="progress"></div>
55+
</body>
56+
</html>

0 commit comments

Comments
 (0)