This commit is contained in:
2025-11-15 11:56:42 +03:00
parent bb13b7b3b6
commit 80307fc435
42 changed files with 4336 additions and 12 deletions

View File

@@ -0,0 +1,12 @@
# The following lines of boilerplate have to be in your project's CMakeLists
# in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)
# (Not part of the boilerplate)
# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection.
#set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common)
set(EXTRA_COMPONENT_DIRS ../)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(example_ota_ws_update)

View File

@@ -0,0 +1,11 @@
{
"folders": [
{
"path": "."
},
{
"path": ".."
}
],
"settings": {}
}

View File

@@ -0,0 +1,15 @@
# Embed the server root certificate into the final binary
idf_component_register(
SRCS
example_ota_ws_update.c
example_echo_ws_server.c
REQUIRES
ota_ws_update
nvs_wifi_connect
esp_http_server
mdns
esp_wifi
EMBED_FILES
example_echo_ws_server.html
)

View File

@@ -0,0 +1,174 @@
/* WebSocket Echo Server Example
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <esp_wifi.h>
#include <esp_event.h>
#include <esp_log.h>
#include <esp_http_server.h>
#include "nvs_wifi_connect.h"
#include "ota_ws_update.h"
/* A simple example that demonstrates using websocket echo server
*/
static const char *TAG = "example_ws_echo_server";
/*
* This handler echos back the received ws data
* and triggers an async send if certain message received
*/
static esp_err_t echo_handler(httpd_req_t *req)
{
if (req->method == HTTP_GET) {
ESP_LOGI(TAG, "Handshake done, the new connection was opened");
return ESP_OK;
}
httpd_ws_frame_t ws_pkt;
uint8_t *buf = NULL;
memset(&ws_pkt, 0, sizeof(httpd_ws_frame_t));
ws_pkt.type = HTTPD_WS_TYPE_TEXT;
/* Set max_len = 0 to get the frame len */
esp_err_t ret = httpd_ws_recv_frame(req, &ws_pkt, 0);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "httpd_ws_recv_frame failed to get frame len with %d", ret);
return ret;
}
//ESP_LOGI(TAG, "frame len is %d", ws_pkt.len);
if (ws_pkt.len) {
/* ws_pkt.len + 1 is for NULL termination as we are expecting a string */
buf = calloc(1, ws_pkt.len + 1);
if (buf == NULL) {
ESP_LOGE(TAG, "Failed to calloc memory for buf");
return ESP_ERR_NO_MEM;
}
ws_pkt.payload = buf;
/* Set max_len = ws_pkt.len to get the frame payload */
ret = httpd_ws_recv_frame(req, &ws_pkt, ws_pkt.len);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "httpd_ws_recv_frame failed with %d", ret);
free(buf);
return ret;
}
//ESP_LOGI(TAG, "Got packet with message: %s", ws_pkt.payload);
}
//ESP_LOGI(TAG, "Packet type: %d", ws_pkt.type);
ret = httpd_ws_send_frame(req, &ws_pkt);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "httpd_ws_send_frame failed with %d", ret);
}
free(buf);
return ret;
}
static const httpd_uri_t example_ws = {
.uri = "/ws",
.method = HTTP_GET,
.handler = echo_handler,
.user_ctx = NULL,
.is_websocket = true
};
static esp_err_t get_handler(httpd_req_t *req)
{
extern const unsigned char example_echo_ws_server_html_start[] asm("_binary_example_echo_ws_server_html_start");
extern const unsigned char example_echo_ws_server_html_end[] asm("_binary_example_echo_ws_server_html_end");
const size_t example_echo_ws_server_html_size = (example_echo_ws_server_html_end - example_echo_ws_server_html_start);
httpd_resp_send_chunk(req, (const char *)example_echo_ws_server_html_start, example_echo_ws_server_html_size);
httpd_resp_sendstr_chunk(req, NULL);
return ESP_OK;
}
static const httpd_uri_t example_gh = {
.uri = "/",
.method = HTTP_GET,
.handler = get_handler,
.user_ctx = NULL};
esp_err_t example_register_uri_handler(httpd_handle_t server);
static httpd_handle_t start_webserver(void)
{
httpd_handle_t server = NULL;
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
config.stack_size = 4096*4;
// Start the httpd server
ESP_LOGI(TAG, "Starting server on port: '%d'", config.server_port);
if (httpd_start(&server, &config) == ESP_OK) {
// Registering the ws handler
ESP_LOGI(TAG, "Registering URI handlers");
example_register_uri_handler(server);
nvs_wifi_connect_register_uri_handler(server);
ota_ws_register_uri_handler(server);
return server;
}
ESP_LOGI(TAG, "Error starting server!");
return NULL;
}
static esp_err_t stop_webserver(httpd_handle_t server)
{
// Stop the httpd server
return httpd_stop(server);
}
static void disconnect_handler(void* arg, esp_event_base_t event_base,
int32_t event_id, void* event_data)
{
httpd_handle_t* server = (httpd_handle_t*) arg;
if (*server) {
ESP_LOGI(TAG, "Stopping webserver");
if (stop_webserver(*server) == ESP_OK) {
*server = NULL;
} else {
ESP_LOGE(TAG, "Failed to stop http server");
}
}
}
static void connect_handler(void* arg, esp_event_base_t event_base,
int32_t event_id, void* event_data)
{
httpd_handle_t* server = (httpd_handle_t*) arg;
if (*server == NULL) {
ESP_LOGI(TAG, "Starting webserver");
*server = start_webserver();
}
}
void example_echo_ws_server(void)
{
static httpd_handle_t server = NULL;
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &connect_handler, &server));
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, &disconnect_handler, &server));
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_AP_STACONNECTED, &connect_handler, &server));
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_AP_STADISCONNECTED, &disconnect_handler, &server));
/* Start the server for the first time */
server = start_webserver();
}
esp_err_t example_register_uri_handler(httpd_handle_t server)
{
esp_err_t ret = ESP_OK;
ret = httpd_register_uri_handler(server, &example_gh);
if (ret)
goto _ret;
ret = httpd_register_uri_handler(server, &example_ws);
if (ret)
goto _ret;
_ret:
return ret;
}

