OTA + remote logging + profiling

This commit is contained in:
2026-02-18 11:12:38 -05:00
parent 63a18677cb
commit 107f185527
16 changed files with 524 additions and 12 deletions

View File

@@ -18,6 +18,10 @@ public:
LoopManager() : m_config_manager(ConfigManager::get_instance()),
m_messaging_interface(std::make_unique<MessagingInterface>()),
m_actuator(ActuatorFactory::create_actuator(m_config_manager.get_module_type())) {
xTaskCreate(reinterpret_cast<TaskFunction_t>(LoopManager::metadata_tx_loop),
"metadata_tx", 3096, this, 3, nullptr);
xTaskCreate(reinterpret_cast<TaskFunction_t>(LoopManager::sensor_loop),
"sensor_tx", 3096, this, 3, nullptr);
// todo: temporary demo register_function call.
const auto function_tag = 100;
@@ -29,6 +33,7 @@ public:
});
}
MessagingInterface &get_messaging_interface();
[[noreturn]] void control_loop() const; // gets control commands
[[noreturn]] static void sensor_loop(char * args); // sends sensor data commands continually
[[noreturn]] static void metadata_tx_loop(char * args); // sends metadata continually (low duty cycle)

View File

@@ -0,0 +1,26 @@
#ifndef REMOTEDEBUGGING_H
#define REMOTEDEBUGGING_H
#include <memory>
#include "MessagingInterface.h"
#include "control/ActuatorFactory.h"
#include "control/IActuator.h"
#include "util/ring_buffer.h"
#define LOG_BUFFER_SIZE 50
static auto log_buffer = std::make_unique<RingBuffer<std::string>>(LOG_BUFFER_SIZE);
class RemoteDebugging {
public:
static std::string get_task_manager();
static std::string get_logs();
static int custom_log_write(const char *data, va_list args);
static void register_calls(MessagingInterface &messaging_interface);
private:
};
#endif // REMOTEDEBUGGING_H

View File

@@ -0,0 +1,26 @@
#ifndef REMOTEMANAGEMENT_H
#define REMOTEMANAGEMENT_H
#include <memory>
#include "esp_ota_ops.h"
#include "MessagingInterface.h"
static esp_ota_handle_t ota_handle;
static const esp_partition_t* update_partition = esp_ota_get_next_update_partition(NULL);
static uint16_t packet_number = 0; // represents last written packet
class RemoteManagement {
public:
static void mark_ota_success();
static bool start_ota();
static bool write_ota(const uint8_t* ota_data, size_t size);
static bool ota_end();
static void restart();
static void register_calls(MessagingInterface &messaging_interface);
private:
};
#endif // REMOTEMANAGEMENT_H

View File

@@ -0,0 +1,149 @@
#include <vector>
#include <mutex>
#include <optional>
template <typename T>
class RingBuffer {
public:
explicit RingBuffer(size_t capacity)
: m_buffer(capacity), m_capacity(capacity) {
}
void push(const T& item) {
std::lock_guard<std::mutex> lock(m_mutex);
m_buffer[m_head] = item;
if (m_full) {
m_tail = (m_tail + 1) % m_capacity;
}
m_head = (m_head + 1) % m_capacity;
m_full = m_head == m_tail;
}
void push(T&& item) {
std::lock_guard<std::mutex> lock(m_mutex);
m_buffer[m_head] = std::move(item);
if (m_full) {
m_tail = (m_tail + 1) % m_capacity;
}
m_head = (m_head + 1) % m_capacity;
m_full = m_head == m_tail;
}
std::optional<T> pop() {
std::lock_guard<std::mutex> lock(m_mutex);
if (empty_locked()) {
return std::nullopt;
}
T value = std::move(m_buffer[m_tail]);
m_full = false;
m_tail = (m_tail + 1) % m_capacity;
return value;
}
std::optional<T> peek() const {
std::lock_guard<std::mutex> lock(m_mutex);
if (empty_locked()) {
return std::nullopt;
}
return m_buffer[m_tail];
}
std::vector<T> drain() {
std::lock_guard<std::mutex> lock(m_mutex);
std::vector<T> out;
size_t count = size_locked();
out.reserve(count);
if (count == 0) {
return out;
}
size_t idx = m_tail;
for (size_t i = 0; i < count; ++i) {
out.push_back(std::move(m_buffer[idx]));
idx = (idx + 1) % m_capacity;
}
m_head = 0;
m_tail = 0;
m_full = false;
return out;
}
std::vector<T> peek_drain() {
std::lock_guard<std::mutex> lock(m_mutex);
std::vector<T> out;
size_t count = size_locked();
out.reserve(count);
if (count == 0) {
return out;
}
size_t idx = m_tail;
for (size_t i = 0; i < count; ++i) {
out.push_back(m_buffer[idx]);
idx = (idx + 1) % m_capacity;
}
return out;
}
void clear() {
std::lock_guard<std::mutex> lock(m_mutex);
m_head = m_tail;
m_full = false;
}
bool empty() const {
std::lock_guard<std::mutex> lock(m_mutex);
return empty_locked();
}
bool full() const {
std::lock_guard<std::mutex> lock(m_mutex);
return m_full;
}
size_t size() const {
std::lock_guard<std::mutex> lock(m_mutex);
return size_locked();
}
size_t capacity() const {
return m_capacity;
}
private:
bool empty_locked() const {
return (!m_full && (m_head == m_tail));
}
size_t size_locked() const {
if (m_full) return m_capacity;
if (m_head >= m_tail) return m_head - m_tail;
return m_capacity + m_head - m_tail;
}
private:
std::vector<T> m_buffer;
const size_t m_capacity;
size_t m_head = 0;
size_t m_tail = 0;
bool m_full = false;
// mutable allows const functions to modify/lock the mutex
mutable std::mutex m_mutex;
};