#pragma once #include "XNFramework.h" #include "XNDDSManager.h" #include "XNByteArray.h" #include "XNTypeTraits.h" #include // 定义UDP包的最大大小 constexpr size_t MAX_UDP_PACKET_SIZE = 40000; class XNDDSInterface { public: XNDDSInterface() = default; virtual ~XNDDSInterface() = default; public: /** * @brief 初始化 * @param framework: 框架 */ virtual void Initialize(XNFrameworkPtr framework, uint32_t modelID) = 0; /** * @brief 获取该接口的UDP包 * @return 字节数组 */ XNByteArray getUDPPackage(); /** * @brief 批量获取指定变量的数据 * @param varNames: 变量名列表 * @return: 变量名到数据的映射 */ std::unordered_map getStringData(std::vector varNames); /** * @brief 批量设置指定变量的数据 * @param data: 变量名到数据的映射 */ void setDataByString(std::unordered_map data); protected: /** * @brief 获取指定变量的字节数据,用于网络通信 * @param data: 数据 * @return 字节数组 */ template XNByteArray getByteArray(eprosima::fastcdr::optional data) { XNByteArray result(getTypeSize()); if constexpr (std::is_arithmetic_v) { if (data) { std::memcpy(result.data(), &data.value(), sizeof(T)); } else { T zero = 0; std::memcpy(result.data(), &zero, sizeof(T)); } } else if constexpr (is_std_array_v) { if (data) { return getByteArrayFromStdArray(data.value()); } else { T zero = {}; return getByteArrayFromStdArray(zero); } } else { static_assert(std::is_arithmetic_v || is_std_array_v, "Type must be arithmetic or std::array"); } return result; } /** * @brief 设置指定变量的字节数据,用于网络通信 * @param data: 数据 * @param byteArray: 字节数组 */ template void setByteArray(eprosima::fastcdr::optional &data, const XNByteArray &byteArray) { if (byteArray.size() < getTypeSize()) return; if constexpr (std::is_arithmetic_v) { T temp; std::memcpy(&temp, byteArray.data(), sizeof(T)); data = temp; } else if constexpr (is_std_array_v) { if (!data) { data = T{}; } setByteArrayFromStdArray(data.value(), byteArray); } else { static_assert(std::is_arithmetic_v || is_std_array_v, "Type must be arithmetic or std::array"); } } /** * @brief 获取指定数组变量的字节数据,用于网络通信 * @param data: 数据 * @return 字节数组 */ template XNByteArray getByteArrayFromStdArray(const std::array &data) { XNByteArray result(getTypeSize() * N); for (std::size_t i = 0; i < N; ++i) { if constexpr (std::is_arithmetic_v) { std::memcpy(result.data() + i * getTypeSize(), &data[i], getTypeSize()); } else { XNByteArray subArray = getByteArrayFromStdArray(data[i]); std::memcpy(result.data() + i * getTypeSize(), subArray.data(), getTypeSize()); } } return result; } /** * @brief 设置指定数组变量的字节数据,用于网络通信 * @param data: 数据 * @param byteArray: 字节数组 */ template void setByteArrayFromStdArray(std::array &data, const XNByteArray &byteArray) { if (byteArray.size() < getTypeSize() * N) return; for (std::size_t i = 0; i < N; ++i) { if constexpr (std::is_arithmetic_v) { std::memcpy(&data[i], byteArray.data() + i * getTypeSize(), getTypeSize()); } else { XNByteArray subArray(byteArray.data() + i * getTypeSize(), getTypeSize()); setByteArrayFromStdArray(data[i], subArray); } } } /** * @brief 获取指定变量的字符串数据,用于JSON前端 * @param data: 数据 * @return: 数据(字符串格式) */ template std::string getString(eprosima::fastcdr::optional data) { if constexpr (std::is_arithmetic_v) { if (data) { return std::to_string(data.value()); } else { return std::to_string(0); } } else if constexpr (is_std_array_v) { if (data) { return getStringFromStdArray(data.value()); } else { T zero = {}; return getStringFromStdArray(zero); } } return std::string(); } /** * @brief 通过字符串数据设置指定变量,用于JSON前端 * @param data: 数据 * @param value: 字符串数据 */ template void setDataFromString(eprosima::fastcdr::optional &data, const std::string &value) { if constexpr (std::is_arithmetic_v) { if constexpr (std::is_same_v || std::is_same_v) { data = std::stod(value); } else { data = std::stoll(value); } } else if constexpr (is_std_array_v) { // 解析输入字符串 std::stringstream ss(value); std::string item; std::vector items; while (std::getline(ss, item, ',')) { items.push_back(item); } T temp; setStdArrayFromString(temp, items, 0); data = temp; } } /** * @brief 获取指定数组变量的字符串数据,用于JSON前端 * @param data: 数据 * @return: 数据(字符串格式) */ template std::string getStringFromStdArray(std::array data) { std::stringstream ss; for (std::size_t i = 0; i < N; ++i) { if (i > 0) ss << ","; if constexpr (std::is_arithmetic_v) { ss << data[i]; } else { ss << getStringFromStdArray(data[i]); } } return ss.str(); } /** * @brief 通过字符串数据设置指定数组变量,用于JSON前端 * @param data: 数据 * @param value: 字符串数据,格式为"数字,数字,..." * @param start_pos: 当前数组在输入字符串中的起始位置 * @return 处理完当前数组后,下一个数组的起始位置 * @throw std::runtime_error: 当输入数据格式不正确时抛出异常 */ template size_t setStdArrayFromString(std::array &data, const std::vector &value, size_t start_pos = 0) { // 递归处理每个元素 for (std::size_t i = 0; i < N; ++i) { try { if constexpr (std::is_arithmetic_v) { // 对于基本类型,直接转换 if constexpr (std::is_same_v || std::is_same_v) { data[i] = static_cast(std::stod(value[start_pos + i])); } else { data[i] = static_cast(std::stoll(value[start_pos + i])); } } else if constexpr (is_std_array_v) { // 对于嵌套数组,递归处理 start_pos = setStdArrayFromString(data[i], value, start_pos + i); } else { static_assert(std::is_arithmetic_v || is_std_array_v, "Type must be arithmetic or std::array"); } } catch (const std::exception &e) { throw std::runtime_error("Error parsing element " + std::to_string(i) + ": " + e.what()); } } return start_pos + N; } template void assign_value_get(eprosima::fastcdr::optional &data, T2 &model_data) { if (data) { auto temp = data.value(); if constexpr (std::is_arithmetic_v) { model_data = temp; } else if constexpr (is_std_array_v) { size_t arraySize = array_size_v; for (size_t i = 0; i < arraySize; ++i) { auto temp2 = temp[i]; if constexpr (std::is_arithmetic_v) { model_data[i] = temp2; } else if constexpr (is_std_array_v) { size_t arraySize2 = array_size_v; for (size_t j = 0; j < arraySize2; ++j) { model_data[i][j] = temp2[j]; } } } } } } virtual void clearOutData() {} virtual void sendOutData() {} protected: struct ByteArrayFunc { std::function func; size_t size; }; std::unordered_map> getDataFunction; std::unordered_map> setDataFunction; std::vector getByteArrayFunction; std::unordered_map> setByteArrayFunction; std::mutex mutex; uint8_t header[5]{}; // 固定大小的头部 size_t headerSize = 5; FAST_DDS_MACRO::DataWriter *dataWriter; }; #define MAP_DATA_FUNC(NAME) \ getDataFunction[#NAME] = [this]() { return getString(data.NAME()); }; \ setDataFunction[#NAME] = [this](std::string value) { \ setDataFromString(out_data.NAME(), value); \ }; \ getByteArrayFunction.push_back( \ {[this]() { return getByteArray(data.NAME()); }, getTypeSize()}); \ setByteArrayFunction[#NAME] = [this](XNByteArray byteArray) { \ setByteArray(data.NAME(), byteArray); \ } #define ASSIGN_VALUE_GET(NAME) \ if (data.NAME()) { \ auto temp = data.NAME().value(); \ if constexpr (std::is_arithmetic_v) { \ model_data->NAME = temp; \ } else if constexpr (is_std_array_v) { \ size_t arraySize = array_size_v; \ for (size_t i = 0; i < arraySize; ++i) { \ if constexpr (std::is_arithmetic_v) { \ model_data->NAME[i] = temp[i]; \ } else if constexpr (is_std_array_v) { \ size_t arraySize2 = array_size_v; \ for (size_t j = 0; j < arraySize2; ++j) { \ model_data->NAME[i][j] = temp[i][j]; \ } \ } \ } \ } \ } #define ASSIGN_VALUE_SET(NAME) \ if constexpr (std::is_arithmetic_v) { \ out_data.NAME(model_data->NAME); \ } else if constexpr (is_std_array_v) { \ using thisType = typename decltype(out_data.NAME())::type; \ thisType temp; \ size_t arraySize1 = array_size_v; \ using subType = thisType::value_type; \ if constexpr (std::is_arithmetic_v) { \ for (size_t i = 0; i < arraySize1; ++i) { \ temp[i] = model_data->NAME[i]; \ } \ } else if constexpr (is_std_array_v) { \ size_t arraySize2 = array_size_v; \ std::array temp; \ for (size_t i = 0; i < arraySize1; ++i) { \ for (size_t j = 0; j < arraySize2; ++j) { \ temp[i][j] = model_data->NAME[i][j]; \ } \ } \ } \ out_data.NAME(temp); \ }