View File

@@ -0,0 +1,131 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<title>Example Websocket Echo Server</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<style>
.column {
float: left;
width: 100%;
margin-top: 2px;
margin-bottom: 2px;
}
.btn {
float: left;
width: 100%;
margin: 2px;
}
.cl1 {
float: left;
width: 100%;
margin: 2px;
margin-top: 2px;
margin-bottom: 2px;
}
.cl01 {
float: left;
width: 100%;
text-align: center;
margin-top: 2px;
margin-bottom: 2px;
}
.cl02 {
float: left;
width: 100%;
text-align: center;
margin-top: 2px;
margin-bottom: 2px;
}
.hdr {
float: left;
width: 100%;
text-align: center;
color: white;
background-color: blue;
padding: 5px;
margin: 5px;
}
.logstr {
width: 100%;
float: left;
}
</style>
</head>
<body>
<div class="hdr">Example Websocket Echo Server </div>
<div class="column">
<button class="btn" id="goWifi" onclick="window.location.href = '/wifi'" >Set WiFi SSID/Password -> /wifi</button>
</div>
<div class="column">
<button class="btn" id="goOta" onclick="window.location.href = '/ota'" >Ota update -> /ota</button>
</div>
<div class="cl1">
<label class="cl01" for="exampleSend">Input string for Echo</label>
<input class="cl02" type="text" id="exampleSend" placeholder="input">
</div>
<div class="cl1">
<label class="cl01" for="exampleEcho">Echo string</label>
<input class="cl02" type="text" id="exampleEcho" placeholder="output">
</div>
<script>
let exSend = document.getElementById("exampleSend");
exSend.addEventListener("input", function (e) {
//console.log(exSend.id + " " + exSend.value );
socket.send(JSON.stringify({ name: exSend.id, msg: exSend.value }));
});
function receiveWsData(data) {
//console.log(data);
try {
let obj = JSON.parse(data);
let exEcho = document.getElementById("exampleEcho");
exEcho.value = obj.msg;
}
catch {
console.log(data + " catch");
}
};
</script>
<script> // Прием, обработка и отправка данных в WS
</script>
<script> // основной старт скрипта, открыть сокет
// создать сокет по адресу
let wsHostStr = "ws://" + document.location.host + document.location.pathname;
wsHostStr += (document.location.pathname == '/') ? "ws" : "/ws";
var socket = new WebSocket(wsHostStr);
</script>
<script> // события WS
socket.onopen = function () {
console.log("connect");
};
socket.onclose = function (event) {
console.log("close");
};
socket.onerror = function () {
console.log("error");
};
socket.onmessage = function (event) {
receiveWsData(event.data);
};
</script>
</body>
</html>

