This commit is contained in:
2026-04-24 16:37:04 +03:00
parent cb1014c950
commit 90037587c0
16 changed files with 224 additions and 3557 deletions

View File

@@ -14,8 +14,10 @@ idf_component_register(
"heartbeat_task.cpp"
"fw_command.cpp"
"json_utils.cpp"
"ota.cpp"
INCLUDE_DIRS "."
REQUIRES nvs_flash
REQUIRES
nvs_flash
esp_wifi
esp_netif
freertos
@@ -25,6 +27,8 @@ idf_component_register(
esp_websocket_client
driver
esp_driver_gpio
esp_http_client
app_update
)
# добавляем кастомный Kconfig
set(COMPONENT_KCONFIG "Kconfig")

View File

@@ -8,13 +8,16 @@ extern "C" {
#include <time.h>
}
static const char *TAG = "heartbeat";
static const char* TAG = "heartbeat";
static void heartbeat_task(void *arg)
static TaskHandle_t heartbeat_task_handle = nullptr;
static void heartbeat_task(void* arg)
{
while (1) {
if (protocol_is_connected()) {
while (1)
{
if (protocol_is_connected())
{
time_t now;
time(&now);
@@ -27,5 +30,17 @@ static void heartbeat_task(void *arg)
void heartbeat_task_start()
{
xTaskCreate(heartbeat_task, "heartbeat", 4096, NULL, 5, NULL);
}
if (heartbeat_task_handle == nullptr)
{
xTaskCreate(heartbeat_task, "heartbeat", 4096, nullptr, 5, &heartbeat_task_handle);
}
}
void heartbeat_task_stop()
{
if (heartbeat_task_handle != nullptr)
{
vTaskDelete(heartbeat_task_handle);
heartbeat_task_handle = nullptr;
}
}

View File

@@ -1,3 +1,4 @@
#pragma once
void heartbeat_task_start(void);
void heartbeat_task_start(void);
void heartbeat_task_stop();

116
esp32/main/ota.cpp Normal file
View File

@@ -0,0 +1,116 @@
#include "esp_http_client.h"
#include "esp_ota_ops.h"
#include "esp_system.h"
#include "esp_log.h"
#include "ota.h"
#include "sender_task.h"
#include "sampler_task.h"
#include "ws.h"
#include "heartbeat_task.h"
#include "fw_command.h"
static TaskHandle_t ota_task_handle = nullptr;
static char url_copy[256];
static char sha256[65];
void perform_ota(void* par)
{
esp_ota_handle_t ota_handle;
uint8_t buf[1024];
int read_bytes;
const esp_partition_t* partition = nullptr;
const char* url = static_cast<const char*>(par);
esp_http_client_config_t config = {};
config.url = url;
config.timeout_ms = 5000;
config.buffer_size = 1024;
esp_http_client_handle_t client = esp_http_client_init(&config);
if (esp_http_client_open(client, 0) != ESP_OK)
{
goto cleanup;
}
partition = esp_ota_get_next_update_partition(nullptr);
if (esp_ota_begin(partition, OTA_SIZE_UNKNOWN, &ota_handle) != ESP_OK)
{
goto cleanup;
}
while ((read_bytes = esp_http_client_read(client, (char*)buf, sizeof(buf))) > 0)
{
if (esp_ota_write(ota_handle, buf, read_bytes) != ESP_OK)
{
esp_ota_end(ota_handle);
goto cleanup;
}
}
if (esp_ota_end(ota_handle) == ESP_OK)
{
uint8_t hash[32];
if (esp_partition_get_sha256(partition, hash) != ESP_OK)
{
goto cleanup;
}
// переводим в hex
char hash_str[65];
for (int i = 0; i < 32; i++)
{
sprintf(&hash_str[i * 2], "%02x", hash[i]);
}
hash_str[64] = '\0';
// сравнение
if (strncmp(hash_str, sha256, 64) != 0)
{
printf("SHA256 mismatch!\n");
goto cleanup;
}
esp_ota_set_boot_partition(partition);
esp_restart();
}
cleanup:
esp_http_client_cleanup(client);
vTaskDelete(nullptr);
ota_task_handle = nullptr;
}
void ota_task_start(const fw_cmd_t* cmd)
{
strncpy(url_copy, cmd->url, sizeof(url_copy));
strncpy(sha256, cmd->sha256, sizeof(sha256));
sampler_task_stop();
sender_task_stop();
heartbeat_task_stop();
ws_disconnect();
if (ota_task_handle == nullptr)
{
xTaskCreate(
perform_ota,
"ota",
4096,
url_copy,
5,
&ota_task_handle
);
}
}
void ota_task_stop()
{
if (ota_task_handle != nullptr)
{
vTaskDelete(ota_task_handle);
ota_task_handle = nullptr;
}
}

4
esp32/main/ota.h Normal file
View File

@@ -0,0 +1,4 @@
#pragma once
#include "fw_command.h"
void ota_task_start(const fw_cmd_t* cmd);

View File

@@ -11,35 +11,52 @@ extern "C" {
// буфер
static ringbuf_t rb;
ringbuf_t* sampler_get_buffer() {
ringbuf_t* sampler_get_buffer()
{
return &rb;
}
static void sampler_task(void *arg) {
static TaskHandle_t sampler_task_handle = nullptr;
static void sampler_task(void* arg)
{
const TickType_t period = pdMS_TO_TICKS(6000);
TickType_t last_wake = xTaskGetTickCount();
while (1) {
while (1)
{
int64_t now_ms = esp_timer_get_time() / 1000;
float temp = ds18b20_read();
ringbuf_push(&rb, now_ms, (int)(temp * 100));
vTaskDelayUntil(&last_wake, period);// 6 секунд
vTaskDelayUntil(&last_wake, period); // 6 секунд
}
}
void sampler_task_start() {
ringbuf_init(&rb);
ds18b20_init(GPIO_NUM_27); // новый драйвер
void sampler_task_start()
{
if (sampler_task_handle == nullptr)
{
ringbuf_init(&rb);
ds18b20_init(GPIO_NUM_27); // новый драйвер
xTaskCreate(
sampler_task,
"sampler",
4096,
NULL,
5,
NULL
);
}
xTaskCreate(
sampler_task,
"sampler",
4096,
nullptr,
5,
&sampler_task_handle
);
}
}
void sampler_task_stop()
{
if (sampler_task_handle != nullptr)
{
vTaskDelete(sampler_task_handle);
sampler_task_handle = nullptr;
}
}

View File

@@ -3,4 +3,5 @@
#include "ringbuf.h"
void sampler_task_start();
ringbuf_t* sampler_get_buffer(); // ← ВОТ ЭТО
ringbuf_t* sampler_get_buffer();
void sampler_task_stop();

View File

@@ -18,11 +18,13 @@ extern "C" {
static uint32_t last_send_ms = 0;
static int64_t last_send_ts = 0;
static TaskHandle_t sender_task_handle = nullptr;
static void sender_task(void* arg)
{
ringbuf_t* rb = sampler_get_buffer();
last_send_ts = time(NULL);
last_send_ts = time(nullptr);
last_send_ms = esp_timer_get_time() / 1000;
while (1)
@@ -31,7 +33,7 @@ static void sender_task(void* arg)
char buf[512];
uint32_t now_ms = esp_timer_get_time() / 1000;
time_t now_ts = time(NULL);
time_t now_ts = time(nullptr);
sample_t tmp[RINGBUF_SIZE];
ringbuf_copy(rb, tmp);
@@ -49,6 +51,7 @@ static void sender_task(void* arg)
out_values[count * 2 + 0] = delta;
out_values[count * 2 + 1] = tmp[i].value;
count++;
if (count >= RINGBUF_SIZE) break;
}
}
@@ -87,12 +90,24 @@ static void sender_task(void* arg)
void sender_task_start()
{
xTaskCreate(
sender_task,
"sender",
4096,
NULL,
5,
NULL
);
if (sender_task_handle == nullptr)
{
xTaskCreate(
sender_task,
"sender",
4096,
nullptr,
5,
&sender_task_handle
);
}
}
void sender_task_stop()
{
if (sender_task_handle != nullptr)
{
vTaskDelete(sender_task_handle);
sender_task_handle = nullptr;
}
}

View File

@@ -1,4 +1,5 @@
#pragma once
// Запуск задачи отправки (1 Гц)
void sender_task_start();
void sender_task_start();
void sender_task_stop();

View File

@@ -51,9 +51,9 @@ void init_wifi(const char* ssid, const char* pass) {
esp_event_handler_instance_t instance_got_ip;
esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID,
&wifi_event_handler, NULL, &instance_any_id);
&wifi_event_handler, nullptr, &instance_any_id);
esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP,
&wifi_event_handler, NULL, &instance_got_ip);
&wifi_event_handler, nullptr, &instance_got_ip);
wifi_config_t wifi_config = {};

View File

@@ -4,6 +4,7 @@
#include <string.h>
#include "sdkconfig.h"
#include "fw_command.h"
#include "ota.h"
static const char* TAG = "WS";
@@ -57,6 +58,8 @@ static void ws_event_handler(void* handler_args,
ESP_LOGI(TAG, "URL: %s", cmd.url);
ESP_LOGI(TAG, "SHA256: %s", cmd.sha256);
ota_task_start(&cmd);
// пока просто лог, без OTA
}
@@ -73,7 +76,7 @@ void ws_init(const char* uri)
config.network_timeout_ms = 5000;
client = esp_websocket_client_init(&config);
esp_websocket_register_events(client, WEBSOCKET_EVENT_ANY, ws_event_handler, NULL);
esp_websocket_register_events(client, WEBSOCKET_EVENT_ANY, ws_event_handler, nullptr);
}
void ws_start()
@@ -108,3 +111,8 @@ void ws_go()
ws_init(uri);
ws_start();
}
void ws_disconnect()
{
esp_websocket_client_stop(client);
}

View File

@@ -9,6 +9,7 @@ void ws_go();
void ws_start();
bool ws_is_connected();
void ws_send(const char* data);
void ws_disconnect();
#ifdef __cplusplus
}