diff --git a/middleware/McuManager/include/IMcuManager.h b/middleware/McuManager/include/IMcuManager.h index 1cb501b7..7a3b2c63 100644 --- a/middleware/McuManager/include/IMcuManager.h +++ b/middleware/McuManager/include/IMcuManager.h @@ -22,14 +22,28 @@ enum class IpcMission TEST = 0, END }; -constexpr int NEVER_TIMEOUT_UNTIL_REPLY = 0; +enum class ASK_RESULT +{ + SUCCEED = 0, + TIMEOUT, + FAILED, + END +}; class VMcuAsk { public: - VMcuAsk() = default; + VMcuAsk() { mSerialNumber = 0; } virtual ~VMcuAsk() = default; - bool IsBlock(void) { return false; } - unsigned int GetTimeOutMs(void) { return NEVER_TIMEOUT_UNTIL_REPLY; } + virtual ASK_RESULT Blocking(void) { return ASK_RESULT::END; } + virtual void StopBlocking(void) {} + virtual bool NeedReply(void) { return false; } + +public: + /** + * @brief The serial number of a single request, assigned by the McuManager module, is used for internal management + * within the McuManager module. + */ + unsigned int mSerialNumber; }; template class McuAsk : public VMcuAsk diff --git a/middleware/McuManager/src/McuDevice.cpp b/middleware/McuManager/src/McuDevice.cpp index 0dd3c3b4..02bd3e3a 100644 --- a/middleware/McuManager/src/McuDevice.cpp +++ b/middleware/McuManager/src/McuDevice.cpp @@ -15,6 +15,11 @@ #include "McuDevice.h" #include "ILog.h" #include +/** + * @brief Do not use static decoration on this constant pointer, as external test code needs to reference it. + * + */ +const char *MCU_UART_DEVICE_PTR = MCU_UART_DEVICE; McuDevice::McuDevice() { mThreadRuning = false; @@ -24,7 +29,7 @@ McuDevice::~McuDevice() {} const StatusCode McuDevice::Init(void) { UartInfo uartDevice = { - MCU_UART_DEVICE, + MCU_UART_DEVICE_PTR, 1152000, 'N', 8, @@ -59,6 +64,29 @@ const StatusCode McuDevice::UnInit(void) mUartDevice = nullptr; return CreateStatusCode(STATUS_CODE_OK); } +size_t McuDevice::WriteData(const void *buff, const size_t buffLength, std::shared_ptr &context, + const unsigned int &serialNumber) +{ + constexpr int WRITE_ERROR = -1; + std::shared_ptr>> ctx = + std::dynamic_pointer_cast>>(context); + if (!ctx) { + return WRITE_ERROR; + } + std::shared_ptr ask = ctx->mData; + ask->mSerialNumber = serialNumber; + mMutex.lock(); + AddMcuAsk(ask); + size_t length = IUartSend(mUartDevice, buff, buffLength); + mMutex.unlock(); + if (ask->NeedReply() == true) { + ASK_RESULT result = ask->Blocking(); + if (ASK_RESULT::SUCCEED == result) { + DeleteMcuAsk(ask); + } + } + return length; +} void McuDevice::DeviceRecvThread(void) { constexpr int RECV_TIMEOUT_MS = 1000; @@ -73,6 +101,10 @@ void McuDevice::DeviceRecvThread(void) while (mThreadRuning) { size_t recvLength = IUartRecv(mUartDevice, keyHeadBuf + recvTotalLength, keyHeadLength - recvTotalLength, RECV_TIMEOUT_MS); + LogInfo("mcu recv length = %d\n", recvLength); + if (recvLength <= 0) { // recv failed or recv nothing + continue; + } recvTotalLength += recvLength; if (keyHeadLength == recvTotalLength) { DeviceRecvData(keyHeadBuf, keyHeadLength); @@ -113,4 +145,16 @@ void McuDevice::DeviceRecvData(const char *keyHead, const size_t headLength) } } free(dataBuf); +} +void McuDevice::AddMcuAsk(std::shared_ptr &ask) +{ + // std::lock_guard locker(mMutex); + if (ask->NeedReply() == true) { + mAllAsk.push_back(ask); + } +} +void McuDevice::DeleteMcuAsk(std::shared_ptr &ask) +{ + // + std::lock_guard locker(mMutex); } \ No newline at end of file diff --git a/middleware/McuManager/src/McuDevice.h b/middleware/McuManager/src/McuDevice.h index 30f2ff9b..b77dc663 100644 --- a/middleware/McuManager/src/McuDevice.h +++ b/middleware/McuManager/src/McuDevice.h @@ -17,6 +17,8 @@ #include "IMcuManager.h" #include "McuProtocol.h" #include "UartDevice.h" +#include +#include #include class McuDevice : public IMcuManager, virtual public VProtocolBase { @@ -25,16 +27,22 @@ public: virtual ~McuDevice(); const StatusCode Init(void) override; const StatusCode UnInit(void) override; + size_t WriteData(const void *buff, const size_t buffLength, std::shared_ptr &context, + const unsigned int &serialNumber) override; public: void DeviceRecvThread(void); private: void DeviceRecvData(const char *keyHead, const size_t headLength); + void AddMcuAsk(std::shared_ptr &ask); + void DeleteMcuAsk(std::shared_ptr &ask); private: + std::mutex mMutex; void *mUartDevice; std::thread mUartRecvThread; bool mThreadRuning; + std::list> mAllAsk; }; #endif \ No newline at end of file diff --git a/test/middleware/McuManager/CMakeLists.txt b/test/middleware/McuManager/CMakeLists.txt index d3491c1e..fb311cb5 100644 --- a/test/middleware/McuManager/CMakeLists.txt +++ b/test/middleware/McuManager/CMakeLists.txt @@ -3,13 +3,15 @@ include(${CMAKE_SOURCE_DIR_IPCSDK}/build/global_config.cmake) set(EXECUTABLE_OUTPUT_PATH ${TEST_OUTPUT_PATH}/bin) include_directories( - . ./src ./include + ./tool/include ${UTILS_SOURCE_PATH}/Log/include ${UTILS_SOURCE_PATH}/StatusCode/include + ${UTILS_SOURCE_PATH}/UartDevice/include ${MIDDLEWARE_SOURCE_PATH}/McuManager/include ${TEST_SOURCE_PATH}/utils/LinuxApiMock/include + ${TEST_SOURCE_PATH}/utils/UartDevice/tool/include/ ${EXTERNAL_SOURCE_PATH}/gtest/googletest-release-1.11.0/googletest/include ${EXTERNAL_SOURCE_PATH}/gtest/googletest-release-1.11.0/googlemock/include ) @@ -22,8 +24,11 @@ link_directories( set(CMAKE_AUTOMOC ON) set(CMAKE_INCLUDE_CURRENT_DIR ON) -set(CMAKE_AUTOMOC ON) -set(CMAKE_INCLUDE_CURRENT_DIR ON) +if (DEFINED MCU_UART_DEVICE) + add_definitions(-DMCU_UART_DEVICE=\"${MCU_UART_DEVICE}\") +else() + message(FATAL_ERROR "You set define MCU_UART_DEVICE in toolchan .cmake file to tell what uart device to contrl.") +endif() aux_source_directory(. SRC_FILES_MAIN) aux_source_directory(./src SRC_FILES) @@ -33,7 +38,7 @@ endif() set(TARGET_NAME McuManagerTest) add_executable(${TARGET_NAME} ${SRC_FILES_MAIN} ${SRC_FILES}) -target_link_libraries(${TARGET_NAME} McuManager UartDeviceTestTool gtest gmock pthread) +target_link_libraries(${TARGET_NAME} McuManager McuManagerTestTool gtest gmock pthread) if(${TEST_COVERAGE} MATCHES "true") target_link_libraries(${TARGET_NAME} gcov) endif() @@ -75,4 +80,6 @@ add_custom_command( WORKING_DIRECTORY ${PLATFORM_PATH}/cmake-shell/ ) endif() -define_file_name(${TARGET_NAME}) \ No newline at end of file +define_file_name(${TARGET_NAME}) + +add_subdirectory(tool) \ No newline at end of file diff --git a/test/middleware/McuManager/src_mock/McuManager_Mock_Test.cpp b/test/middleware/McuManager/src_mock/McuManager_Mock_Test.cpp index 71ecf8a2..2d020b63 100644 --- a/test/middleware/McuManager/src_mock/McuManager_Mock_Test.cpp +++ b/test/middleware/McuManager/src_mock/McuManager_Mock_Test.cpp @@ -1,11 +1,13 @@ #include "ILog.h" #include "IMcuManager.h" #include "LinuxApiMock.h" +#include "McuManagerTestTool.h" #include #include +#include namespace McuManagerMockTest { -class McuManagerMockTest : public testing::Test +class McuManagerMockTest : public testing::Test, public McuManagerTestTool { public: McuManagerMockTest() {} @@ -23,7 +25,7 @@ public: std::shared_ptr test = mLinuxTest; LinuxApiMock::GetInstance(&test); LinuxApiMock::GetInstance()->Init(); - // RegisterUartDevice(mLinuxTest, gUartDevice); + McuManagerTestTool::Init(mLinuxTest); } virtual void TearDown() { @@ -31,16 +33,26 @@ public: mLinuxTest = std::make_shared(); std::shared_ptr test = std::make_shared(); LinuxApiMock::GetInstance(&test); - // UnregisterUartDevice(gUartDevice); + McuManagerTestTool::UnInit(); } public: std::shared_ptr mLinuxTest; }; -// ../output_files/test/bin/McuManagerTest --gtest_filter=McuManagerMockTest.UNIT_McuManager_EXAMPLE_AUTO_Demo -TEST_F(McuManagerMockTest, UNIT_McuManager_EXAMPLE_AUTO_Demo) +// ../output_files/test/bin/McuManagerTest +// --gtest_filter=McuManagerMockTest.INTEGRATION_McuManager_EXAMPLE_GetIpcMissiony +TEST_F(McuManagerMockTest, INTEGRATION_McuManager_EXAMPLE_GetIpcMissiony) { + class McuAskTest : public McuAsk + { + public: + McuAskTest() = default; + virtual ~McuAskTest() = default; + }; IMcuManager::GetInstance()->Init(); + std::shared_ptr ask = std::make_shared(); + IMcuManager::GetInstance()->GetIpcMissiony(ask); + std::this_thread::sleep_for(std::chrono::milliseconds(2000)); IMcuManager::GetInstance()->UnInit(); } } // namespace McuManagerMockTest \ No newline at end of file diff --git a/test/middleware/McuManager/tool/CMakeLists.txt b/test/middleware/McuManager/tool/CMakeLists.txt new file mode 100644 index 00000000..2c5ed3bc --- /dev/null +++ b/test/middleware/McuManager/tool/CMakeLists.txt @@ -0,0 +1,53 @@ +include(${CMAKE_SOURCE_DIR_IPCSDK}/build/global_config.cmake) +set(EXECUTABLE_OUTPUT_PATH ${EXEC_OUTPUT_PATH}) +set(LIBRARY_OUTPUT_PATH ${LIBS_OUTPUT_PATH}) + +include_directories( + ./src + ./include + ${UTILS_SOURCE_PATH}/StatusCode/include + ${UTILS_SOURCE_PATH}/Log/include + ${TEST_SOURCE_PATH}/utils/LinuxApiMock/include +) +# link_directories( +# ${EXTERNAL_SOURCE_PATH}/libconfig/libconfig-1.7.3/lib/.libs +# ) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +aux_source_directory(./src TEST_TOOL_SRC_FILES) +set(TEST_TOOL_TARGET McuManagerTestTool) +add_library(${TEST_TOOL_TARGET} STATIC ${TEST_TOOL_SRC_FILES}) +target_link_libraries(${TEST_TOOL_TARGET} UartDeviceTestTool LinuxApiMock Log) + +if ("${CLANG_TIDY_SUPPORT}" MATCHES "true") +add_custom_target( + McuManagerTestTool_code_check + COMMAND ${CLANG_TIDY_EXE} + -checks='${CLANG_TIDY_CHECKS}' + --header-filter=.* + --system-headers=false + ${TEST_TOOL_SRC_FILES} + ${CLANG_TIDY_CONFIG} + -p ${PLATFORM_PATH}/cmake-shell + WORKING_DIRECTORY ${TEST_SOURCE_PATH}/middleware/McuManager/tool +) +file(GLOB_RECURSE HEADER_FILES *.h) +add_custom_target( + McuManagerTestTool_code_format + COMMAND ${CLANG_FORMAT_EXE} + -style=file + -i ${TEST_TOOL_SRC_FILES} ${HEADER_FILES} + WORKING_DIRECTORY ${TEST_SOURCE_PATH}/middleware/McuManager/tool +) +add_custom_command( + TARGET ${TEST_TOOL_TARGET} + PRE_BUILD + COMMAND make McuManagerTestTool_code_check + COMMAND make McuManagerTestTool_code_format + WORKING_DIRECTORY ${PLATFORM_PATH}/cmake-shell/ +) +endif() + +define_file_name(${TEST_TOOL_TARGET}) \ No newline at end of file diff --git a/test/middleware/McuManager/tool/include/McuManagerTestTool.h b/test/middleware/McuManager/tool/include/McuManagerTestTool.h new file mode 100644 index 00000000..ce2eaebd --- /dev/null +++ b/test/middleware/McuManager/tool/include/McuManagerTestTool.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2023 Fancy Code. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MCU_MANAGER_TEST_TOOL_H +#define MCU_MANAGER_TEST_TOOL_H +#include "LinuxApiMock.h" +#include "UartDeviceTestTool.h" +class McuManagerTestTool : public UartDeviceTestTool +{ +public: + McuManagerTestTool() = default; + virtual ~McuManagerTestTool() = default; + void Init(std::shared_ptr &mock); + void UnInit(void); +}; +#endif \ No newline at end of file diff --git a/test/middleware/McuManager/tool/src/McuManagerTestTool.cpp b/test/middleware/McuManager/tool/src/McuManagerTestTool.cpp new file mode 100644 index 00000000..bd5f565b --- /dev/null +++ b/test/middleware/McuManager/tool/src/McuManagerTestTool.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2023 Fancy Code. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "McuManagerTestTool.h" +#include "ILog.h" +extern const char *MCU_UART_DEVICE_PTR; +static UartInfo gUartDevice = { + MCU_UART_DEVICE_PTR, + 1152000, + 'N', + 8, + 1, + 'N', +}; +void McuManagerTestTool::Init(std::shared_ptr &mock) +{ + LogInfo("McuManagerTestTool::Init\n"); + RegisterUartDevice(mock, gUartDevice); +} +void McuManagerTestTool::UnInit(void) +{ + // + UnregisterUartDevice(gUartDevice); +} \ No newline at end of file diff --git a/test/utils/CMakeLists.txt b/test/utils/CMakeLists.txt index e9b8df2a..1486257c 100644 --- a/test/utils/CMakeLists.txt +++ b/test/utils/CMakeLists.txt @@ -5,5 +5,6 @@ add_subdirectory(SharedData) add_subdirectory(WebServer) add_subdirectory(UartDevice) add_subdirectory(LinuxApiMock) +add_subdirectory(McuProtocol) diff --git a/test/utils/McuProtocol/CMakeLists.txt b/test/utils/McuProtocol/CMakeLists.txt new file mode 100644 index 00000000..f4e8c70d --- /dev/null +++ b/test/utils/McuProtocol/CMakeLists.txt @@ -0,0 +1,2 @@ + +add_subdirectory(tool) \ No newline at end of file diff --git a/test/utils/McuProtocol/tool/CMakeLists.txt b/test/utils/McuProtocol/tool/CMakeLists.txt new file mode 100644 index 00000000..a1382016 --- /dev/null +++ b/test/utils/McuProtocol/tool/CMakeLists.txt @@ -0,0 +1,53 @@ +include(${CMAKE_SOURCE_DIR_IPCSDK}/build/global_config.cmake) +set(EXECUTABLE_OUTPUT_PATH ${EXEC_OUTPUT_PATH}) +set(LIBRARY_OUTPUT_PATH ${LIBS_OUTPUT_PATH}) + +include_directories( + ./src + ./include + ${UTILS_SOURCE_PATH}/StatusCode/include + ${UTILS_SOURCE_PATH}/Log/include + ${TEST_SOURCE_PATH}/utils/LinuxApiMock/include +) +# link_directories( +# ${EXTERNAL_SOURCE_PATH}/libconfig/libconfig-1.7.3/lib/.libs +# ) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +aux_source_directory(./src TEST_TOOL_SRC_FILES) +set(TEST_TOOL_TARGET McuProtocolTestTool) +add_library(${TEST_TOOL_TARGET} STATIC ${TEST_TOOL_SRC_FILES}) +target_link_libraries(${TEST_TOOL_TARGET} LinuxApiMock Log) + +if ("${CLANG_TIDY_SUPPORT}" MATCHES "true") +add_custom_target( + McuProtocolTestTool_code_check + COMMAND ${CLANG_TIDY_EXE} + -checks='${CLANG_TIDY_CHECKS}' + --header-filter=.* + --system-headers=false + ${TEST_TOOL_SRC_FILES} + ${CLANG_TIDY_CONFIG} + -p ${PLATFORM_PATH}/cmake-shell + WORKING_DIRECTORY ${TEST_SOURCE_PATH}/utils/McuProtocol/tool +) +file(GLOB_RECURSE HEADER_FILES *.h) +add_custom_target( + McuProtocolTestTool_code_format + COMMAND ${CLANG_FORMAT_EXE} + -style=file + -i ${TEST_TOOL_SRC_FILES} ${HEADER_FILES} + WORKING_DIRECTORY ${TEST_SOURCE_PATH}/utils/McuProtocol/tool +) +add_custom_command( + TARGET ${TEST_TOOL_TARGET} + PRE_BUILD + COMMAND make McuProtocolTestTool_code_check + COMMAND make McuProtocolTestTool_code_format + WORKING_DIRECTORY ${PLATFORM_PATH}/cmake-shell/ +) +endif() + +define_file_name(${TEST_TOOL_TARGET}) \ No newline at end of file diff --git a/test/utils/McuProtocol/tool/include/McuProtocolTestTool.h b/test/utils/McuProtocol/tool/include/McuProtocolTestTool.h new file mode 100644 index 00000000..f297c002 --- /dev/null +++ b/test/utils/McuProtocol/tool/include/McuProtocolTestTool.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2023 Fancy Code. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ \ No newline at end of file diff --git a/test/utils/McuProtocol/tool/src/McuProtocolTestTool.cpp b/test/utils/McuProtocol/tool/src/McuProtocolTestTool.cpp new file mode 100644 index 00000000..f297c002 --- /dev/null +++ b/test/utils/McuProtocol/tool/src/McuProtocolTestTool.cpp @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2023 Fancy Code. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ \ No newline at end of file diff --git a/test/utils/UartDevice/CMakeLists.txt b/test/utils/UartDevice/CMakeLists.txt index 865a7450..bc452e5e 100644 --- a/test/utils/UartDevice/CMakeLists.txt +++ b/test/utils/UartDevice/CMakeLists.txt @@ -20,9 +20,6 @@ link_directories( set(CMAKE_AUTOMOC ON) set(CMAKE_INCLUDE_CURRENT_DIR ON) -set(CMAKE_AUTOMOC ON) -set(CMAKE_INCLUDE_CURRENT_DIR ON) - aux_source_directory(. SRC_FILES) aux_source_directory(./src SRC_FILES) if(${TARGET_PLATFORM} MATCHES ${DEFINE_LINUX}) diff --git a/test/utils/UartDevice/tool/src/UartDeviceTestTool.cpp b/test/utils/UartDevice/tool/src/UartDeviceTestTool.cpp index 98bed5f2..b827d318 100644 --- a/test/utils/UartDevice/tool/src/UartDeviceTestTool.cpp +++ b/test/utils/UartDevice/tool/src/UartDeviceTestTool.cpp @@ -25,7 +25,7 @@ void UartDeviceTestTool::RegisterUartDevice(std::shared_ptr &mock, co constexpr int TCGETATTR_SUCCEED = 0; constexpr int TCSETATTR_SUCCEED = 0; int uartFd = mock->GetHandleForMock(); - LogInfo("uartFd = %d\n", uartFd); + LogInfo("device = %s, uartFd = %d\n", uart.mDevice, uartFd); EXPECT_CALL(*mock.get(), fx_open(uart.mDevice, _)).WillRepeatedly(DoAll((Return(uartFd)))); EXPECT_CALL(*mock.get(), fx_tcgetattr(uartFd, _)).WillRepeatedly(DoAll(Return(TCGETATTR_SUCCEED))); EXPECT_CALL(*mock.get(), fx_tcsetattr(uartFd, _, _)).WillRepeatedly(DoAll(Return(TCSETATTR_SUCCEED))); diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt index 7fa10474..a64cb10d 100644 --- a/utils/CMakeLists.txt +++ b/utils/CMakeLists.txt @@ -9,3 +9,4 @@ add_subdirectory(LinuxApi) # add_subdirectory(MultiProcess) add_subdirectory(WebServer) add_subdirectory(McuProtocol) +add_subdirectory(ModBusCRC16) diff --git a/utils/McuProtocol/CMakeLists.txt b/utils/McuProtocol/CMakeLists.txt index 12329192..95132a9a 100644 --- a/utils/McuProtocol/CMakeLists.txt +++ b/utils/McuProtocol/CMakeLists.txt @@ -7,6 +7,7 @@ include_directories( ./include # ${UTILS_SOURCE_PATH}/LinuxApi/include ${UTILS_SOURCE_PATH}/StatusCode/include + ${UTILS_SOURCE_PATH}/ModBusCRC16/include ${UTILS_SOURCE_PATH}/Log/include ) # link_directories( @@ -20,7 +21,7 @@ aux_source_directory(./src SRC_FILES) set(TARGET_NAME McuProtocol) add_library(${TARGET_NAME} STATIC ${SRC_FILES}) -target_link_libraries(${TARGET_NAME} StatusCode Log) +target_link_libraries(${TARGET_NAME} ModBusCRC16 StatusCode Log) if ("${CLANG_TIDY_SUPPORT}" MATCHES "true") add_custom_target( diff --git a/utils/McuProtocol/include/McuProtocol.h b/utils/McuProtocol/include/McuProtocol.h index f2d8d3e9..3e670789 100644 --- a/utils/McuProtocol/include/McuProtocol.h +++ b/utils/McuProtocol/include/McuProtocol.h @@ -59,7 +59,11 @@ public: protected: virtual std::shared_ptr SharedFromThis(void) { return std::make_shared(); } - virtual size_t WriteData(const void *buff, const size_t buffLength) { return 0; } + virtual size_t WriteData(const void *buff, const size_t buffLength, std::shared_ptr &context, + const unsigned int &serialNumber) + { + return 0; + } protected: virtual size_t GetKeyHeadLength(void) { return 0; } diff --git a/utils/McuProtocol/src/McuProtocol.cpp b/utils/McuProtocol/src/McuProtocol.cpp index 8a90fa09..c5813b34 100644 --- a/utils/McuProtocol/src/McuProtocol.cpp +++ b/utils/McuProtocol/src/McuProtocol.cpp @@ -42,8 +42,13 @@ const StatusCode McuProtocol::GetIpcMissiony(std::shared_ptr & std::shared_ptr param = std::make_shared>(PROTOCOL_COMMAND::ASK_IPC_MISSION, data); std::shared_ptr handle = ProtocolHandle::CreateProtocolData(param); - WriteData(handle->GetProtocolDataBuff(), handle->GetProtocolDataLength()); - return CreateStatusCode(STATUS_CODE_OK); + size_t length = + WriteData(handle->GetProtocolDataBuff(), handle->GetProtocolDataLength(), context, handle->GetSerialNumber()); + LogInfo("WriteData length = %d\n", length); + if (handle->GetProtocolDataLength() == length) { + return CreateStatusCode(STATUS_CODE_OK); + } + return CreateStatusCode(STATUS_CODE_NOT_OK); } void McuProtocol::DataHandleThread(void) { diff --git a/utils/McuProtocol/src/ProtocolHandle.cpp b/utils/McuProtocol/src/ProtocolHandle.cpp index b547c958..876e772a 100644 --- a/utils/McuProtocol/src/ProtocolHandle.cpp +++ b/utils/McuProtocol/src/ProtocolHandle.cpp @@ -14,7 +14,9 @@ */ #include "ProtocolHandle.h" #include "ILog.h" +#include "ModBusCRC16.h" #include +unsigned int ProtocolHandle::mSerialNumber = 0; constexpr unsigned short PROTOCOL_HEAD = 0xFAC1; constexpr size_t KEY_HEAD_LENGTH = sizeof(short) + sizeof(unsigned int) + sizeof(short) + sizeof(short); #pragma pack(1) @@ -28,9 +30,55 @@ typedef struct protocol_packet short mCheckCode; } ProtocolPacket; #pragma pack() +ProtocolHandle::ProtocolHandle(const std::shared_ptr ¶m) : mParam(param) +{ + mProtocolData = nullptr; + mProtocolDataLength = 0; + mSerialNumber = 0; + mMakePacketFunc[ASK_IPC_MISSION] = std::bind(&ProtocolHandle::MakeAskIpcMissionPacket, this, std::placeholders::_1); +} +ProtocolHandle::~ProtocolHandle() +{ + if (nullptr != mProtocolData) { + free(mProtocolData); + mProtocolData = nullptr; + } +} +void ProtocolHandle::MakeProtocolPacket(const std::shared_ptr ¶m) +{ + std::map::iterator iter; + iter = mMakePacketFunc.find(param->mCommand); + if (iter != mMakePacketFunc.end()) { + mMakePacketFunc[param->mCommand](param); + } +} +void ProtocolHandle::MakeAskIpcMissionPacket(const std::shared_ptr ¶m) +{ + if (mProtocolData != nullptr) { + LogError("Something wrong happened, make packet failed.\n"); + return; + } + size_t dataLength = KEY_HEAD_LENGTH + sizeof(short); + mProtocolData = (unsigned char *)malloc(dataLength); + if (nullptr == mProtocolData) { + LogError("malloc failed, MakeAskIpcMissionPacket return.\n"); + return; + } + ProtocolPacket packet; + packet.mHead = PROTOCOL_HEAD; + packet.mCommand = param->mCommand; + packet.mLength = dataLength; + packet.mCheckCode = Calculate_Check_Sum(mProtocolData, dataLength - sizeof(short)); + packet.mSerialNumber = mSerialNumber; + mSerialNumber++; + memcpy(mProtocolData, &packet, KEY_HEAD_LENGTH); + memcpy(mProtocolData + KEY_HEAD_LENGTH, &packet.mCheckCode, sizeof(short)); + mProtocolDataLength = dataLength; +} std::shared_ptr ProtocolHandle::CreateProtocolData(const std::shared_ptr ¶m) { - std::shared_ptr handle = std::make_shared(); + std::shared_ptr handle = std::make_shared(param); + handle->MakeProtocolPacket(param); return handle; } void ProtocolHandle::ProtocolAnalysis(const void *data, const size_t &length) diff --git a/utils/McuProtocol/src/ProtocolHandle.h b/utils/McuProtocol/src/ProtocolHandle.h index 54e18393..9f89db4d 100644 --- a/utils/McuProtocol/src/ProtocolHandle.h +++ b/utils/McuProtocol/src/ProtocolHandle.h @@ -15,6 +15,8 @@ #ifndef PROTOCOL_HANDLE_H #define PROTOCOL_HANDLE_H #include "StatusCode.h" +#include +#include #include enum PROTOCOL_COMMAND { @@ -44,13 +46,36 @@ public: */ T mData; }; +using MakePacketFunc = std::function &)>; class ProtocolHandle { public: - ProtocolHandle() = default; - virtual ~ProtocolHandle() = default; - virtual void *GetProtocolDataBuff(void) { return nullptr; } - virtual size_t GetProtocolDataLength(void) { return 0; } + ProtocolHandle(const std::shared_ptr ¶m); + virtual ~ProtocolHandle(); + void *GetProtocolDataBuff(void) { return mProtocolData; } + size_t GetProtocolDataLength(void) { return mProtocolDataLength; } + unsigned int GetSerialNumber(void) { return mProtocolSerialNumber; } + +private: + void MakeProtocolPacket(const std::shared_ptr ¶m); + void MakeAskIpcMissionPacket(const std::shared_ptr ¶m); + +private: + std::shared_ptr mParam; + std::map mMakePacketFunc; + unsigned char *mProtocolData; + size_t mProtocolDataLength; + /** + * @brief Single protocol package serial number. + * + */ + unsigned int mProtocolSerialNumber; + /** + * @brief The global protocol packet serial number is used to bind the data content of the one question one answer + * protocol. + * + */ + static unsigned int mSerialNumber; public: static std::shared_ptr CreateProtocolData(const std::shared_ptr ¶m); diff --git a/utils/ModBusCRC16/CMakeLists.txt b/utils/ModBusCRC16/CMakeLists.txt new file mode 100644 index 00000000..fccf46b2 --- /dev/null +++ b/utils/ModBusCRC16/CMakeLists.txt @@ -0,0 +1,44 @@ + +include(${CMAKE_SOURCE_DIR_IPCSDK}/build/global_config.cmake) +set(EXECUTABLE_OUTPUT_PATH ${EXEC_OUTPUT_PATH}) +set(LIBRARY_OUTPUT_PATH ${LIBS_OUTPUT_PATH}) + +include_directories( + ./src + ./include + ${UTILS_SOURCE_PATH}/ModBusCRC16/include + ${UTILS_SOURCE_PATH}/Log/include +) +#do not rely on any other library +#link_directories( +#) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +aux_source_directory(./src SRC_FILES) + +set(TARGET_NAME ModBusCRC16) +add_library(${TARGET_NAME} STATIC ${SRC_FILES}) +target_link_libraries(${TARGET_NAME} Log) + +if ("${CLANG_TIDY_SUPPORT}" MATCHES "true") +add_custom_target( + ModBusCRC16_code_check + COMMAND ${CLANG_TIDY_EXE} + -checks='${CLANG_TIDY_CHECKS}' + --header-filter=.* + --system-headers=false + ${SRC_FILES} + ${CLANG_TIDY_CONFIG} + -p ${PLATFORM_PATH}/cmake-shell + WORKING_DIRECTORY ${UTILS_SOURCE_PATH}/ModBusCRC16 +) +add_custom_command( + TARGET ${TARGET_NAME} + PRE_BUILD + COMMAND make ModBusCRC16_code_check + WORKING_DIRECTORY ${PLATFORM_PATH}/cmake-shell/ +) +endif() +define_file_name(${TARGET_NAME}) \ No newline at end of file diff --git a/utils/ModBusCRC16/include/ModBusCRC16.h b/utils/ModBusCRC16/include/ModBusCRC16.h new file mode 100644 index 00000000..acb3335c --- /dev/null +++ b/utils/ModBusCRC16/include/ModBusCRC16.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2023 Fancy Code. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MODBUSCRC16_H +#define MODBUSCRC16_H +#ifdef __cplusplus +extern "C" { +#endif +unsigned short Calculate_Check_Sum(const unsigned char *pData, unsigned short length); +#ifdef __cplusplus +} +#endif +#endif \ No newline at end of file diff --git a/utils/ModBusCRC16/src/ModBusCRC16.cpp b/utils/ModBusCRC16/src/ModBusCRC16.cpp new file mode 100644 index 00000000..36928cb5 --- /dev/null +++ b/utils/ModBusCRC16/src/ModBusCRC16.cpp @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2023 Fancy Code. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "ModBusCRC16.h" +/* Table of CRC values for high–order byte */ +unsigned char chCRCHi[] = { + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, + 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, + 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, + 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, + 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, + 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, + 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, + 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, + 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, + 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, + 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, + 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40}; + +/* Table of CRC values for low–order byte */ +unsigned char chCRCLo[] = { + 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, + 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, + 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, + 0x12, 0x13, 0xD3, 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, + 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, + 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, + 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26, 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, + 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, + 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, + 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5, 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, + 0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, + 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, + 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C, 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, + 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80, 0x40}; +/** + * @brief Calculate check sum. + * + * @param pData pointer of data + * @param length length of data + * @return unsigned short + */ +unsigned short Calculate_Check_Sum(const unsigned char *pData, unsigned short length) +{ + unsigned char CRCHi = 0xFF; + unsigned char CRCLo = 0xFF; + int uIndex; + while (length--) { + uIndex = CRCHi ^ *pData++; + CRCHi = CRCLo ^ chCRCHi[uIndex]; + CRCLo = chCRCLo[uIndex]; + } + return (CRCHi << 8 | CRCLo); +} \ No newline at end of file diff --git a/utils/UartDevice/src/UartDeviceImpl.cpp b/utils/UartDevice/src/UartDeviceImpl.cpp index 21af0159..79a06319 100644 --- a/utils/UartDevice/src/UartDeviceImpl.cpp +++ b/utils/UartDevice/src/UartDeviceImpl.cpp @@ -30,6 +30,7 @@ const char *GetUartDeviceModuleName(void) { return UART_DEVICE_NAME; } UartDeviceImpl::UartDeviceImpl(const UartInfo &uatrInfo) : mUatrInfo(uatrInfo) { mFd = -1; } const StatusCode UartDeviceImpl::UartOpen(void) { + LogInfo("open uart device = %s\n", mUatrInfo.mDevice); mFd = fx_open(mUatrInfo.mDevice, O_RDWR | O_NOCTTY | O_NONBLOCK); if (INVALID_FD == mFd) { perror("Can't Open Serial Port");