View File

@@ -0,0 +1,55 @@
/* OTA example
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include "esp_log.h"
#include "esp_http_server.h"
#include "nvs_wifi_connect.h"
#include "ota_ws_update.h"
extern esp_err_t example_register_uri_handler(httpd_handle_t server);
void example_echo_ws_server(void);
//static const char *TAG = "ota_ws";
#define MDNS
#ifdef MDNS
#define HOST_NAME "esp-ota"
#include "mdns.h"
#include "lwip/apps/netbiosns.h"
#endif // MDNS
#ifdef MDNS
static void initialise_mdns(void)
{
mdns_init();
mdns_hostname_set(HOST_NAME);
mdns_instance_name_set("esp home web server");
mdns_txt_item_t serviceTxtData[] = {
{"board", "esp32"},
{"path", "/"}};
ESP_ERROR_CHECK(mdns_service_add("ESP32-WebServer", "_http", "_tcp", 80, serviceTxtData,
sizeof(serviceTxtData) / sizeof(serviceTxtData[0])));
netbiosns_init();
netbiosns_set_name(HOST_NAME);
}
#endif // MDNS
void app_main(void)
{
nvs_wifi_connect(); // return with error ?
#ifdef MDNS
initialise_mdns();
#endif // MDNS
example_echo_ws_server();
}

View File

@@ -0,0 +1,6 @@
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x4000
otadata, data, ota, , 0x2000
phy_init, data, phy, , 0x1000
ota_0, app, ota_0, , 1M
ota_1, app, ota_1, , 1M
1 # Name, Type, SubType, Offset, Size, Flags
2 nvs, data, nvs, 0x9000, 0x4000
3 otadata, data, ota, , 0x2000
4 phy_init, data, phy, , 0x1000
5 ota_0, app, ota_0, , 1M
6 ota_1, app, ota_1, , 1M

View File

@@ -0,0 +1,40 @@
-----BEGIN PRIVATE KEY-----
MIIG/gIBADANBgkqhkiG9w0BAQEFAASCBugwggbkAgEAAoIBgQDFmskeWxaJtPCV
Xydauqm6Q/wW9D0ewNUo+L9sopGz/Lrw5JdynLQDcxcioqpow5Nr9A8y8+YJc9zH
sMs4qJYDLcxROeimGlPqtrj4OxFXDyok12fxDquYTXaJzTAM+rp/i/VJJVKonYU0
DOuG8tX1lsrlfkwYixaoPUGL/WuG1srHay5NKCcXjYVUKsjHkfEgfKAhF/6cPTj6
yeKH6nNQQofOYUN5hkGgT19ek3or0dYph9r3VozyjV12/D1K+o0Vl+LQc7IX3xxN
DB9s3aGVIMglir8AY2ZjkqRyJRzbIrjufXYxw/e6uP2YQyBagEBWlsEhxKVsVOvi
O5fHfw+Svd9vgO3PRIA9bDh2isO6SHis6akgWBsXNh/FS1Kyl1IrBt+CnIsgQRzz
po7hh/TfU6VCKXL5fZR+fK6Ze12MP+B30HEXrW+VhzvhCMWjbyFIYJ1jGfd5N/zD
3E26cQPn711M+13cbKJeSWU0aX9dwQxPSXJdytORijxlFfUIAmsCAwEAAQKCAYA4
3/9JJHCNPC4O4C9klttpSE4TkULSSjBQNaBrNTN4uaJY2YKZs27Am2yqRGWF99zD
sqB5SugICngeZc1oRmW/DnyDWIaU4HkM0oDUubOY+j1oEzPQlydek9Utfoh5A+WP
9omn/v0WmRgQzjMwSU65/Cfz+/ENE2N3EwJ9t3gufD4rPbc67/aoecxJWHMnteLQ
Ne6k99IJyDlRPbBc7Gc6T5vlE+um27Sh3paVkx8T47afh4HHtPqmiXfAWoONxCU7
YXXWfIo4qB80it77QHtHdAgXxEZGug2WsDakf1bC/veZ0Qm4OkfkYzFF3DhRXTia
sffXdP6z+/nB+WG0k/qIqo5BweW3aOb+pyXATGTNVsRp98cxS6GpyZb3yUDnfiLL
vKzzMwPPJyA2X1cDVUrwTETg9jRB/UDTsYLjedar2FRkVI46lPZtvdqHLx5+UpDs
CEAooRaOi10LB52zhqhyKpy2VtsHXuhOLrGlj8R5DPGqzB9ZjlOLqsIxzXgT1+kC
gcEAzDxdkbY7xj1Q7HKOVQiRr45xijkL6kleglmBFt0DqFMETYzb4Y7xDEdU82H0
XBlOnQIc6GD4PBGQDGGURSkQya7aSEWfIIRG3PCTCzSJhghPK+olFz5+39x/QUSm
zTY9rjIzAXu/VBSnFK+bL2A+etJOQFOrhfGESbWHsbuqPbigU5q9eCAcQs/GBI1F
x1ckjRCkUxpNS1jP92GWpIPVQQYd8IFwLfcA6nJq8UoXpIZazYfqeOOyN47ns7ho
TRhfAoHBAPewKcmEfikaTExIQKckN7rpfMJRmp3oWsq18AF6nywVYylhJPFo74Tw
6P/lsFJqjgCbN2bbMuw7vCq2a36tBy1rRFaNtRNjl8XjO3XP5RZG5Z9lUFA7Gvf+
pY8qUIWzBWXVi/KugpAwNvy7rgYoqKZyUFOrm/4ehCz7uGD5OmpucEVPvOQIDYPe
cqF27iLXYiTJv20ASVnpmoF5XJaztQa2O9VSupTgxNGXi+iUz+azrIeUviTbOgZP
H5flbfyBdQKBwQCV4WsNhv3g4pijnQIlFy/K9S8PsAO1gPhxknuwqquHeLz8qHWo
1zzAtQx7vBQXDp9pi+ZpBtjFRGJBI88q3hMq3z3jsewwccKLW6WdoIWYLjrj0GY9
46g6Ytekr1v112t2jfJukUD81Fc1UBYDs47GldXFUWHb3z0k1qppXX524yoNkM6g
/Heg9FeueXqO6r2xJFhjgDbfJ6MfOafSvcjfejy4hlUr9kvewe8HekdVfx/eG3OQ
GhFswlv5wUgR4+MCgcBaOJEAFoLd9fZU0vy55TdnniUToyXu3vQzYpJJ96CDLkcw
i3IpfU/B3P8CN2hCnQ2cqu1DShUCd7/Szx/YxK4YnToHTRboOR7PtjWydEe+FZUO
upjGoMDyFI+51m/+Q3dz4JVZkLd+ThG5faOmGqlT98/Kqnfn2LXMrOQ8bowYuKGs
nZ7wcP57Skv3BJs5lbrqK5LO4YvWdIETKGHRgyQtjbO9wKS2FimbLtiHn60bG9d8
i3G3eyNnqOqZKbkmgQECgcEAgX9k4kDqK7IoNdk5Keypxvk5xUi+8rM2A52aRjer
m1a32/0EmV2+gggtg5h9K4xUdoaRfvnggx5XqMNoshp4Qm5nKu4bJavdO+us2HVA
urstNyvWaoQQJm26LAoG6u57DqmX6j0RnOUjL9OBgGiNDwqaek+QbqHSc0mrSH36
Nfo9+XOssR7sZbNzKRGLlWGP1ham7QTjf6wkMFMYozBZZ96NgNbPW+gWd/kZlFCe
3YUVwrqlblfFYykcpa1p1llz
-----END PRIVATE KEY-----