diff --git a/components/flatbuffers/TopologyBuilder.cpp b/components/flatbuffers/TopologyBuilder.cpp index d87daba..8ea5319 100644 --- a/components/flatbuffers/TopologyBuilder.cpp +++ b/components/flatbuffers/TopologyBuilder.cpp @@ -1,23 +1,48 @@ #include "TopologyBuilder.h" #ifdef TOPOLOGYBUILDER namespace Flatbuffers{ - SerializedMessage TopologyBuilder::build_topology(const std::vector>& topology){ + SerializedMessage TopologyBuilder::build_topology(const std::unordered_map>& topology_map) { builder_.Clear(); - - auto neighbours_vec = builder_.CreateVector(topology); - auto topology_offset = Topology::CreateTopologyInfo(builder_, static_cast(topology.size()), neighbours_vec); + + std::vector> neighbours; + neighbours.reserve(topology_map.size()); + + for (const auto& [board_id, connections] : topology_map) { + auto conn_vec = builder_.CreateVectorOfStructs(connections); + auto blob = Topology::CreateNeighbourBlob( + builder_, + board_id, + static_cast(connections.size()), + conn_vec + ); + + neighbours.push_back(blob); + } + + auto neighbours_vec = builder_.CreateVector(neighbours); + auto topology_offset = Topology::CreateTopologyInfo( + builder_, + static_cast(neighbours.size()), + neighbours_vec + ); builder_.Finish(topology_offset); - return { - builder_.GetBufferPointer(), - builder_.GetSize() - }; + return { builder_.GetBufferPointer(), builder_.GetSize() }; } - flatbuffers::Offset TopologyBuilder::build_neighbour_info(uint16_t board_id, const std::vector& connections){ - auto conn = builder_.CreateVectorOfStructs(connections); - return Topology::CreateNeighbourBlob(builder_, board_id, static_cast(connections.size()), conn); + flatbuffers::Offset TopologyBuilder::build_neighbour_info( + uint16_t board_id, + const std::vector& connections + ) { + auto conn_vec = builder_.CreateVectorOfStructs(connections); + + return Topology::CreateNeighbourBlob( + builder_, + board_id, + static_cast(connections.size()), + conn_vec + ); } Topology::ChannelBoardConn TopologyBuilder::build_connections(uint8_t channel, uint16_t board_id){ diff --git a/components/flatbuffers/include/TopologyBuilder.h b/components/flatbuffers/include/TopologyBuilder.h index 14c98e6..f996818 100644 --- a/components/flatbuffers/include/TopologyBuilder.h +++ b/components/flatbuffers/include/TopologyBuilder.h @@ -14,11 +14,11 @@ namespace Flatbuffers { public: TopologyBuilder() : builder_(RIP_MAX_ROUTES*(sizeof(Topology::NeighbourBlob) + sizeof(Topology::ChannelBoardConn)*MAX_CHANNELS)) {} - SerializedMessage build_topology(const std::vector>& topology); - flatbuffers::Offset build_neighbour_info(uint16_t board_id, const std::vector& connections); + SerializedMessage build_topology(const std::unordered_map>& topology_map); Topology::ChannelBoardConn build_connections(uint8_t channel, uint16_t board_id); - + private: + flatbuffers::Offset build_neighbour_info(uint16_t board_id, const std::vector& connections); flatbuffers::FlatBufferBuilder builder_; }; } diff --git a/components/movements/TopologyManager.cpp b/components/movements/TopologyManager.cpp index 7199263..3031258 100644 --- a/components/movements/TopologyManager.cpp +++ b/components/movements/TopologyManager.cpp @@ -204,18 +204,90 @@ esp_err_t TopologyManager::get_curr_topology(std::unordered_map(m.size)); + + res = nvs_commit(handle); + if (res != ESP_OK) { + ESP_LOGE(TOPOLOGY_DEBUG_TAG, "Failed to commit data size"); + return res; + } + + res = nvs_set_blob(handle, MOVEMENTS_NVS_TOPOLOGY_KEY, m.data, m.size); + + if (res != ESP_OK){ + ESP_LOGE(TOPOLOGY_DEBUG_TAG, "Failed to write to nvs"); + return res; + } + + res = nvs_commit(handle); + if (res != ESP_OK) { + ESP_LOGE(TOPOLOGY_DEBUG_TAG, "Failed to commit topology"); + return res; + } + + return ESP_OK; +} + +esp_err_t TopologyManager::get_nvs_topology(std::unordered_map>>& topology){ + if (!ready) { + return ESP_ERR_INVALID_STATE; + } + + size_t size = 0; + esp_err_t res = nvs_get_u32(handle,MOVEMENTS_NVS_TOPOLOGY_DATA_SIZE_KEY, reinterpret_cast(&size)); + + if (res != ESP_OK) { + ESP_LOGE(TOPOLOGY_DEBUG_TAG, "Failed to read data size"); + return res; + } + + std::vector buffer(size); + + res = nvs_get_blob(handle, MOVEMENTS_NVS_TOPOLOGY_KEY, buffer.data(), &size); + + if (res != ESP_OK) { + ESP_LOGE(TOPOLOGY_DEBUG_TAG, "Failed to read blob"); + return res; + } + + // Verify the FlatBuffer + flatbuffers::Verifier verifier(buffer.data(), buffer.size()); + if (!Topology::VerifyTopologyInfoBuffer(verifier)) { + ESP_LOGE(TOPOLOGY_DEBUG_TAG, "FlatBuffer verification failed"); + return ESP_ERR_INVALID_ARG; + } + + // Parse root + const Topology::TopologyInfo* topo = Topology::GetTopologyInfo(buffer.data()); + + topology.clear(); + + // Replace neighbours() with your actual accessor name + auto neighbours = topo->boards(); + + for (const auto* nb : *neighbours) { + uint16_t board_id = nb->curr_board_id(); + + std::vector> connections; + connections.reserve(nb->neighbour_connections()->size()); + + for (const auto* conn : *nb->neighbour_connections()) { + connections.emplace_back(conn->channel(), conn->board_id()); + } + + topology.emplace(board_id, std::move(connections)); + } + + return ESP_OK; +} #endif //MOVEMENTS \ No newline at end of file diff --git a/components/movements/include/MovementManager.h b/components/movements/include/MovementManager.h index f7ed809..dbc071c 100644 --- a/components/movements/include/MovementManager.h +++ b/components/movements/include/MovementManager.h @@ -6,6 +6,7 @@ #define MOVEMENTS_NVS_NAMESPACE "movements" #define MOVEMENTS_NVS_KEY "key" #define MOVEMENTS_NVS_TOPOLOGY_KEY "topology" +#define MOVEMENTS_NVS_TOPOLOGY_DATA_SIZE_KEY "data_size" #define MOVEMENTS_DEBUG_TAG "movements" class MovementManager { diff --git a/components/movements/include/TopologyManager.h b/components/movements/include/TopologyManager.h index a87c1bb..94ebf6d 100644 --- a/components/movements/include/TopologyManager.h +++ b/components/movements/include/TopologyManager.h @@ -5,9 +5,9 @@ #include #include -// move these to constants header file? -#include "RMTManager.h" -#include "DataLinkManager.h" +#include "constants/rmt.h" +#include "constants/datalink.h" + #include "Frames.h" #include "TopologyBuilder.h" #include @@ -26,7 +26,7 @@ class TopologyManager { esp_err_t verify_topology(); esp_err_t get_curr_topology(std::unordered_map>>& topology); esp_err_t write_nvs_topology(); - esp_err_t get_nvs_topology(std::unordered_map>& topology); + esp_err_t get_nvs_topology(std::unordered_map>>& topology); private: std::unordered_map> topology; diff --git a/main/README.md b/main/README.md index 215a013..0e1298e 100644 --- a/main/README.md +++ b/main/README.md @@ -42,6 +42,10 @@ To run the sample code, add the compiler variable `PP_MOVE=1` when compiling. You can use the `SRC_BOARD` compiler variable to set a custom board id. +The sample topology used to test: + +![Sample Topology Used for Testing](images/sample_topology.png) + # cat ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⣿⣿⡷⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ diff --git a/main/images/sample_topology.png b/main/images/sample_topology.png new file mode 100644 index 0000000..54504a6 Binary files /dev/null and b/main/images/sample_topology.png differ diff --git a/main/main_preprogrammed_test.cpp b/main/main_preprogrammed_test.cpp index 2b36d7c..0d73426 100644 --- a/main/main_preprogrammed_test.cpp +++ b/main/main_preprogrammed_test.cpp @@ -44,7 +44,6 @@ extern "C" [[noreturn]] void app_main(void) { } ESP_ERROR_CHECK(ret); - esp_netif_init(); esp_event_loop_create_default(); printf("finished esp init\n"); @@ -140,10 +139,59 @@ extern "C" [[noreturn]] void app_main(void) { if (res != ESP_OK){ ESP_LOGE(MOVEMENT_DEBUG_TAG, "Topology verification incorrectly failed"); + restart(); } else { ESP_LOGI(MOVEMENT_DEBUG_TAG, "Topology verification passed"); } + res = obj.write_nvs_topology(); + + if (res == ESP_OK){ + ESP_LOGI(MOVEMENT_DEBUG_TAG, "Topology NVS write success"); + } else { + ESP_LOGE(MOVEMENT_DEBUG_TAG, "Topology NVS write failed"); + restart(); + } + + std::unordered_map>> nvs_topology; + + res = obj.get_nvs_topology(nvs_topology); + if (res == ESP_OK){ + ESP_LOGI(MOVEMENT_DEBUG_TAG, "Topology NVS read success"); + } else { + ESP_LOGE(MOVEMENT_DEBUG_TAG, "Topology NVS read failed"); + restart(); + } + + if (nvs_topology.size() != test_connections.size()){ + ESP_LOGE(MOVEMENT_DEBUG_TAG, "Topology NVS size is different"); + restart(); + } + + for (const auto& connections : test_connections){ + const auto& test = connections.first; + + if (nvs_topology.find(connections.second) == nvs_topology.end()){ + ESP_LOGE(MOVEMENT_DEBUG_TAG, "Failed to find board %d in topology", connections.second); + restart(); + } + + if (test.size() != nvs_topology[connections.second].size()){ + ESP_LOGE(MOVEMENT_DEBUG_TAG, "Board %d connections are different in topology", connections.second); + restart(); + } + } + + ESP_LOGI(MOVEMENT_DEBUG_TAG, "Topology NVS R/W success! Got back the same topology"); + + ESP_LOGI(MOVEMENT_DEBUG_TAG, "Topology NVS got:"); + + for (const auto& [key, connections] : nvs_topology){ + for (const auto& c : connections){ + ESP_LOGI(MOVEMENT_DEBUG_TAG, "Board %d -> board %d on channel %d", key, c.second, c.first); + } + } + //test removing a board from topology uint16_t board_id_to_remove = 2;