mirror of
https://github.com/ok-home/ota_ws_update.git
synced 2025-11-13 22:03:27 +03:00
first
This commit is contained in:
5
main/CMakeLists.txt
Normal file
5
main/CMakeLists.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
# Embed the server root certificate into the final binary
|
||||
idf_build_get_property(project_dir PROJECT_DIR)
|
||||
idf_component_register(SRCS "simple_ota_example.c"
|
||||
INCLUDE_DIRS "."
|
||||
EMBED_TXTFILES ${project_dir}/server_certs/ca_cert.pem)
|
||||
54
main/Kconfig.projbuild
Normal file
54
main/Kconfig.projbuild
Normal file
@@ -0,0 +1,54 @@
|
||||
menu "Example Configuration"
|
||||
|
||||
config EXAMPLE_FIRMWARE_UPGRADE_URL
|
||||
string "firmware upgrade url endpoint"
|
||||
default "https://192.168.0.3:8070/hello_world.bin"
|
||||
help
|
||||
URL of server which hosts the firmware
|
||||
image.
|
||||
|
||||
config EXAMPLE_USE_CERT_BUNDLE
|
||||
bool "Enable certificate bundle"
|
||||
default y
|
||||
depends on MBEDTLS_CERTIFICATE_BUNDLE
|
||||
help
|
||||
Enable trusted root certificate bundle. This approach allows to have
|
||||
OTA updates functional with any public server without requirement
|
||||
to explicitly add its server certificate.
|
||||
|
||||
config EXAMPLE_FIRMWARE_UPGRADE_URL_FROM_STDIN
|
||||
bool
|
||||
default y if EXAMPLE_FIRMWARE_UPGRADE_URL = "FROM_STDIN"
|
||||
|
||||
config EXAMPLE_SKIP_COMMON_NAME_CHECK
|
||||
bool "Skip server certificate CN fieldcheck"
|
||||
default n
|
||||
help
|
||||
This allows you to skip the validation of OTA server certificate CN field.
|
||||
|
||||
config EXAMPLE_FIRMWARE_UPGRADE_BIND_IF
|
||||
bool "Support firmware upgrade bind specified interface"
|
||||
default n
|
||||
help
|
||||
This allows you to bind specified interface in OTA example.
|
||||
|
||||
choice EXAMPLE_FIRMWARE_UPGRADE_BIND_IF_TYPE
|
||||
prompt "Choose OTA data bind interface"
|
||||
default EXAMPLE_FIRMWARE_UPGRADE_BIND_IF_STA
|
||||
depends on EXAMPLE_FIRMWARE_UPGRADE_BIND_IF
|
||||
help
|
||||
Select which interface type of OTA data go through.
|
||||
|
||||
config EXAMPLE_FIRMWARE_UPGRADE_BIND_IF_STA
|
||||
bool "Bind wifi station interface"
|
||||
depends on EXAMPLE_CONNECT_WIFI
|
||||
help
|
||||
Select wifi station interface to pass the OTA data.
|
||||
|
||||
config EXAMPLE_FIRMWARE_UPGRADE_BIND_IF_ETH
|
||||
bool "Bind ethernet interface"
|
||||
depends on EXAMPLE_CONNECT_ETHERNET
|
||||
help
|
||||
Select ethernet interface to pass the OTA data.
|
||||
endchoice
|
||||
endmenu
|
||||
201
main/simple_ota_example.c
Normal file
201
main/simple_ota_example.c
Normal file
@@ -0,0 +1,201 @@
|
||||
/* 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 "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_ota_ops.h"
|
||||
#include "esp_http_client.h"
|
||||
#include "esp_https_ota.h"
|
||||
#include "protocol_examples_common.h"
|
||||
#include "string.h"
|
||||
#ifdef CONFIG_EXAMPLE_USE_CERT_BUNDLE
|
||||
#include "esp_crt_bundle.h"
|
||||
#endif
|
||||
|
||||
#include "nvs.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "protocol_examples_common.h"
|
||||
#include <sys/socket.h>
|
||||
#if CONFIG_EXAMPLE_CONNECT_WIFI
|
||||
#include "esp_wifi.h"
|
||||
#endif
|
||||
|
||||
#define HASH_LEN 32
|
||||
|
||||
#ifdef CONFIG_EXAMPLE_FIRMWARE_UPGRADE_BIND_IF
|
||||
/* The interface name value can refer to if_desc in esp_netif_defaults.h */
|
||||
#if CONFIG_EXAMPLE_FIRMWARE_UPGRADE_BIND_IF_ETH
|
||||
static const char *bind_interface_name = EXAMPLE_NETIF_DESC_ETH;
|
||||
#elif CONFIG_EXAMPLE_FIRMWARE_UPGRADE_BIND_IF_STA
|
||||
static const char *bind_interface_name = EXAMPLE_NETIF_DESC_STA;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static const char *TAG = "simple_ota_example";
|
||||
extern const uint8_t server_cert_pem_start[] asm("_binary_ca_cert_pem_start");
|
||||
extern const uint8_t server_cert_pem_end[] asm("_binary_ca_cert_pem_end");
|
||||
|
||||
#define OTA_URL_SIZE 256
|
||||
|
||||
esp_err_t _http_event_handler(esp_http_client_event_t *evt)
|
||||
{
|
||||
switch (evt->event_id) {
|
||||
case HTTP_EVENT_ERROR:
|
||||
ESP_LOGD(TAG, "HTTP_EVENT_ERROR");
|
||||
break;
|
||||
case HTTP_EVENT_ON_CONNECTED:
|
||||
ESP_LOGD(TAG, "HTTP_EVENT_ON_CONNECTED");
|
||||
break;
|
||||
case HTTP_EVENT_HEADER_SENT:
|
||||
ESP_LOGD(TAG, "HTTP_EVENT_HEADER_SENT");
|
||||
break;
|
||||
case HTTP_EVENT_ON_HEADER:
|
||||
ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value);
|
||||
break;
|
||||
case HTTP_EVENT_ON_DATA:
|
||||
ESP_LOGD(TAG, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len);
|
||||
break;
|
||||
case HTTP_EVENT_ON_FINISH:
|
||||
ESP_LOGD(TAG, "HTTP_EVENT_ON_FINISH");
|
||||
break;
|
||||
case HTTP_EVENT_DISCONNECTED:
|
||||
ESP_LOGD(TAG, "HTTP_EVENT_DISCONNECTED");
|
||||
break;
|
||||
case HTTP_EVENT_REDIRECT:
|
||||
ESP_LOGD(TAG, "HTTP_EVENT_REDIRECT");
|
||||
break;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void simple_ota_example_task(void *pvParameter)
|
||||
{
|
||||
ESP_LOGI(TAG, "Starting OTA example task");
|
||||
#ifdef CONFIG_EXAMPLE_FIRMWARE_UPGRADE_BIND_IF
|
||||
esp_netif_t *netif = get_example_netif_from_desc(bind_interface_name);
|
||||
if (netif == NULL) {
|
||||
ESP_LOGE(TAG, "Can't find netif from interface description");
|
||||
abort();
|
||||
}
|
||||
struct ifreq ifr;
|
||||
esp_netif_get_netif_impl_name(netif, ifr.ifr_name);
|
||||
ESP_LOGI(TAG, "Bind interface name is %s", ifr.ifr_name);
|
||||
#endif
|
||||
esp_http_client_config_t config = {
|
||||
.url = CONFIG_EXAMPLE_FIRMWARE_UPGRADE_URL,
|
||||
#ifdef CONFIG_EXAMPLE_USE_CERT_BUNDLE
|
||||
.crt_bundle_attach = esp_crt_bundle_attach,
|
||||
#else
|
||||
.cert_pem = (char *)server_cert_pem_start,
|
||||
#endif /* CONFIG_EXAMPLE_USE_CERT_BUNDLE */
|
||||
.event_handler = _http_event_handler,
|
||||
.keep_alive_enable = true,
|
||||
#ifdef CONFIG_EXAMPLE_FIRMWARE_UPGRADE_BIND_IF
|
||||
.if_name = &ifr,
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef CONFIG_EXAMPLE_FIRMWARE_UPGRADE_URL_FROM_STDIN
|
||||
char url_buf[OTA_URL_SIZE];
|
||||
if (strcmp(config.url, "FROM_STDIN") == 0) {
|
||||
example_configure_stdin_stdout();
|
||||
fgets(url_buf, OTA_URL_SIZE, stdin);
|
||||
int len = strlen(url_buf);
|
||||
url_buf[len - 1] = '\0';
|
||||
config.url = url_buf;
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Configuration mismatch: wrong firmware upgrade image url");
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_EXAMPLE_SKIP_COMMON_NAME_CHECK
|
||||
config.skip_cert_common_name_check = true;
|
||||
#endif
|
||||
|
||||
esp_https_ota_config_t ota_config = {
|
||||
.http_config = &config,
|
||||
};
|
||||
ESP_LOGI(TAG, "Attempting to download update from %s", config.url);
|
||||
esp_err_t ret = esp_https_ota(&ota_config);
|
||||
if (ret == ESP_OK) {
|
||||
ESP_LOGI(TAG, "OTA Succeed, Rebooting...");
|
||||
esp_restart();
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Firmware upgrade failed");
|
||||
}
|
||||
while (1) {
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
|
||||
static void print_sha256(const uint8_t *image_hash, const char *label)
|
||||
{
|
||||
char hash_print[HASH_LEN * 2 + 1];
|
||||
hash_print[HASH_LEN * 2] = 0;
|
||||
for (int i = 0; i < HASH_LEN; ++i) {
|
||||
sprintf(&hash_print[i * 2], "%02x", image_hash[i]);
|
||||
}
|
||||
ESP_LOGI(TAG, "%s %s", label, hash_print);
|
||||
}
|
||||
|
||||
static void get_sha256_of_partitions(void)
|
||||
{
|
||||
uint8_t sha_256[HASH_LEN] = { 0 };
|
||||
esp_partition_t partition;
|
||||
|
||||
// get sha256 digest for bootloader
|
||||
partition.address = ESP_BOOTLOADER_OFFSET;
|
||||
partition.size = ESP_PARTITION_TABLE_OFFSET;
|
||||
partition.type = ESP_PARTITION_TYPE_APP;
|
||||
esp_partition_get_sha256(&partition, sha_256);
|
||||
print_sha256(sha_256, "SHA-256 for bootloader: ");
|
||||
|
||||
// get sha256 digest for running partition
|
||||
esp_partition_get_sha256(esp_ota_get_running_partition(), sha_256);
|
||||
print_sha256(sha_256, "SHA-256 for current firmware: ");
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "OTA example app_main start");
|
||||
// Initialize NVS.
|
||||
esp_err_t err = nvs_flash_init();
|
||||
if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
|
||||
// 1.OTA app partition table has a smaller NVS partition size than the non-OTA
|
||||
// partition table. This size mismatch may cause NVS initialization to fail.
|
||||
// 2.NVS partition contains data in new format and cannot be recognized by this version of code.
|
||||
// If this happens, we erase NVS partition and initialize NVS again.
|
||||
ESP_ERROR_CHECK(nvs_flash_erase());
|
||||
err = nvs_flash_init();
|
||||
}
|
||||
ESP_ERROR_CHECK(err);
|
||||
|
||||
get_sha256_of_partitions();
|
||||
|
||||
ESP_ERROR_CHECK(esp_netif_init());
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
|
||||
/* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig.
|
||||
* Read "Establishing Wi-Fi or Ethernet Connection" section in
|
||||
* examples/protocols/README.md for more information about this function.
|
||||
*/
|
||||
ESP_ERROR_CHECK(example_connect());
|
||||
|
||||
#if CONFIG_EXAMPLE_CONNECT_WIFI
|
||||
/* Ensure to disable any WiFi power save mode, this allows best throughput
|
||||
* and hence timings for overall OTA operation.
|
||||
*/
|
||||
esp_wifi_set_ps(WIFI_PS_NONE);
|
||||
#endif // CONFIG_EXAMPLE_CONNECT_WIFI
|
||||
|
||||
xTaskCreate(&simple_ota_example_task, "ota_example_task", 8192, NULL, 5, NULL);
|
||||
}
|
||||
Reference in New Issue
Block a user