From 4b85bfbfde322027d1e407e8d70f238d8267384b Mon Sep 17 00:00:00 2001 From: wlxuz Date: Fri, 13 Jun 2025 10:08:39 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E8=B0=83=E8=AF=95=E5=8D=8F=E8=AE=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: wlxuz Change-Id: Id93b6ba2c5ed28c9ed856805df79aec65cdbd246 --- CMakeLists.txt | 9 ++- test/CMakeLists.txt | 7 +- test/test_xcom_parser.xcom | 42 ++++++++++-- .../{xcom_parser.cpp => xcom_parser_test.cpp} | 27 +++++--- test/xcom_process.cpp | 39 ----------- test/xcom_process_test.cpp | 62 +++++++++++++++++ xcom_handler.cpp | 14 ++-- xcom_node.cpp | 24 ++++--- xcom_node.h | 11 ++- xcom_process.cpp | 67 +++++++++++++------ xcom_process.h | 18 +++-- 11 files changed, 209 insertions(+), 111 deletions(-) rename test/{xcom_parser.cpp => xcom_parser_test.cpp} (76%) delete mode 100644 test/xcom_process.cpp create mode 100644 test/xcom_process_test.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 62058cc..3896eee 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,7 +28,10 @@ if (USE_LUA_PROTOCOL) endif(USE_LUA_PROTOCOL) if (USE_XCOM_PROTOCOL) - target_include_directories(${MODULE} PUBLIC libxcom/include) - target_link_libraries(${MODULE} dbms utils libxcom) + target_include_directories(${MODULE} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/libxcom/include) + target_link_libraries(${MODULE} dbms utils xcom) endif(USE_XCOM_PROTOCOL) -add_subdirectory(test) \ No newline at end of file + +if (PROJECT_ENABLE_TEST) + add_subdirectory(test) +endif() \ No newline at end of file diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index d6ddb5b..53c4084 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -12,4 +12,9 @@ function(add_google_test test_target) endfunction() # add_google_test(lua_config) -add_google_test(xcom_parser) +add_google_test(xcom_parser_test) +add_google_test(xcom_process_test) + +install(FILES test_xcom_parser.xcom + DESTINATION $/testfiles/ + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ) diff --git a/test/test_xcom_parser.xcom b/test/test_xcom_parser.xcom index 9f3c57f..52b9cfd 100644 --- a/test/test_xcom_parser.xcom +++ b/test/test_xcom_parser.xcom @@ -4,13 +4,13 @@ protocol:{ ```xcom #型号 modbus(crc16) - def crc16: $crc($1,0x8005,0xffff,0x0000,0) + def crc_modbus: $crc16($1,0x8005,0xffff,0x0000,1,1) # 以上可以定义公共函数 - def modbus_read_req:[$addr $fcode $itom(2,$reg) $itom(2,$reglen) $crc16($group(0,$pos))] - def modbus_read_resp:[$addr $fcode $ditch(1,$assign(&dl,$0)) $data($ditch($dl)) $ditch(2,$chk($0,$crc16($group(0,$pos))))] - def modbus_write_req:[$addr $fcode $itom(2,$reg) $itom(2,$reglen) $len($1) $1 $crc16($group(0,$pos))] - def modbus_write_resp:[$addr $fcode $ditch(1,$assign(&dl,$0)) $data($ditch($dl)) $ditch(2,$chk($0,$crc16($group(0,$pos))))] + def modbus_read_req:[$addr $fcode $itom(2,$reg) $itom(2,$reglen) $crc_modbus($group(0,$pos))] + def modbus_read_resp:[$addr $fcode $ditch(1,{dl=$int($0)}) $ditch($dl, {data=$0}) $ditch(2,{$chk($0,$crc_modbus($group(0,$pos)))})] + def modbus_write_req:[$addr $fcode $itom(2,$reg) $itom(2,$reglen) $len($1) $1 $crc_modbus($group(0,$pos))] + def modbus_write_resp:[$addr $fcode $ditch(1,{dl=$int($0)}) $ditch($dl,{data=$0}) $ditch(2,{$chk($0,$crc_modbus($group(0,$pos)))})] ``` # read,write表示读写流程,名称可以自定义,但要与funcpoints的flow绑定名称一致 read:{ @@ -26,5 +26,37 @@ 11X:{flow:read, fcode:03H, reg: 0000H, reglen:2, result:$float($data)}, 12K:{flow:write, fcode:10H, reg: 0db8H, reglen:1, result:$int($data)} } + }, + P056934A925C21000T : { + name:雷优/485/多回路水表V2, + protocol:{ + ```xcom + def chksum: $itom(1,$sum($1)%256) + + # $addr $len 都是输入的参数 + def cj188_read_req: [68H $fcode $sbcd($addr) 01H $len($seq) $seq $chksum($group(0,$pos)) 16H] + def cj188_read_resp: [68H $fcode $sbcd($addr) 81H $ditch(1,{dl=$int($0-$int($seq))}) $seq $ditch($dl,{data=$0}) $ditch(1) 16H] + ``` + # read,write表示读写流程,名称可以自定义,但要与funcpoints的flow绑定名称一致 + read:{ + send:$cj188_read_req() + recv:$cj188_read_resp() + }, + write:{ + send:$cj188_write_req() + recv:$cj188_write_resp() + } + }, + funcpoints:{ + 12L:{flow:read, fcode:10H, seq: [1fH 90H 01H], result:$bcd($data,0,4)*0.001}, + 12P:{flow:12L, fcode:10H, seq: [1fH 90H 01H], result:$bcd($data,4,4)*0.0001}, + 14Z:{flow:12L, fcode:10H, seq: [1fH 90H 01H], result:$bcd($data,11,2)*0.1}, + 13B:{flow:12L, fcode:10H, seq: [1fH 90H 01H], result:$int8($data,13,1)}, + 401:{flow:12L, fcode:10H, seq: [1fH 90H 01H], result:$bcd($data,4,4)}, + 402:{flow:12L, fcode:10H, seq: [1fH 90H 01H], result:$bcd($data,4,4)}, + 403:{flow:12L, fcode:10H, seq: [1fH 90H 01H], result:$bcd($data,4,4)}, + 404:{flow:12L, fcode:10H, seq: [1fH 90H 01H], result:$bcd($data,4,4)}, + 405:{flow:12L, fcode:10H, seq: [1fH 90H 01H], result:$bcd($data,4,4)}, + } } } \ No newline at end of file diff --git a/test/xcom_parser.cpp b/test/xcom_parser_test.cpp similarity index 76% rename from test/xcom_parser.cpp rename to test/xcom_parser_test.cpp index d7dcb48..3825232 100644 --- a/test/xcom_parser.cpp +++ b/test/xcom_parser_test.cpp @@ -7,10 +7,15 @@ class XComParserTest : public ::testing::Test { public: void SetUp() override { - load = xcomParser_.LoadXComFile("./test_xcom_parser.xcom"); + load = xcomParser_.LoadXComFile( + VENDOR_TEST_PATH + "/test_xcom_parser.xcom"); } - void TearDown() override { xcomParser_.Clear(); } + void TearDown() override + { + xcomParser_.Clear(); + load = false; + } XComParser xcomParser_; bool load = false; @@ -58,18 +63,22 @@ TEST_F(XComParserTest, LoadXComFileFunctions) xcomParser_.GetXComNode("P0046F56202C21000T"); const FuncParam_t &funcpoints = xcomNode->GetFuncParam("11X"); EXPECT_EQ(funcpoints.flow, "read"); - EXPECT_EQ(funcpoints.resultExpr->funcName(), "$float($data)"); + EXPECT_EQ(funcpoints.resultExpr->ToExprString(), "$float($data)"); EXPECT_EQ(funcpoints.vars.size(), 3); + EXPECT_NE(funcpoints.vars.find("reg"), funcpoints.vars.end()); EXPECT_NE(funcpoints.vars.find("reglen"), funcpoints.vars.end()); EXPECT_NE(funcpoints.vars.find("fcode"), funcpoints.vars.end()); - EXPECT_EQ(funcpoints.vars.at("reg"), - libxcom::OpValue(static_cast(0000))); - EXPECT_EQ( - funcpoints.vars.at("reglen"), libxcom::OpValue(static_cast(2))); - EXPECT_EQ( - funcpoints.vars.at("fcode"), libxcom::OpValue(static_cast(3))); + libxcom::OpValue reg = funcpoints.vars.at("reg"); + libxcom::OpValue reglen = funcpoints.vars.at("reglen"); + libxcom::OpValue fcode = funcpoints.vars.at("fcode"); + reg.Show(); + reglen.Show(); + fcode.Show(); + EXPECT_EQ(reg, libxcom::OpValue(static_cast(0000))); + EXPECT_EQ(reglen, libxcom::OpValue(static_cast(2))); + EXPECT_EQ(fcode, libxcom::OpValue(static_cast(3))); } } // namespace protocol diff --git a/test/xcom_process.cpp b/test/xcom_process.cpp deleted file mode 100644 index 60ddae7..0000000 --- a/test/xcom_process.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#include -#include -#include "xcom_process.h" -#include "xcom_handler.h" -#include "cmdvalue.h" - -namespace protocol { -class XComProcessTest : public ::testing::Test { -public: - void SetUp() override {} - - void TearDown() override {} - - XComHandler xcomHandler_; - bool load = false; -}; - -TEST_F(XComProcessTest, Process) -{ - std::shared_ptr xcomNode = - xcomHandler_.GetXComNode("P004C0F3E15821000T"); - XComProcess xcomProcess(xcomNode, "2014051809"); - xcomProcess.Process( - "12N", [](const libxcom::CmdValue &cmd) -> libxcom::CmdValue { - uint8_t buff[] = {0x68, 0x20, 0x09, 0x18, 0x05, 0x14, 0x20, 0x00, - 0x00, 0x81, 7, 0x1f, 0x90, 0x01, 0x0, 0x01, 0x22, 0x33, 0x55}; - libxcom::CmdValue cmdValue(buff, sizeof(buff)); - return cmdValue; - }); - // xcomProcess -} -} // namespace protocol - -int main(int argc, char *argv[]) -{ - utils::set_enable(true); - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} \ No newline at end of file diff --git a/test/xcom_process_test.cpp b/test/xcom_process_test.cpp new file mode 100644 index 0000000..7cbd607 --- /dev/null +++ b/test/xcom_process_test.cpp @@ -0,0 +1,62 @@ +#include +#include +#include "xcom_process.h" +#include "xcom_handler.h" +#include "cmdvalue.h" + +namespace protocol { +class XComProcessTest : public ::testing::Test { +public: + void SetUp() override + { + load = xcomParser_.LoadXComFile( + VENDOR_TEST_PATH + "/test_xcom_parser.xcom"); + } + + void TearDown() override + { + xcomParser_.Clear(); + load = false; + } + + XComParser xcomParser_; + bool load = false; +}; +TEST_F(XComProcessTest, Process) +{ + std::shared_ptr xcomNode = + xcomParser_.GetXComNode("P056934A925C21000T"); + XComProcess xcomProcess(xcomNode, "00000024240033"); + EXPECT_TRUE(xcomProcess.Process( + "12L", + [&](const libxcom::CmdValue &cmd, const ParseRecv &parseRecv) -> bool { + EXPECT_EQ(cmd.Data(), + std::vector({0x68, 0x10, 0x33, 0x00, 0x24, 0x24, 0x00, + 0x00, 0x00, 01, 03, 0x90, 0x1F, 0x01, 0xEC, 16})); + std::vector data = {0x68, 0x10, 0x33, 0x00, 0x24, 0x24, + 0x00, 0x00, 0x00, 0x81, 20, 0x90, 0x1F, 0x01, 00, 00, 00, 00, + 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 0xEC, 16}; + int result = parseRecv(data.data(), data.size()); + EXPECT_EQ(result, RECV_COMPLETE); + }, + {}, 1.00)); + EXPECT_TRUE(xcomProcess.Process( + "12P", + [&](const libxcom::CmdValue &cmd, const ParseRecv &parseRecv) -> bool { + + }, + {}, 1.00)); + EXPECT_FLOAT_EQ(xcomProcess.GetResult("12L").As(), 0); + + EXPECT_EQ(xcomProcess.GetResult("data").As().Data(), + std::vector({00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, + 00, 00, 00, 00, 00})); +} +} // namespace protocol + +int main(int argc, char *argv[]) +{ + utils::set_enable(true); + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/xcom_handler.cpp b/xcom_handler.cpp index 647b136..9390840 100644 --- a/xcom_handler.cpp +++ b/xcom_handler.cpp @@ -7,21 +7,17 @@ #include namespace protocol { -XComHandler::XComHandler() -{ - if (!xComParser_.LoadXComFile(VENDOR_CONFIG_PATH + "/protocol.xcom")) { - HTELINK_LOG_ERR("load protocol.xcom failed"); - } -} +XComHandler::XComHandler() {} XComHandler::~XComHandler() { xComParser_.Clear(); } std::shared_ptr XComHandler::GetXComInstance() { static std::shared_ptr staticXComHandler = nullptr; - if (staticXComHandler == nullptr) { - staticXComHandler = std::make_shared(); - } + static std::once_flag initFlag; + + std::call_once(initFlag, + [&]() { staticXComHandler = std::make_shared(); }); return staticXComHandler; } diff --git a/xcom_node.cpp b/xcom_node.cpp index f64df6a..cdd1484 100644 --- a/xcom_node.cpp +++ b/xcom_node.cpp @@ -1,7 +1,6 @@ #include "xcom_node.h" -#include #include - +#include namespace protocol { void XComNode::SetName(const std::string &name) { name_ = name; } @@ -45,10 +44,20 @@ const std::string &XComNode::GetTemplate() const // TODO: insert return statement here return template_; } -const Flow_t &XComNode::GetFlow(const std::string &key) const +const Flow_t XComNode::GetFlow(const std::string &key) const { + if (mapFlow_.find(key) == mapFlow_.end()) { + if (funcPoints_.find(key) != funcPoints_.end()) { + return GetFlow(GetFuncParam(key).flow); + } + return Flow_t(); + } return mapFlow_.at(key); } +bool XComNode::HasFuncId(const std::string &id) +{ + return funcPoints_.find(id) != funcPoints_.end(); +}; const FuncParam_t &XComNode::GetFuncParam(const std::string &funcId) const { return funcPoints_.at(funcId); @@ -60,19 +69,14 @@ libxcom::OpValue XComNode::ExprToValue(const std::string &strExpr) if (expr == nullptr) { return libxcom::OpValue::Null(); } - libxcom::Operator oprator(nullptr); + libxcom::Operator oprator; return expr->GenCmd(oprator); } std::shared_ptr XComNode::WrapExpress(const std::string &str) { - libxcom::TempBuf tempBuf(str); - int32_t pos = 0; - libxcom::TempBuf::RESULT res = tempBuf.Parse(pos, true); - if ((res != libxcom::TempBuf::OK && res != libxcom::TempBuf::FIN)) - return NULL; - return tempBuf.ResultExpress(); + return libxcom::Template::instance()->StaticParse(str); } const std::string &XComNode::GetName() const { return name_; } } // namespace protocol diff --git a/xcom_node.h b/xcom_node.h index 66c9647..1ee47ec 100644 --- a/xcom_node.h +++ b/xcom_node.h @@ -2,21 +2,19 @@ #define FOUNDATION_PROTOCOL_XCOMNODE_H #include #include -#include "template.h" #include "dbms.pb.h" -#include "express.h" +#include namespace protocol { - typedef struct { std::string flow; - std::shared_ptr resultExpr; + libxcom::XExpress resultExpr; std::unordered_map vars; } FuncParam_t; typedef struct { std::string call; - std::shared_ptr expr; + libxcom::XExpress expr; } Process_t; typedef struct { @@ -39,7 +37,8 @@ public: const std::string &GetName() const; const std::string &GetId() const; const std::string &GetTemplate() const; - const Flow_t &GetFlow(const std::string &key) const; + const Flow_t GetFlow(const std::string &key) const; + bool HasFuncId(const std::string &id); const FuncParam_t &GetFuncParam(const std::string &funcId) const; private: diff --git a/xcom_process.cpp b/xcom_process.cpp index 15fbf2c..a68821c 100644 --- a/xcom_process.cpp +++ b/xcom_process.cpp @@ -2,23 +2,50 @@ #include "xcom_node.h" namespace protocol { -XComProcess::XComProcess( - std::shared_ptr xcomNode, const std::string &addr) +XComProcess::XComProcess(const std::shared_ptr &xcomNode, + const std::string &addr) : xcomNode_(xcomNode) , dataItem_(xcomNode->GetName(), xcomNode->GetTemplate()) { - dataItem_.SetVar("addr", addr); + dataItem_.SetVar("addr", libxcom::OpValue(addr)); } -bool XComProcess::Process(const std::string &funcId, XComSendFunc sendFunc, - const std::vector ¶ms) +XComProcess::~XComProcess() {} + +bool XComProcess::IsReadFlow(const std::string &funcId) { if (xcomNode_ == nullptr) { return false; } + if (!xcomNode_->HasFuncId(funcId)) { + HTELINK_LOG_ERR("not find funcId %s", funcId); + return false; + } const FuncParam_t &funcParam = xcomNode_->GetFuncParam(funcId); - const Flow_t &flow = xcomNode_->GetFlow(funcParam.flow); - dataItem_.SetDataExpr(funcParam.resultExpr, 1); + if (funcParam.flow.find("read") == funcParam.flow.npos) { + return false; + } + return true; +} + +bool XComProcess::Process(const std::string &funcId, XComSend sendFunc, + const std::vector ¶ms, float ratio) +{ + if (xcomNode_ == nullptr) { + return false; + } + if (dataItem_.HasVar(funcId)) { + return true; + } + + if (!xcomNode_->HasFuncId(funcId)) { + HTELINK_LOG_ERR("not find funcId %s", funcId); + return false; + } + + const FuncParam_t &funcParam = xcomNode_->GetFuncParam(funcId); + Flow_t flow = xcomNode_->GetFlow(funcParam.flow); + dataItem_.SetDataExpr(funcParam.resultExpr, ratio); for (auto &var : funcParam.vars) { // second 需要先转换成OpValue @@ -29,29 +56,25 @@ bool XComProcess::Process(const std::string &funcId, XComSendFunc sendFunc, for (auto &opValue : params) { dataItem_.PushParam(opValue); } - std::stack stackFlow; - + libxcom::OpValue cmd; for (auto &proc : flow.procList) { if (proc.call == "send") { // 指令序列化, 绑定send函数 - libxcom::OpValue cmd = dataItem_.GenerateCmd(proc.expr); + cmd = dataItem_.GenerateCmd(proc.expr); if (cmd.IsEmpty()) { + HTELINK_LOG_ERR( + "cmd gen failed, %s", proc.expr->GetExprString()); return false; } - libxcom::CmdValue recv = sendFunc(cmd.GenCmd()); - stackFlow.push(std::move(recv)); } else if (proc.call == "recv") { - if (stackFlow.empty()) { - HTELINK_LOG_WARN("Need send process before recv"); - return false; - } - libxcom::RECV_RESULT result = - dataItem_.ParseRecvCmd(stackFlow.top(), proc.expr); - if (result != RECV_COMPLETE) { - HTELINK_LOG_ERR("receive cmd parse error, %d", result); + dataItem_.ParseRecvCmd(proc.expr); + if (!sendFunc(cmd.GenCmd(), + [&](uint8_t *buf, int32_t len) -> libxcom::RECV_RESULT { + return dataItem_.ProcessRealRecv(buf, len); + })) { + HTELINK_LOG_ERR("process %s send failed", proc.call); return false; } - stackFlow.pop(); } else { HTELINK_LOG_ERR("Not support this process, %s", proc.call.c_str()); return false; @@ -60,7 +83,7 @@ bool XComProcess::Process(const std::string &funcId, XComSendFunc sendFunc, dataItem_.SetVar(funcId, dataItem_.Result()); return true; } -const libxcom::OpValue &XComProcess::GetResult(const std::string &var) const +libxcom::OpValue XComProcess::GetResult(const std::string &var) { return dataItem_.GetVar(var); } diff --git a/xcom_process.h b/xcom_process.h index d6ca7be..325ee32 100644 --- a/xcom_process.h +++ b/xcom_process.h @@ -2,7 +2,6 @@ #define FOUNDATION_PROTOCOL_XCOMPROCESS_H #include #include -#include "template.h" #include #include #include "xcom_node.h" @@ -11,19 +10,24 @@ namespace protocol { +using ParseRecv = std::function; +using XComSend = + std::function; class XComListener { public: std::function xComSendBuffer; }; -using XComSendFunc = - std::function; + class XComProcess { public: - XComProcess(std::shared_ptr xcomNode, const std::string &addr); - bool Process(const std::string &funcId, XComSendFunc sendFunc, - const std::vector ¶ms = {}); - const libxcom::OpValue &GetResult(const std::string &var) const; + XComProcess( + const std::shared_ptr &xcomNode, const std::string &addr); + ~XComProcess(); + bool IsReadFlow(const std::string &funcId); + bool Process(const std::string &funcId, XComSend sendFunc, + const std::vector ¶ms = {}, float ratio = 1); + libxcom::OpValue GetResult(const std::string &var); private: std::shared_ptr xcomNode_ = nullptr; -- Gitee From e0cdf26060c14c7ee45be1b8da3d58bbb5b54910 Mon Sep 17 00:00:00 2001 From: wlxuz Date: Fri, 13 Jun 2025 11:00:41 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=BE=9D=E8=B5=96?= =?UTF-8?q?=E5=85=B3=E7=B3=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: wlxuz Change-Id: Ibc0f9bc815b45cdacbd43f2a2ad9b545bfe414df --- test/test_xcom_parser.xcom | 2 +- xcom_node.cpp | 5 ++++- xcom_process.cpp | 5 +++++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/test/test_xcom_parser.xcom b/test/test_xcom_parser.xcom index 52b9cfd..747f5e2 100644 --- a/test/test_xcom_parser.xcom +++ b/test/test_xcom_parser.xcom @@ -35,7 +35,7 @@ # $addr $len 都是输入的参数 def cj188_read_req: [68H $fcode $sbcd($addr) 01H $len($seq) $seq $chksum($group(0,$pos)) 16H] - def cj188_read_resp: [68H $fcode $sbcd($addr) 81H $ditch(1,{dl=$int($0-$int($seq))}) $seq $ditch($dl,{data=$0}) $ditch(1) 16H] + def cj188_read_resp: [68H $fcode $sbcd($addr) 81H $ditch(1,{dl=$int($0)-$int($seq)}) $seq $ditch($dl,{data=$0}) $ditch(1) 16H] ``` # read,write表示读写流程,名称可以自定义,但要与funcpoints的flow绑定名称一致 read:{ diff --git a/xcom_node.cpp b/xcom_node.cpp index cdd1484..b28d8ef 100644 --- a/xcom_node.cpp +++ b/xcom_node.cpp @@ -1,6 +1,7 @@ #include "xcom_node.h" #include #include +#include namespace protocol { void XComNode::SetName(const std::string &name) { name_ = name; } @@ -71,7 +72,9 @@ libxcom::OpValue XComNode::ExprToValue(const std::string &strExpr) } libxcom::Operator oprator; - return expr->GenCmd(oprator); + libxcom::OpValue v = expr->GenCmd(oprator); + HTELINK_LOG_DEBUG("expr: %s -> %s", strExpr, v.toString()); + return v; } std::shared_ptr XComNode::WrapExpress(const std::string &str) diff --git a/xcom_process.cpp b/xcom_process.cpp index a68821c..47a8dae 100644 --- a/xcom_process.cpp +++ b/xcom_process.cpp @@ -56,6 +56,11 @@ bool XComProcess::Process(const std::string &funcId, XComSend sendFunc, for (auto &opValue : params) { dataItem_.PushParam(opValue); } + + if (dataItem_.HasVar(funcParam.flow)) { + dataItem_.SetVar(funcId, dataItem_.Result()); + return true; + } libxcom::OpValue cmd; for (auto &proc : flow.procList) { if (proc.call == "send") { -- Gitee From 1a9644809804d431c7712892e09f2dbc186dd08c Mon Sep 17 00:00:00 2001 From: wlxuz Date: Sat, 14 Jun 2025 20:32:46 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E5=AE=8C=E5=96=84=E5=A4=84=E7=90=86?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: wlxuz Change-Id: If2343ec88262c08dccde369b1532832a0f34190d --- test/test_xcom_parser.xcom | 30 ++++----- test/xcom_parser_test.cpp | 34 ++++++++++ test/xcom_process_test.cpp | 127 +++++++++++++++++++++++++++++++++---- xcom_node.cpp | 4 +- xcom_process.cpp | 17 +++-- 5 files changed, 177 insertions(+), 35 deletions(-) diff --git a/test/test_xcom_parser.xcom b/test/test_xcom_parser.xcom index 747f5e2..11439da 100644 --- a/test/test_xcom_parser.xcom +++ b/test/test_xcom_parser.xcom @@ -7,10 +7,10 @@ def crc_modbus: $crc16($1,0x8005,0xffff,0x0000,1,1) # 以上可以定义公共函数 - def modbus_read_req:[$addr $fcode $itom(2,$reg) $itom(2,$reglen) $crc_modbus($group(0,$pos))] - def modbus_read_resp:[$addr $fcode $ditch(1,{dl=$int($0)}) $ditch($dl, {data=$0}) $ditch(2,{$chk($0,$crc_modbus($group(0,$pos)))})] - def modbus_write_req:[$addr $fcode $itom(2,$reg) $itom(2,$reglen) $len($1) $1 $crc_modbus($group(0,$pos))] - def modbus_write_resp:[$addr $fcode $ditch(1,{dl=$int($0)}) $ditch($dl,{data=$0}) $ditch(2,{$chk($0,$crc_modbus($group(0,$pos)))})] + def modbus_read_req:[$num($addr) $fcode $itom(2,$reg) $itom(2,$reglen) $crc_modbus($group(0,$pos))] + def modbus_read_resp:[$num($addr) $fcode $ditch(1,{dl=$int($0)}) $ditch($dl, {data=$0}) $ditch(2,{$chk($0,$crc_modbus($group(0,$pos)))})] + def modbus_write_req:[$num($addr) $fcode $itom(2,$reg) $itom(2,$reglen) $len($1) $1 $crc_modbus($group(0,$pos))] + def modbus_write_resp:[$num($addr) $fcode $ditch(1,{dl=$int($0)}) $ditch($dl,{data=$0}) $ditch(2,{$chk($0,$crc_modbus($group(0,$pos)))})] ``` # read,write表示读写流程,名称可以自定义,但要与funcpoints的flow绑定名称一致 read:{ @@ -34,8 +34,8 @@ def chksum: $itom(1,$sum($1)%256) # $addr $len 都是输入的参数 - def cj188_read_req: [68H $fcode $sbcd($addr) 01H $len($seq) $seq $chksum($group(0,$pos)) 16H] - def cj188_read_resp: [68H $fcode $sbcd($addr) 81H $ditch(1,{dl=$int($0)-$int($seq)}) $seq $ditch($dl,{data=$0}) $ditch(1) 16H] + def cj188_read_req: [68H $fcode $sbcd($addr) 01H 3 $itom(3,$seq) $chksum($group(0,$pos)) 16H] + def cj188_read_resp: [68H $fcode $sbcd($addr) 81H $ditch(1,{dl=$int($0)-3}) $itom(3,$seq) $ditch($dl,{data=$0}) $ditch(1) 16H] ``` # read,write表示读写流程,名称可以自定义,但要与funcpoints的flow绑定名称一致 read:{ @@ -48,15 +48,15 @@ } }, funcpoints:{ - 12L:{flow:read, fcode:10H, seq: [1fH 90H 01H], result:$bcd($data,0,4)*0.001}, - 12P:{flow:12L, fcode:10H, seq: [1fH 90H 01H], result:$bcd($data,4,4)*0.0001}, - 14Z:{flow:12L, fcode:10H, seq: [1fH 90H 01H], result:$bcd($data,11,2)*0.1}, - 13B:{flow:12L, fcode:10H, seq: [1fH 90H 01H], result:$int8($data,13,1)}, - 401:{flow:12L, fcode:10H, seq: [1fH 90H 01H], result:$bcd($data,4,4)}, - 402:{flow:12L, fcode:10H, seq: [1fH 90H 01H], result:$bcd($data,4,4)}, - 403:{flow:12L, fcode:10H, seq: [1fH 90H 01H], result:$bcd($data,4,4)}, - 404:{flow:12L, fcode:10H, seq: [1fH 90H 01H], result:$bcd($data,4,4)}, - 405:{flow:12L, fcode:10H, seq: [1fH 90H 01H], result:$bcd($data,4,4)}, + 12L:{flow:read, fcode:10H, seq: 0x1f9001, result:$bcd($data,0,4)*0.001}, + 12P:{flow:12L, fcode:10H, seq: 0x1f9001, result:$bcd($data,4,4)*0.0001}, + 14Z:{flow:12L, fcode:10H, seq: 0x1f9001, result:$bcd($data,11,2)*0.1}, + 13B:{flow:12L, fcode:10H, seq: 0x1f9001, result:$int8($data,13,1)}, + 401:{flow:12L, fcode:10H, seq: 0x1f9001, result:$bcd($data,4,4)}, + 402:{flow:12L, fcode:10H, seq: 0x1f9001, result:$bcd($data,4,4)}, + 403:{flow:12L, fcode:10H, seq: 0x1f9001, result:$bcd($data,4,4)}, + 404:{flow:12L, fcode:10H, seq: 0x1f9001, result:$bcd($data,4,4)}, + 405:{flow:12L, fcode:10H, seq: 0x1f9001, result:$bcd($data,4,4)}, } } } \ No newline at end of file diff --git a/test/xcom_parser_test.cpp b/test/xcom_parser_test.cpp index 3825232..c749f62 100644 --- a/test/xcom_parser_test.cpp +++ b/test/xcom_parser_test.cpp @@ -57,6 +57,22 @@ TEST_F(XComParserTest, LoadXComFileFlow) EXPECT_EQ(writeFlow.procList.at(1).call, "recv"); } +TEST_F(XComParserTest, LoadXComFileFlow2) +{ + std::shared_ptr xcomNode = + xcomParser_.GetXComNode("P056934A925C21000T"); + + const Flow_t &readFlow = xcomNode->GetFlow("read"); + EXPECT_EQ(readFlow.procList.size(), 2); + EXPECT_EQ(readFlow.procList.at(0).call, "send"); + EXPECT_EQ(readFlow.procList.at(1).call, "recv"); + + const Flow_t &flow = xcomNode->GetFlow("12L"); + EXPECT_EQ(flow.procList.size(), 2); + EXPECT_EQ(flow.procList.at(0).call, "send"); + EXPECT_EQ(flow.procList.at(1).call, "recv"); +} + TEST_F(XComParserTest, LoadXComFileFunctions) { std::shared_ptr xcomNode = @@ -80,6 +96,24 @@ TEST_F(XComParserTest, LoadXComFileFunctions) EXPECT_EQ(reglen, libxcom::OpValue(static_cast(2))); EXPECT_EQ(fcode, libxcom::OpValue(static_cast(3))); } + +TEST_F(XComParserTest, LoadXComFileFunctions2) +{ + std::shared_ptr xcomNode = + xcomParser_.GetXComNode("P056934A925C21000T"); + const FuncParam_t &funcpoints = xcomNode->GetFuncParam("12L"); + EXPECT_EQ(funcpoints.flow, "read"); + EXPECT_EQ(funcpoints.resultExpr->ToExprString(), "$bcd($data,0,4)*0.001"); + EXPECT_EQ(funcpoints.vars.size(), 2); + + EXPECT_EQ(funcpoints.vars.at("seq").As(), 0x1f9001); + EXPECT_EQ(funcpoints.vars.at("fcode").As(), 0x10); + + libxcom::OpValue seq = funcpoints.vars.at("seq"); + libxcom::OpValue fcode = funcpoints.vars.at("fcode"); + seq.Show(); + fcode.Show(); +} } // namespace protocol int main(int argc, char *argv[]) diff --git a/test/xcom_process_test.cpp b/test/xcom_process_test.cpp index 7cbd607..12d914a 100644 --- a/test/xcom_process_test.cpp +++ b/test/xcom_process_test.cpp @@ -4,6 +4,15 @@ #include "xcom_handler.h" #include "cmdvalue.h" +#define TS(func) \ + do { \ + struct timeval t1, t2; \ + gettimeofday(&t1, NULL); \ + func; \ + gettimeofday(&t2, NULL); \ + printf(#func ": %.3fmsecs\n", (t2.tv_sec - t1.tv_sec) * 1000.0 + \ + (t2.tv_usec - t1.tv_usec) / 1000.0); \ + } while (0) namespace protocol { class XComProcessTest : public ::testing::Test { public: @@ -22,36 +31,126 @@ public: XComParser xcomParser_; bool load = false; }; + TEST_F(XComProcessTest, Process) { std::shared_ptr xcomNode = xcomParser_.GetXComNode("P056934A925C21000T"); XComProcess xcomProcess(xcomNode, "00000024240033"); - EXPECT_TRUE(xcomProcess.Process( - "12L", - [&](const libxcom::CmdValue &cmd, const ParseRecv &parseRecv) -> bool { - EXPECT_EQ(cmd.Data(), - std::vector({0x68, 0x10, 0x33, 0x00, 0x24, 0x24, 0x00, - 0x00, 0x00, 01, 03, 0x90, 0x1F, 0x01, 0xEC, 16})); - std::vector data = {0x68, 0x10, 0x33, 0x00, 0x24, 0x24, - 0x00, 0x00, 0x00, 0x81, 20, 0x90, 0x1F, 0x01, 00, 00, 00, 00, - 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 0xEC, 16}; - int result = parseRecv(data.data(), data.size()); - EXPECT_EQ(result, RECV_COMPLETE); - }, - {}, 1.00)); + bool result; + TS(result = xcomProcess.Process( + "12L", + [&](const libxcom::CmdValue &cmd, + const ParseRecv &parseRecv) -> bool { + EXPECT_EQ(cmd.Data(), std::vector({0x68, 0x10, 0x33, + 0x00, 0x24, 0x24, 0x00, 0x00, 0x00, 01, + 03, 0x1F, 0x90, 0x01, 0xA7, 0x16})); + std::vector data = {0x68, 0x10, 0x33, 0x00, 0x24, 0x24, + 0x00, 0x00, 0x00, 0x81, 20, 0x1F, 0x90, 0x01, 00, 00, 00, 00, + 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 0xA7, + 0x16}; + int result = parseRecv(data.data(), data.size()); + EXPECT_EQ(result, RECV_COMPLETE); + return true; + }, + {}, 1.00)); + xcomProcess.GetResult("dl").Show(); + bool flag = false; EXPECT_TRUE(xcomProcess.Process( "12P", [&](const libxcom::CmdValue &cmd, const ParseRecv &parseRecv) -> bool { - + flag = true; + return true; }, {}, 1.00)); + EXPECT_EQ(flag, false); EXPECT_FLOAT_EQ(xcomProcess.GetResult("12L").As(), 0); + EXPECT_FLOAT_EQ(xcomProcess.GetResult("12P").As(), 0); EXPECT_EQ(xcomProcess.GetResult("data").As().Data(), std::vector({00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00})); } + +TEST_F(XComProcessTest, Process2) +{ + std::shared_ptr xcomNode = + xcomParser_.GetXComNode("P0046F56202C21000T"); + XComProcess xcomProcess(xcomNode, "01"); + bool result; + TS(result = xcomProcess.Process( + "11X", + [&](const libxcom::CmdValue &cmd, + const ParseRecv &parseRecv) -> bool { + EXPECT_EQ(cmd.Data(), std::vector({0x01, 0x03, 0x00, + 0x00, 0x00, 0x02, 0x0B, 0xC4})); + std::vector data = { + 0x01, 0x03, 0x04, 0x42, 0x07, 0x00, 0x00, 0x37, 0x25}; + int result = parseRecv(data.data(), data.size()); + EXPECT_EQ(result, RECV_COMPLETE); + return true; + }, + {}, 1.00)); + xcomProcess.GetResult("dl").Show(); + EXPECT_EQ(xcomProcess.GetResult("dl").As(), 4); + EXPECT_FLOAT_EQ(xcomProcess.GetResult("11X").As(), 33.75); + EXPECT_EQ(xcomProcess.GetResult("data").As().Data(), + std::vector({0x42, 0x07, 0x00, 0x00})); +} + +TEST_F(XComProcessTest, ProcessNotComplete) +{ + std::shared_ptr xcomNode = + xcomParser_.GetXComNode("P056934A925C21000T"); + XComProcess xcomProcess(xcomNode, "00000024240033"); + + auto func = [&](const libxcom::CmdValue &cmd, + const ParseRecv &parseRecv) -> bool { + EXPECT_EQ(cmd.Data(), + std::vector({0x68, 0x10, 0x33, 0x00, 0x24, 0x24, 0x00, + 0x00, 0x00, 01, 03, 0x1F, 0x90, 0x01, 0xA7, 0x16})); + std::vector data1 = {0x68, 0x10, 0x33, 0x00, 0x24}; + std::vector data2 = { + 0x24, 0x00, 0x00, 0x00, 0x81, 20, 0x1F, 0x90, 0x01, 00, 00, 00}; + std::vector data3 = { + 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 0xA7, 0x16}; + for (int32_t i = 0; i < 3; ++i) { + if (i == 0) { + int result = parseRecv(data1.data(), data1.size()); + EXPECT_EQ(result, RECV_NOT_COMPLETE); + } else if (i == 1) { + int result = parseRecv(data2.data(), data2.size()); + EXPECT_EQ(result, RECV_NOT_COMPLETE); + } else { + int result = parseRecv(data3.data(), data3.size()); + EXPECT_EQ(result, RECV_COMPLETE); + } + } + return true; + }; + EXPECT_TRUE(xcomProcess.Process("12L", func, {}, 1.00)); +} + +TEST_F(XComProcessTest, ProcessFail) +{ + std::shared_ptr xcomNode = + xcomParser_.GetXComNode("P056934A925C21000T"); + XComProcess xcomProcess(xcomNode, "00000024240033"); + EXPECT_FALSE(xcomProcess.Process( + "12L", + [&](const libxcom::CmdValue &cmd, const ParseRecv &parseRecv) -> bool { + EXPECT_EQ(cmd.Data(), + std::vector({0x68, 0x10, 0x33, 0x00, 0x24, 0x24, 0x00, + 0x00, 0x00, 01, 03, 0x1F, 0x90, 0x01, 0xA7, 0x16})); + std::vector data = {0x68, 0x10, 0x33, 0x00, 0x24, 0x24, + 0x00, 0x00, 0x00, 0x81, 20, 0x1F, 0x91, 0x01, 00, 00, 00, 00, + 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 0xA7, 0x16}; + int result = parseRecv(data.data(), data.size()); + EXPECT_EQ(result, RECV_FAILED); + return false; + }, + {}, 1.00)); +} } // namespace protocol int main(int argc, char *argv[]) diff --git a/xcom_node.cpp b/xcom_node.cpp index b28d8ef..e35a977 100644 --- a/xcom_node.cpp +++ b/xcom_node.cpp @@ -73,7 +73,9 @@ libxcom::OpValue XComNode::ExprToValue(const std::string &strExpr) libxcom::Operator oprator; libxcom::OpValue v = expr->GenCmd(oprator); - HTELINK_LOG_DEBUG("expr: %s -> %s", strExpr, v.toString()); + if (v.IsEmpty()) { + HTELINK_LOG_DEBUG("expr: %s -> %s", strExpr, v.toString()); + } return v; } diff --git a/xcom_process.cpp b/xcom_process.cpp index 47a8dae..a915e66 100644 --- a/xcom_process.cpp +++ b/xcom_process.cpp @@ -46,6 +46,7 @@ bool XComProcess::Process(const std::string &funcId, XComSend sendFunc, const FuncParam_t &funcParam = xcomNode_->GetFuncParam(funcId); Flow_t flow = xcomNode_->GetFlow(funcParam.flow); dataItem_.SetDataExpr(funcParam.resultExpr, ratio); + HTELINK_LOG_DEBUG("ratio: %f", ratio); for (auto &var : funcParam.vars) { // second 需要先转换成OpValue @@ -73,10 +74,10 @@ bool XComProcess::Process(const std::string &funcId, XComSend sendFunc, } } else if (proc.call == "recv") { dataItem_.ParseRecvCmd(proc.expr); - if (!sendFunc(cmd.GenCmd(), - [&](uint8_t *buf, int32_t len) -> libxcom::RECV_RESULT { - return dataItem_.ProcessRealRecv(buf, len); - })) { + auto func = [&](uint8_t *buf, int32_t len) -> libxcom::RECV_RESULT { + return dataItem_.ProcessRealRecv(buf, len); + }; + if (!sendFunc(cmd.GenCmd(), func)) { HTELINK_LOG_ERR("process %s send failed", proc.call); return false; } @@ -85,7 +86,13 @@ bool XComProcess::Process(const std::string &funcId, XComSend sendFunc, return false; } } - dataItem_.SetVar(funcId, dataItem_.Result()); + auto result = dataItem_.Result(); + result.Show(); + if (result.IsEmpty()) { + HTELINK_LOG_ERR("get result failed"); + return false; + } + dataItem_.SetVar(funcId, std::move(result)); return true; } libxcom::OpValue XComProcess::GetResult(const std::string &var) -- Gitee