Improve watchdog monitoring and CLI
This commit is contained in:
158
main/main.c
158
main/main.c
@@ -5,45 +5,80 @@
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_log.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#include "dcdc_controller.h"
|
||||
#include "ina226_monitor.h"
|
||||
#include "uart_mux.h"
|
||||
#include "usb_cdc_cli.h"
|
||||
#include "usb_cdc_log.h"
|
||||
#include "watch_config.h"
|
||||
#include "ws2812_status.h"
|
||||
|
||||
static const char *TAG = "watch-watch";
|
||||
static const char HB_MESSAGE[] = "{\"hb\":1}\r\n";
|
||||
static const char HB_MESSAGE[] = "{\"cmd\":\"status\"}\r\n";
|
||||
|
||||
static int noop_vprintf(const char *fmt, va_list args)
|
||||
{
|
||||
(void)fmt;
|
||||
(void)args;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
if (usb_cdc_log_init() != ESP_OK) {
|
||||
ESP_LOGW(TAG, "USB CDC лог недоступний");
|
||||
esp_log_set_vprintf(noop_vprintf);
|
||||
|
||||
if (watch_config_init() != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Не вдалося ініціалізувати конфігурацію");
|
||||
} else {
|
||||
ESP_LOGI(TAG, "USB CDC лог активовано");
|
||||
ESP_LOGI(TAG, "Конфігурацію завантажено");
|
||||
}
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(2000)); // Затримка для стабілізації живлення після перезавантаження
|
||||
|
||||
if (usb_cdc_cli_init() == ESP_OK) {
|
||||
ESP_LOGI(TAG, "USB CDC CLI активовано");
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Не вдалося запустити USB CLI");
|
||||
}
|
||||
|
||||
bool ws_ready = false;
|
||||
if (ws2812_status_init() == ESP_OK) {
|
||||
ws_ready = true;
|
||||
} else {
|
||||
ESP_LOGW(TAG, "WS2812 статусний індикатор недоступний");
|
||||
}
|
||||
|
||||
const watch_config_t *cfg = watch_config_get();
|
||||
const uint32_t start_delay_ms = cfg->heartbeat_start_delay_sec * 1000U;
|
||||
TickType_t start_delay = pdMS_TO_TICKS(start_delay_ms);
|
||||
if (start_delay > 0) {
|
||||
ESP_LOGI(TAG, "Очікування %u с перед стартом опитування", cfg->heartbeat_start_delay_sec);
|
||||
if (ws_ready) {
|
||||
ws2812_status_set_startup_hold(start_delay_ms);
|
||||
}
|
||||
vTaskDelay(start_delay);
|
||||
if (ws_ready) {
|
||||
ws2812_status_set_startup_hold(0);
|
||||
}
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Запуск watch-watch systems");
|
||||
if (dcdc_init() != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Помилка ініціалізації DCDC контролера");
|
||||
ws2812_status_init();
|
||||
ws2812_status_set_error(true);
|
||||
if (ws_ready) {
|
||||
ws2812_status_set_error(true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (ws2812_status_init() == ESP_OK) {
|
||||
if (ws_ready) {
|
||||
ws2812_status_refresh_from_dcdc();
|
||||
esp_err_t anim_err = ws2812_status_play_bringup_animation(1, 120);
|
||||
if (anim_err != ESP_OK) {
|
||||
ESP_LOGW(TAG, "Анімація WS2812 недоступна: %s", esp_err_to_name(anim_err));
|
||||
}
|
||||
} else {
|
||||
ESP_LOGW(TAG, "WS2812 статусний індикатор недоступний");
|
||||
}
|
||||
|
||||
if (ina226_monitor_init() == ESP_OK) {
|
||||
@@ -59,36 +94,97 @@ void app_main(void)
|
||||
ESP_LOGW(TAG, "UART мультиплексор недоступний");
|
||||
}
|
||||
|
||||
|
||||
|
||||
ESP_LOGI(TAG, "Початок послідовного ввімкнення каналів з інтервалом 4 с");
|
||||
const TickType_t on_time = pdMS_TO_TICKS(4000);
|
||||
const TickType_t mux_timeout = pdMS_TO_TICKS(600);
|
||||
TickType_t channel_next_hb[DCDC_CHANNEL_COUNT] = {0};
|
||||
bool channel_powered[DCDC_CHANNEL_COUNT] = {false};
|
||||
const TickType_t power_on_stagger = pdMS_TO_TICKS(3000);
|
||||
ESP_LOGI(TAG, "Початок циклічного опитування всіх каналів");
|
||||
|
||||
while (true) {
|
||||
for (size_t ch = 0; ch < dcdc_channel_count(); ++ch) {
|
||||
if (!dcdc_get_state(ch)) {
|
||||
cfg = watch_config_get();
|
||||
TickType_t hb_period = pdMS_TO_TICKS(cfg->heartbeat_period_sec * 1000U);
|
||||
if (hb_period == 0) {
|
||||
hb_period = 1;
|
||||
}
|
||||
TickType_t now = xTaskGetTickCount();
|
||||
size_t channels = dcdc_channel_count();
|
||||
for (size_t ch = 0; ch < channels; ++ch) {
|
||||
bool powered = dcdc_get_state(ch);
|
||||
if (!powered) {
|
||||
channel_powered[ch] = false;
|
||||
ESP_LOGI(TAG, "-> Ввімкнення каналу %d", (int)ch);
|
||||
dcdc_enable(ch);
|
||||
ws2812_status_set_channel_state(ch, true);
|
||||
if (dcdc_enable(ch) == ESP_OK) {
|
||||
powered = true;
|
||||
channel_powered[ch] = true;
|
||||
channel_next_hb[ch] = now + hb_period;
|
||||
if (ws_ready) {
|
||||
ws2812_status_set_channel_state(ch, true);
|
||||
}
|
||||
vTaskDelay(power_on_stagger);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Не вдалося ввімкнути канал %d", (int)ch);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!channel_powered[ch]) {
|
||||
channel_powered[ch] = true;
|
||||
channel_next_hb[ch] = now + hb_period;
|
||||
continue;
|
||||
}
|
||||
|
||||
now = xTaskGetTickCount();
|
||||
if (now < channel_next_hb[ch]) {
|
||||
continue;
|
||||
}
|
||||
ws2812_status_mark_active(ch);
|
||||
vTaskDelay(on_time);
|
||||
|
||||
ina226_reading_t reading = {0};
|
||||
if (ina226_monitor_sample(&reading) == ESP_OK) {
|
||||
if (ina226_monitor_ready() && ina226_monitor_sample(&reading) == ESP_OK) {
|
||||
ESP_LOGI(TAG, "Живлення: %.2f В, %.1f мА, %.1f мВт",
|
||||
reading.voltage_v, reading.current_ma, reading.power_mw);
|
||||
}
|
||||
|
||||
if (uart_mux_ready()) {
|
||||
if (uart_mux_write(ch,
|
||||
(const uint8_t *)HB_MESSAGE,
|
||||
sizeof(HB_MESSAGE) - 1,
|
||||
pdMS_TO_TICKS(100)) != ESP_OK) {
|
||||
ESP_LOGW(TAG, "Не вдалося надіслати heartbeat на канал %d", (int)ch);
|
||||
esp_err_t tx_err = uart_mux_write(ch,
|
||||
(const uint8_t *)HB_MESSAGE,
|
||||
sizeof(HB_MESSAGE) - 1,
|
||||
mux_timeout);
|
||||
if (tx_err != ESP_OK) {
|
||||
ESP_LOGW(TAG, "Не вдалося надіслати heartbeat на канал %d: %s",
|
||||
(int)ch, esp_err_to_name(tx_err));
|
||||
} else {
|
||||
uint8_t rx_buffer[CONFIG_WATCH_UART_MUX_DEFAULT_READ_LEN];
|
||||
size_t received = 0;
|
||||
esp_err_t rx_err = uart_mux_read(ch,
|
||||
rx_buffer,
|
||||
sizeof(rx_buffer),
|
||||
&received,
|
||||
mux_timeout);
|
||||
if (rx_err == ESP_OK) {
|
||||
if (received > 0) {
|
||||
ESP_LOGI(TAG, "RX CH%u (%u байт після heartbeat)", (unsigned)ch, (unsigned)received);
|
||||
ESP_LOG_BUFFER_HEX_LEVEL(TAG, rx_buffer, received, ESP_LOG_INFO);
|
||||
uart_mux_process_rx(ch, rx_buffer, received);
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Канал %d не відповів даними на heartbeat", (int)ch);
|
||||
uart_mux_report_miss(ch);
|
||||
}
|
||||
} else if (rx_err == ESP_ERR_TIMEOUT) {
|
||||
ESP_LOGW(TAG, "Час очікування відповіді з каналу %d перевищено", (int)ch);
|
||||
uart_mux_report_miss(ch);
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Помилка читання відповіді CH%u: %s",
|
||||
(unsigned)ch, esp_err_to_name(rx_err));
|
||||
uart_mux_report_miss(ch);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ESP_LOGW(TAG, "UART мультиплексор недоступний, очікування...");
|
||||
}
|
||||
|
||||
channel_next_hb[ch] = now + hb_period;
|
||||
}
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(50));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user