mirror of
https://github.com/BotChain-Robots/firmware.git
synced 2026-07-08 17:47:21 +02:00
208 lines
5.3 KiB
C++
208 lines
5.3 KiB
C++
#include "MovementSetManager.h"
|
|
#include "esp_log.h"
|
|
#ifdef MOVEMENTS
|
|
|
|
MovementSetManager::MovementSetManager(){
|
|
esp_err_t res = nvs_open(MOVEMENTS_NVS_NAMESPACE, NVS_READWRITE, &handle);
|
|
|
|
if (res != ESP_OK){
|
|
ESP_LOGE(MOVEMENTS_DEBUG_TAG, "Failed to open nvs for %s", MOVEMENTS_NVS_NAMESPACE);
|
|
return;
|
|
}
|
|
|
|
ready = true;
|
|
};
|
|
|
|
MovementSetManager::~MovementSetManager(){
|
|
nvs_close(handle);
|
|
}
|
|
|
|
/**
|
|
* @brief Adds a movement entry into the movements map
|
|
*
|
|
* @param entry Movement entry information
|
|
* @param index Sequence number of the movements
|
|
* @return esp_err_t
|
|
*/
|
|
esp_err_t MovementSetManager::add_movement(MovementEntryData& entry, uint8_t index){
|
|
if (!ready){
|
|
return ESP_ERR_INVALID_STATE;
|
|
}
|
|
|
|
if (entry.board_id == PC_ADDR || entry.board_id == BROADCAST_ADDR){
|
|
return ESP_ERR_INVALID_ARG;
|
|
}
|
|
|
|
if (movements.find(index) != movements.end()){
|
|
for (MovementEntryData& e : movements[index]){
|
|
if (e.board_id == entry.board_id){
|
|
return ESP_ERR_INVALID_ARG; //only unique board ids per index
|
|
}
|
|
}
|
|
}
|
|
|
|
if (entry.post_delay_ms == 0){
|
|
//we don't want 0ms delay in between the movements, so we will add the default delay
|
|
entry.post_delay_ms = DEFAULT_DELAY_MS;
|
|
}
|
|
|
|
if (entry.ack != static_cast<uint8_t>(ACK_VALUES::NO_ACK) && entry.ack_ttl_ms == 0){
|
|
entry.ack_ttl_ms = DEFAULT_ACK_TTL_MS;
|
|
}
|
|
|
|
movements[index].push_back(entry);
|
|
|
|
return ESP_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Removes a movement entry from the sequence, given the board id
|
|
*
|
|
* @param index Sequence number
|
|
* @param board_id
|
|
* @return esp_err_t
|
|
*/
|
|
esp_err_t MovementSetManager::remove_movement(uint8_t index, uint8_t board_id){
|
|
if (board_id == PC_ADDR || board_id == BROADCAST_ADDR){
|
|
return ESP_ERR_INVALID_ARG;
|
|
}
|
|
|
|
if (movements.find(index) == movements.end()){
|
|
return ESP_ERR_INVALID_ARG;
|
|
}
|
|
|
|
if (!ready){
|
|
return ESP_ERR_INVALID_STATE;
|
|
}
|
|
|
|
bool found = false;
|
|
|
|
for (auto it = movements[index].begin(); it != movements[index].end(); ++it) {
|
|
if (it->board_id == board_id){
|
|
movements[index].erase(it);
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!found){
|
|
return ESP_ERR_NOT_FOUND;
|
|
}
|
|
|
|
return ESP_OK;
|
|
}
|
|
|
|
esp_err_t MovementSetManager::get_curr_movement_set(std::unordered_map<uint8_t, std::vector<MovementEntryData>>& set){
|
|
if (!ready){
|
|
return ESP_ERR_INVALID_STATE;
|
|
}
|
|
|
|
set = movements;
|
|
return ESP_OK;
|
|
}
|
|
|
|
esp_err_t MovementSetManager::get_nvs_movement_set(std::unordered_map<uint8_t, std::vector<MovementEntryData>>& set){
|
|
if (!ready){
|
|
return ESP_ERR_INVALID_STATE;
|
|
}
|
|
|
|
size_t size = 0;
|
|
esp_err_t res = nvs_get_u32(handle, MOVEMENTS_NVS_SET_SIZE_KEY, reinterpret_cast<uint32_t*>(&size));
|
|
|
|
if (res != ESP_OK) {
|
|
ESP_LOGE(MOVEMENTS_DEBUG_TAG, "Failed to read data size");
|
|
return res;
|
|
}
|
|
|
|
std::vector<uint8_t> buffer(size);
|
|
|
|
res = nvs_get_blob(handle, MOVEMENTS_NVS_SET_KEY, buffer.data(), &size);
|
|
|
|
if (res != ESP_OK) {
|
|
ESP_LOGE(MOVEMENTS_DEBUG_TAG, "Failed to read blob");
|
|
return res;
|
|
}
|
|
|
|
// Verify the FlatBuffer
|
|
flatbuffers::Verifier verifier(buffer.data(), buffer.size());
|
|
if (!Movement::VerifyMovementSetBuffer(verifier)) {
|
|
ESP_LOGE(MOVEMENTS_DEBUG_TAG, "FlatBuffer verification failed");
|
|
return ESP_ERR_INVALID_ARG;
|
|
}
|
|
|
|
// Parse root
|
|
const Movement::MovementSet* movement_set = Movement::GetMovementSet(buffer.data());
|
|
|
|
movements.clear();
|
|
|
|
const auto* map = movement_set->movement_map();
|
|
if (!map) {
|
|
return ESP_OK; // empty set
|
|
}
|
|
|
|
// Iterate map entries
|
|
for (const Movement::MovementVector* mv : *map) {
|
|
uint8_t key = mv->key();
|
|
|
|
auto& vec = movements[key];
|
|
vec.clear();
|
|
|
|
const auto* entries = mv->movements();
|
|
if (!entries) {
|
|
continue;
|
|
}
|
|
|
|
vec.reserve(entries->size());
|
|
|
|
// Must iterate over Movement::MovementEntry* (FlatBuffers table)
|
|
for (const Movement::MovementEntry* e : *entries) {
|
|
vec.push_back({
|
|
e->board_id(),
|
|
e->module_type(),
|
|
e->value_action(),
|
|
*e->condition(), // copy struct
|
|
e->ack(),
|
|
e->ack_ttl_ms(),
|
|
e->post_delay_ms()
|
|
});
|
|
}
|
|
}
|
|
|
|
set = movements;
|
|
|
|
return ESP_OK;
|
|
}
|
|
|
|
esp_err_t MovementSetManager::write_nvs_movement_set(){
|
|
if (!ready){
|
|
return ESP_ERR_INVALID_STATE;
|
|
}
|
|
|
|
Flatbuffers::SerializedMessage m = builder.build_movement_set(movements);
|
|
|
|
esp_err_t res = nvs_set_u32(handle, MOVEMENTS_NVS_SET_SIZE_KEY, static_cast<uint32_t>(m.size));
|
|
|
|
res = nvs_commit(handle);
|
|
|
|
if (res != ESP_OK) {
|
|
ESP_LOGE(MOVEMENTS_DEBUG_TAG, "Failed to commit data size");
|
|
return res;
|
|
}
|
|
|
|
res = nvs_set_blob(handle, MOVEMENTS_NVS_SET_KEY, m.data, m.size);
|
|
|
|
if (res != ESP_OK){
|
|
ESP_LOGE(MOVEMENTS_DEBUG_TAG, "Failed to write to nvs");
|
|
return res;
|
|
}
|
|
|
|
res = nvs_commit(handle);
|
|
if (res != ESP_OK) {
|
|
ESP_LOGE(MOVEMENTS_DEBUG_TAG, "Failed to commit topology");
|
|
return res;
|
|
}
|
|
|
|
return ESP_OK;
|
|
}
|
|
|
|
#endif //MOVEMENTS
|