V0.21.18.250613_alpha:数据监控的CSV文件注入功能完备
This commit is contained in:
parent
5b9bb35775
commit
e1b4139d04
Binary file not shown.
@ -273,7 +273,7 @@ protected:
|
||||
}
|
||||
} else if constexpr (is_std_array_v<T>) {
|
||||
// 对于嵌套数组,递归处理
|
||||
start_pos = setStdArrayFromString(data[i], value, start_pos + i);
|
||||
start_pos = setStdArrayFromString(data[i], value, start_pos);
|
||||
} else {
|
||||
static_assert(
|
||||
std::is_arithmetic_v<T> || is_std_array_v<T>,
|
||||
|
@ -273,7 +273,7 @@ protected:
|
||||
}
|
||||
} else if constexpr (is_std_array_v<T>) {
|
||||
// 对于嵌套数组,递归处理
|
||||
start_pos = setStdArrayFromString(data[i], value, start_pos + i);
|
||||
start_pos = setStdArrayFromString(data[i], value, start_pos);
|
||||
} else {
|
||||
static_assert(
|
||||
std::is_arithmetic_v<T> || is_std_array_v<T>,
|
||||
|
@ -11,49 +11,96 @@ CSVDataInjectThread::~CSVDataInjectThread()
|
||||
stop();
|
||||
}
|
||||
|
||||
bool CSVDataInjectThread::Initialize(std::vector<std::string> structNames)
|
||||
bool CSVDataInjectThread::Initialize(std::vector<InjectDataInfo> injectDataInfos)
|
||||
{
|
||||
m_csvFile.open(m_csvFilePath);
|
||||
if (!m_csvFile.is_open()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_injectDataInfos = injectDataInfos;
|
||||
|
||||
std::string headerLine;
|
||||
if (!std::getline(m_csvFile, headerLine)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<std::string> interfaceNames;
|
||||
// 修改CSV头解析逻辑
|
||||
std::stringstream ss(headerLine);
|
||||
std::string field;
|
||||
std::getline(ss, field, ',');
|
||||
std::getline(ss, field, ','); // 跳过第一列时间戳
|
||||
|
||||
// 使用getline读取所有字段,包括最后一个
|
||||
while (std::getline(ss, field, ',')) {
|
||||
interfaceNames.push_back(field);
|
||||
// 去除字段前后的空白字符
|
||||
field.erase(0, field.find_first_not_of(" \t\r\n"));
|
||||
field.erase(field.find_last_not_of(" \t\r\n") + 1);
|
||||
|
||||
if (!field.empty()) {
|
||||
parseHeaderField(field);
|
||||
}
|
||||
}
|
||||
|
||||
// 将结构体和接口名称一一对应
|
||||
if (structNames.size() != interfaceNames.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < structNames.size(); i++) {
|
||||
m_structInterfaceMap[structNames[i]].push_back(interfaceNames[i]);
|
||||
}
|
||||
|
||||
for (const auto &[structName, interfaceNames] : m_structInterfaceMap) {
|
||||
auto dataMonitor = DataMonitorFactory::GetInstance(structName);
|
||||
for (const auto &injectDataInfo : m_injectDataInfos) {
|
||||
auto dataMonitor = DataMonitorFactory::GetInstance(injectDataInfo.structName);
|
||||
if (dataMonitor == nullptr) {
|
||||
return false;
|
||||
}
|
||||
if (dataMonitor->isInitialized()) {
|
||||
m_alreadyStartedMonitors[structName] = dataMonitor;
|
||||
m_alreadyStartedMonitors[injectDataInfo.structName] = dataMonitor;
|
||||
} else {
|
||||
m_notStartedMonitors[structName] = dataMonitor;
|
||||
m_notStartedMonitors[injectDataInfo.structName] = dataMonitor;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void CSVDataInjectThread::parseHeaderField(const std::string &headerField)
|
||||
{
|
||||
CSVHeaderField csvHeaderField;
|
||||
csvHeaderField.fieldName = headerField.substr(0, headerField.find('['));
|
||||
csvHeaderField.arrayDim = 0;
|
||||
csvHeaderField.arrayIndex1 = 0;
|
||||
csvHeaderField.arrayIndex2 = 0;
|
||||
|
||||
if (headerField.find('[') != std::string::npos) {
|
||||
// 处理一维数组
|
||||
size_t firstBracketPos = headerField.find('[');
|
||||
size_t firstBracketEndPos = headerField.find(']');
|
||||
csvHeaderField.arrayIndex1 = std::stoi(
|
||||
headerField.substr(firstBracketPos + 1, firstBracketEndPos - firstBracketPos - 1));
|
||||
csvHeaderField.arrayDim = 1;
|
||||
|
||||
// 检查是否有第二个方括号,判断是否为二维数组
|
||||
if (headerField.find('[', firstBracketEndPos) != std::string::npos) {
|
||||
size_t secondBracketPos = headerField.find('[', firstBracketEndPos);
|
||||
size_t secondBracketEndPos = headerField.find(']', secondBracketPos);
|
||||
csvHeaderField.arrayIndex2 = std::stoi(headerField.substr(
|
||||
secondBracketPos + 1, secondBracketEndPos - secondBracketPos - 1));
|
||||
csvHeaderField.arrayDim = 2;
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &injectDataInfo : m_injectDataInfos) {
|
||||
for (int i = 0; i < injectDataInfo.interfaceNames.size(); i++) {
|
||||
if (injectDataInfo.interfaceNames[i] == csvHeaderField.fieldName) {
|
||||
csvHeaderField.structName = injectDataInfo.structName;
|
||||
if (injectDataInfo.arraySizes[i].second > 1) {
|
||||
csvHeaderField.arraySize1 = injectDataInfo.arraySizes[i].first;
|
||||
} else {
|
||||
csvHeaderField.arraySize1 = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (csvHeaderField.structName.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_headerFields.push_back(csvHeaderField);
|
||||
}
|
||||
|
||||
void CSVDataInjectThread::start()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
@ -107,14 +154,62 @@ void CSVDataInjectThread::updateData()
|
||||
double timeStamp = std::stod(field);
|
||||
m_nextExecuteTime = static_cast<int64_t>(timeStamp * 1000); // 转换为毫秒
|
||||
|
||||
// 解析每个结构体的数据
|
||||
for (const auto &[structName, interfaceNames] : m_structInterfaceMap) {
|
||||
std::unordered_map<std::string, std::string> dataMap;
|
||||
for (const auto &interfaceName : interfaceNames) {
|
||||
std::getline(ss, field, ',');
|
||||
dataMap[interfaceName] = field;
|
||||
// 为每个结构体初始化数据
|
||||
std::unordered_map<std::string, std::unordered_map<std::string, std::vector<std::string>>>
|
||||
tempDataMap;
|
||||
for (const auto &injectDataInfo : m_injectDataInfos) {
|
||||
std::unordered_map<std::string, std::vector<std::string>> dataMap;
|
||||
for (int i = 0; i < injectDataInfo.interfaceNames.size(); i++) {
|
||||
if (injectDataInfo.arraySizes[i].first > 1) {
|
||||
for (int j = 0; j < injectDataInfo.arraySizes[i].first; j++) {
|
||||
if (injectDataInfo.arraySizes[i].second > 1) {
|
||||
for (int k = 0; k < injectDataInfo.arraySizes[i].second; k++) {
|
||||
dataMap[injectDataInfo.interfaceNames[i]].push_back("0");
|
||||
}
|
||||
} else {
|
||||
dataMap[injectDataInfo.interfaceNames[i]].push_back("0");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
dataMap[injectDataInfo.interfaceNames[i]].push_back("0");
|
||||
}
|
||||
}
|
||||
m_data[structName] = dataMap;
|
||||
tempDataMap[injectDataInfo.structName] = dataMap;
|
||||
}
|
||||
|
||||
// 读取下一行数据
|
||||
for (int i = 0; i < m_headerFields.size(); i++) {
|
||||
std::getline(ss, field, ',');
|
||||
if (m_headerFields[i].arrayDim == 0) {
|
||||
tempDataMap[m_headerFields[i].structName][m_headerFields[i].fieldName][0] = field;
|
||||
} else if (m_headerFields[i].arrayDim == 1) {
|
||||
tempDataMap[m_headerFields[i].structName][m_headerFields[i].fieldName]
|
||||
[m_headerFields[i].arrayIndex1] = field;
|
||||
} else if (m_headerFields[i].arrayDim == 2) {
|
||||
tempDataMap[m_headerFields[i].structName][m_headerFields[i].fieldName]
|
||||
[m_headerFields[i].arrayIndex1 * m_headerFields[i].arraySize1
|
||||
+ m_headerFields[i].arrayIndex2] = field;
|
||||
}
|
||||
}
|
||||
|
||||
// 将tempDataMap转换为m_data格式
|
||||
for (const auto &[structName, dataMap] : tempDataMap) {
|
||||
std::unordered_map<std::string, std::string> structData;
|
||||
for (const auto &[interfaceName, values] : dataMap) {
|
||||
if (values.empty()) {
|
||||
structData[interfaceName] = "0";
|
||||
} else {
|
||||
std::stringstream ss;
|
||||
for (size_t i = 0; i < values.size(); ++i) {
|
||||
ss << values[i];
|
||||
if (i < values.size() - 1) {
|
||||
ss << ",";
|
||||
}
|
||||
}
|
||||
structData[interfaceName] = ss.str();
|
||||
}
|
||||
}
|
||||
m_data[structName] = structData;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ public:
|
||||
*/
|
||||
~CSVDataInjectThread();
|
||||
|
||||
bool Initialize(std::vector<std::string> structNames);
|
||||
bool Initialize(std::vector<InjectDataInfo> injectDataInfos);
|
||||
|
||||
/**
|
||||
* @brief 启动数据注入线程
|
||||
@ -50,10 +50,13 @@ private:
|
||||
*/
|
||||
void threadFunc();
|
||||
|
||||
void parseHeaderField(const std::string &headerField);
|
||||
|
||||
private:
|
||||
std::string m_csvFilePath;
|
||||
std::ifstream m_csvFile;
|
||||
std::unordered_map<std::string, std::vector<std::string>> m_structInterfaceMap;
|
||||
std::vector<InjectDataInfo> m_injectDataInfos;
|
||||
std::vector<CSVHeaderField> m_headerFields;
|
||||
std::thread m_thread; ///< 数据注入线程
|
||||
std::atomic<bool> m_running; ///< 线程运行标志
|
||||
std::mutex m_mutex; ///< 互斥锁
|
||||
@ -65,6 +68,4 @@ private:
|
||||
std::unordered_map<std::string, std::unordered_map<std::string, std::string>>
|
||||
m_data; ///< 要注入的数据
|
||||
std::atomic<int64_t> m_nextExecuteTime; ///< 下一次执行的时间点
|
||||
};
|
||||
|
||||
using CSVDataInjectThreadPtr = std::shared_ptr<CSVDataInjectThread>;
|
||||
};
|
@ -209,3 +209,51 @@ struct ModelDefinition {
|
||||
*/
|
||||
std::vector<std::shared_ptr<NamespaceDefinition>> namespaceDefinitions;
|
||||
};
|
||||
|
||||
struct InjectDataInfo {
|
||||
/**
|
||||
* @brief 结构体名称
|
||||
*/
|
||||
std::string structName;
|
||||
/**
|
||||
* @brief 接口名称
|
||||
*/
|
||||
std::vector<std::string> interfaceNames;
|
||||
|
||||
/**
|
||||
* @brief 数组大小
|
||||
*/
|
||||
std::vector<std::pair<int, int>> arraySizes;
|
||||
};
|
||||
|
||||
struct CSVHeaderField {
|
||||
/**
|
||||
* @brief 字段名
|
||||
*/
|
||||
std::string fieldName;
|
||||
|
||||
/**
|
||||
* @brief 结构体名称
|
||||
*/
|
||||
std::string structName;
|
||||
|
||||
/**
|
||||
* @brief 数组维度
|
||||
*/
|
||||
int arrayDim;
|
||||
|
||||
/**
|
||||
* @brief 数组索引1
|
||||
*/
|
||||
int arrayIndex1;
|
||||
|
||||
/**
|
||||
* @brief 数组索引2
|
||||
*/
|
||||
int arrayIndex2;
|
||||
|
||||
/**
|
||||
* @brief 一维数组大小
|
||||
*/
|
||||
int arraySize1;
|
||||
};
|
@ -20,7 +20,7 @@ bool g_modelInfoMonitorStarted = false;
|
||||
SystemControl *systemControl = nullptr;
|
||||
bool g_systemControlStarted = false;
|
||||
|
||||
CSVDataInjectThreadPtr g_csvDataInjectThread;
|
||||
CSVDataInjectThread *g_csvDataInjectThread = nullptr;
|
||||
|
||||
// 初始化函数实现
|
||||
int XN_Initialize(const char *domainId, int domainIdLen, char *errorMsg, int errorMsgSize)
|
||||
@ -584,26 +584,40 @@ int XN_StopInjectContinuous(const char *structName, const int structNameLen, cha
|
||||
}
|
||||
|
||||
// 从csv文件中注入数据接口
|
||||
int XNMONITORSERVER_EXPORT XN_InjectDataInterfaceFromCsv(const char *structName,
|
||||
const int structNameLen,
|
||||
int XNMONITORSERVER_EXPORT XN_InjectDataInterfaceFromCsv(const char *injectDataInfo,
|
||||
const int injectDataInfoLen,
|
||||
const char *csvFilePath,
|
||||
const int csvFilePathLen, char *infoMsg,
|
||||
int infoMsgSize)
|
||||
{
|
||||
std::vector<std::string> structNames;
|
||||
std::string structNameStr(structName, structNameLen);
|
||||
try {
|
||||
nlohmann::json structNamesJson = nlohmann::json::parse(structNameStr);
|
||||
if (!structNamesJson.is_array()) {
|
||||
if (infoMsg && infoMsgSize > 0) {
|
||||
strncpy(infoMsg, "Invalid struct name format - expected JSON array",
|
||||
infoMsgSize - 1);
|
||||
infoMsg[infoMsgSize - 1] = '\0';
|
||||
}
|
||||
return -1;
|
||||
if (!g_initialized) {
|
||||
if (infoMsg && infoMsgSize > 0) {
|
||||
strncpy(infoMsg, "DDSMonitor Not Initialized", infoMsgSize - 1);
|
||||
infoMsg[infoMsgSize - 1] = '\0';
|
||||
}
|
||||
for (const auto &structNameJson : structNamesJson) {
|
||||
structNames.push_back(structNameJson.get<std::string>());
|
||||
return -1;
|
||||
}
|
||||
if (g_csvDataInjectThread != nullptr) {
|
||||
g_csvDataInjectThread->stop();
|
||||
delete g_csvDataInjectThread;
|
||||
g_csvDataInjectThread = nullptr;
|
||||
}
|
||||
std::vector<InjectDataInfo> injectDataInfos;
|
||||
std::string injectDataInfoStr(injectDataInfo, injectDataInfoLen);
|
||||
try {
|
||||
nlohmann::json injectDataInfoJson = nlohmann::json::parse(injectDataInfoStr);
|
||||
for (const auto &[structName, interfaceInfo] : injectDataInfoJson.items()) {
|
||||
InjectDataInfo info;
|
||||
info.structName = structName;
|
||||
for (const auto &[interfaceName, size] : interfaceInfo.items()) {
|
||||
info.interfaceNames.push_back(interfaceName);
|
||||
if (size.is_array()) {
|
||||
info.arraySizes.push_back({size[0].get<int>(), size[1].get<int>()});
|
||||
} else {
|
||||
info.arraySizes.push_back({0, 0});
|
||||
}
|
||||
}
|
||||
injectDataInfos.push_back(info);
|
||||
}
|
||||
} catch (const nlohmann::json::parse_error &e) {
|
||||
if (infoMsg && infoMsgSize > 0) {
|
||||
@ -628,31 +642,42 @@ int XNMONITORSERVER_EXPORT XN_InjectDataInterfaceFromCsv(const char *structName,
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
if (g_csvDataInjectThread == nullptr) {
|
||||
g_csvDataInjectThread = std::make_shared<CSVDataInjectThread>(csvFilePathStr);
|
||||
bool ret = g_csvDataInjectThread->Initialize(structNames);
|
||||
if (ret) {
|
||||
g_csvDataInjectThread->start();
|
||||
} else {
|
||||
try {
|
||||
g_csvDataInjectThread = new CSVDataInjectThread(csvFilePathStr);
|
||||
if (!g_csvDataInjectThread->Initialize(injectDataInfos)) {
|
||||
delete g_csvDataInjectThread;
|
||||
g_csvDataInjectThread = nullptr;
|
||||
if (infoMsg && infoMsgSize > 0) {
|
||||
strncpy(infoMsg, "CSV 注入线程初始化失败", infoMsgSize - 1);
|
||||
infoMsg[infoMsgSize - 1] = '\0';
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
g_csvDataInjectThread->start();
|
||||
} catch (const std::exception &e) {
|
||||
if (g_csvDataInjectThread) {
|
||||
delete g_csvDataInjectThread;
|
||||
g_csvDataInjectThread = nullptr;
|
||||
}
|
||||
if (infoMsg && infoMsgSize > 0) {
|
||||
strncpy(infoMsg, "CSV 注入线程已在运行", infoMsgSize - 1);
|
||||
strncpy(infoMsg, e.what(), infoMsgSize - 1);
|
||||
infoMsg[infoMsgSize - 1] = '\0';
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
std::cout << "CSV注入线程已启动" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int XN_GetCsvDataInjectStatus(char *infoMsg, int infoMsgSize)
|
||||
{
|
||||
if (!g_initialized) {
|
||||
if (infoMsg && infoMsgSize > 0) {
|
||||
strncpy(infoMsg, "DDSMonitor Not Initialized", infoMsgSize - 1);
|
||||
infoMsg[infoMsgSize - 1] = '\0';
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (g_csvDataInjectThread == nullptr) {
|
||||
if (infoMsg && infoMsgSize > 0) {
|
||||
strncpy(infoMsg, "CSV 注入线程已不存在", infoMsgSize - 1);
|
||||
@ -660,14 +685,20 @@ int XN_GetCsvDataInjectStatus(char *infoMsg, int infoMsgSize)
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
if (g_csvDataInjectThread->isRunning()) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
return g_csvDataInjectThread->isRunning() ? 1 : 0;
|
||||
}
|
||||
|
||||
int XN_StopCsvDataInject(char *infoMsg, int infoMsgSize)
|
||||
{
|
||||
if (!g_initialized) {
|
||||
if (infoMsg && infoMsgSize > 0) {
|
||||
strncpy(infoMsg, "DDSMonitor Not Initialized", infoMsgSize - 1);
|
||||
infoMsg[infoMsgSize - 1] = '\0';
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (g_csvDataInjectThread == nullptr) {
|
||||
if (infoMsg && infoMsgSize > 0) {
|
||||
strncpy(infoMsg, "CSV 注入线程已不存在", infoMsgSize - 1);
|
||||
@ -676,9 +707,18 @@ int XN_StopCsvDataInject(char *infoMsg, int infoMsgSize)
|
||||
return -1;
|
||||
}
|
||||
|
||||
g_csvDataInjectThread->stop();
|
||||
g_csvDataInjectThread.reset(); // 释放智能指针
|
||||
std::cout << "CSV注入线程已停止" << std::endl;
|
||||
try {
|
||||
g_csvDataInjectThread->stop();
|
||||
delete g_csvDataInjectThread;
|
||||
g_csvDataInjectThread = nullptr;
|
||||
} catch (const std::exception &e) {
|
||||
if (infoMsg && infoMsgSize > 0) {
|
||||
strncpy(infoMsg, e.what(), infoMsgSize - 1);
|
||||
infoMsg[infoMsgSize - 1] = '\0';
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -214,8 +214,8 @@ extern "C"
|
||||
* @param infoMsgSize 错误信息大小
|
||||
* @return 0: 成功, -1: 失败
|
||||
*/
|
||||
int XNMONITORSERVER_EXPORT XN_InjectDataInterfaceFromCsv(const char *structName,
|
||||
const int structNameLen,
|
||||
int XNMONITORSERVER_EXPORT XN_InjectDataInterfaceFromCsv(const char *InjectDataInfo,
|
||||
const int InjectDataInfoLen,
|
||||
const char *csvFilePath,
|
||||
const int csvFilePathLen,
|
||||
char *infoMsg, int infoMsgSize);
|
||||
|
@ -21,6 +21,7 @@ class DataMonitor extends HTMLElement {
|
||||
isInjecting: false,
|
||||
fileName: '',
|
||||
structNames: [],
|
||||
structData: {}, // 用于存储结构体数据
|
||||
filePath: '' // 添加文件路径
|
||||
};
|
||||
this.monitorStatus = 0; // 监控状态:0-未监控,1-监控中,2-错误
|
||||
@ -419,7 +420,6 @@ class DataMonitor extends HTMLElement {
|
||||
throw new Error(`获取CSV注入状态失败: ${csvStatusResponse.status} ${csvStatusResponse.statusText}`);
|
||||
}
|
||||
const csvStatusData = await csvStatusResponse.json();
|
||||
console.log('CSV注入状态:', csvStatusData.data);
|
||||
// 如果状态为0,触发停止注入
|
||||
if (csvStatusData.data === 0) {
|
||||
// 模拟点击停止CSV注入按钮
|
||||
@ -1916,7 +1916,7 @@ class DataMonitor extends HTMLElement {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
structName: JSON.stringify(this.csvState.structNames),
|
||||
structName: JSON.stringify(this.csvState.structData),
|
||||
csvFilePath: this.csvState.filePath
|
||||
})
|
||||
});
|
||||
@ -2127,7 +2127,7 @@ class DataMonitor extends HTMLElement {
|
||||
// 检查每个头部是否在接口表中
|
||||
const missingInterfaces = [];
|
||||
const invalidInterfaces = [];
|
||||
const structNames = []; // 用于按顺序收集结构体名称
|
||||
const structData = {}; // 用于存储结构体数据
|
||||
|
||||
// 检查第一个接口(时间)是否在接口表中
|
||||
const firstHeader = validateResult.headers[0];
|
||||
@ -2141,14 +2141,49 @@ class DataMonitor extends HTMLElement {
|
||||
// 检查其他接口是否在接口表中
|
||||
for (let i = 1; i < validateResult.headers.length; i++) {
|
||||
const header = validateResult.headers[i];
|
||||
// 提取接口名称和数组索引
|
||||
const match = header.match(/^(.+?)(?:\[(\d+)\](?:\[(\d+)\])?)?$/);
|
||||
if (!match) continue;
|
||||
|
||||
const baseInterfaceName = match[1];
|
||||
const index1 = match[2] ? parseInt(match[2]) : null;
|
||||
const index2 = match[3] ? parseInt(match[3]) : null;
|
||||
|
||||
const interfaceInfo = this.interfaces.find(interfaceItem =>
|
||||
interfaceItem.InterfaceName === header
|
||||
interfaceItem.InterfaceName === baseInterfaceName
|
||||
);
|
||||
|
||||
if (!interfaceInfo) {
|
||||
missingInterfaces.push(header);
|
||||
} else {
|
||||
// 按顺序收集结构体名称
|
||||
structNames.push(interfaceInfo.ModelStructName);
|
||||
// 构造结构体数据
|
||||
if (!structData[interfaceInfo.ModelStructName]) {
|
||||
structData[interfaceInfo.ModelStructName] = {};
|
||||
}
|
||||
|
||||
if (!structData[interfaceInfo.ModelStructName][baseInterfaceName]) {
|
||||
const size1 = interfaceInfo.InterfaceArraySize_1 || 0;
|
||||
const size2 = interfaceInfo.InterfaceArraySize_2 || 0;
|
||||
|
||||
structData[interfaceInfo.ModelStructName][baseInterfaceName] = [size1, size2];
|
||||
}
|
||||
|
||||
// 检查数组索引是否越界
|
||||
if (index1 !== null) {
|
||||
if (index2 !== null) {
|
||||
// 二维数组
|
||||
if (index1 >= interfaceInfo.InterfaceArraySize_1 || index2 >= interfaceInfo.InterfaceArraySize_2) {
|
||||
console.warn(`接口 ${baseInterfaceName} 的数组索引 [${index1}][${index2}] 超出范围`);
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
// 一维数组
|
||||
if (index1 >= interfaceInfo.InterfaceArraySize_1) {
|
||||
console.warn(`接口 ${baseInterfaceName} 的数组索引 [${index1}] 超出范围`);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2183,7 +2218,7 @@ class DataMonitor extends HTMLElement {
|
||||
|
||||
// 更新CSV状态
|
||||
this.csvState.fileName = result.file.name;
|
||||
this.csvState.structNames = structNames;
|
||||
this.csvState.structData = structData; // 保存结构体数据
|
||||
this.csvState.filePath = result.file.path;
|
||||
}
|
||||
|
||||
|
@ -326,7 +326,7 @@ router.post('/stop-all-continuous', async (req, res) => {
|
||||
/**
|
||||
* @brief 从CSV文件注入数据
|
||||
* @route POST /api/data-monitor/inject-csv
|
||||
* @param {string} structName - 结构体名称
|
||||
* @param {string} structName - 结构体数据JSON字符串,格式为 {structName1: {interfaceName1: [size1, size2], ...}, structName2: ...}
|
||||
* @param {string} csvFilePath - CSV文件路径
|
||||
* @returns {Object} 返回注入结果
|
||||
*/
|
||||
@ -340,6 +340,43 @@ router.post('/inject-csv', async (req, res) => {
|
||||
});
|
||||
}
|
||||
|
||||
// 解析并验证 structName JSON 字符串
|
||||
let structData;
|
||||
try {
|
||||
structData = JSON.parse(structName);
|
||||
// 验证数据结构
|
||||
if (typeof structData !== 'object' || structData === null) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: '结构体数据格式错误:必须是有效的对象'
|
||||
});
|
||||
}
|
||||
// 验证每个结构体的接口数据
|
||||
for (const [structName, interfaces] of Object.entries(structData)) {
|
||||
if (typeof interfaces !== 'object' || interfaces === null) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: `结构体 ${structName} 的接口数据格式错误:必须是有效的对象`
|
||||
});
|
||||
}
|
||||
for (const [interfaceName, sizes] of Object.entries(interfaces)) {
|
||||
if (!Array.isArray(sizes) || sizes.length !== 2 ||
|
||||
typeof sizes[0] !== 'number' || typeof sizes[1] !== 'number' ||
|
||||
sizes[0] < 0 || sizes[1] < 0) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: `接口 ${interfaceName} 的数据格式错误:必须是包含两个非负数字的数组 [size1, size2]`
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: `结构体数据解析失败: ${error.message}`
|
||||
});
|
||||
}
|
||||
|
||||
const result = systemMonitor.injectDataInterfaceFromCsv(structName, csvFilePath);
|
||||
if (result.includes('失败')) {
|
||||
return res.status(500).json({ success: false, message: result });
|
||||
|
Loading…
x
Reference in New Issue
Block a user