diff --git a/middleware/McuManager/src/McuDevice.cpp b/middleware/McuManager/src/McuDevice.cpp index f5298dc..0dd3c3b 100644 --- a/middleware/McuManager/src/McuDevice.cpp +++ b/middleware/McuManager/src/McuDevice.cpp @@ -13,7 +13,13 @@ * limitations under the License. */ #include "McuDevice.h" -McuDevice::McuDevice() { mUartDevice = nullptr; } +#include "ILog.h" +#include +McuDevice::McuDevice() +{ + mThreadRuning = false; + mUartDevice = nullptr; +} McuDevice::~McuDevice() {} const StatusCode McuDevice::Init(void) { @@ -26,14 +32,85 @@ const StatusCode McuDevice::Init(void) 'N', }; mUartDevice = CreateUartDevice(uartDevice); + if (nullptr == mUartDevice) { + LogError("CreateUartDevice failed.\n"); + return CreateStatusCode(STATUS_CODE_NOT_OK); + } + StatusCode code = IUartOpen(mUartDevice); + if (IsCodeOK(code) == false) { + LogError("IUartOpen failed.\n"); + return code; + } + auto recvThread = [](std::shared_ptr device) { device->DeviceRecvThread(); }; + std::shared_ptr device = std::dynamic_pointer_cast(SharedFromThis()); + mUartRecvThread = std::thread(recvThread, device); return CreateStatusCode(STATUS_CODE_OK); } const StatusCode McuDevice::UnInit(void) { + mThreadRuning = false; + if (mUartRecvThread.joinable()) { + mUartRecvThread.join(); + } if (nullptr != mUartDevice) { IUartDeviceFree(mUartDevice); } mUartDevice = nullptr; return CreateStatusCode(STATUS_CODE_OK); +} +void McuDevice::DeviceRecvThread(void) +{ + constexpr int RECV_TIMEOUT_MS = 1000; + size_t recvTotalLength = 0; + const size_t keyHeadLength = GetKeyHeadLength(); + char *keyHeadBuf = (char *)malloc(keyHeadLength); + if (nullptr == keyHeadBuf) { + LogError("malloc failed, DeviceRecvThread return.\n"); + return; + } + mThreadRuning = true; + while (mThreadRuning) { + size_t recvLength = + IUartRecv(mUartDevice, keyHeadBuf + recvTotalLength, keyHeadLength - recvTotalLength, RECV_TIMEOUT_MS); + recvTotalLength += recvLength; + if (keyHeadLength == recvTotalLength) { + DeviceRecvData(keyHeadBuf, keyHeadLength); + memset(keyHeadBuf, 0, keyHeadLength); + recvTotalLength = 0; + } + } + free(keyHeadBuf); +} + +void McuDevice::DeviceRecvData(const char *keyHead, const size_t headLength) +{ + constexpr int RECV_TIMEOUT_MS = 1000; + size_t recvTotalLength = 0; + size_t dataLength = 0; + // const size_t keyHeadLength = GetKeyHeadLength(); + const StatusCode code = GetDataLength(keyHead, headLength, dataLength); + if (IsCodeOK(code) == false || 0 == dataLength || dataLength <= headLength) { + LogError("Recv data error.\n"); + return; + } + char *dataBuf = (char *)malloc(dataLength); + if (nullptr == dataBuf) { + LogError("malloc failed, DeviceRecvData return.\n"); + return; + } + memset(dataBuf, 0, dataLength); + memcpy(dataBuf, keyHead, headLength); + while (mThreadRuning) { + size_t recvLength = IUartRecv(mUartDevice, + dataBuf + headLength + recvTotalLength, + dataLength - headLength - recvTotalLength, + RECV_TIMEOUT_MS); + recvTotalLength += recvLength; + if (dataLength - headLength == recvTotalLength) { + PushMcuData(dataBuf, dataLength); + break; + } + } + free(dataBuf); } \ No newline at end of file diff --git a/middleware/McuManager/src/McuDevice.h b/middleware/McuManager/src/McuDevice.h index e5b0221..30f2ff9 100644 --- a/middleware/McuManager/src/McuDevice.h +++ b/middleware/McuManager/src/McuDevice.h @@ -17,6 +17,7 @@ #include "IMcuManager.h" #include "McuProtocol.h" #include "UartDevice.h" +#include class McuDevice : public IMcuManager, virtual public VProtocolBase { public: @@ -25,7 +26,15 @@ public: const StatusCode Init(void) override; const StatusCode UnInit(void) override; +public: + void DeviceRecvThread(void); + +private: + void DeviceRecvData(const char *keyHead, const size_t headLength); + private: void *mUartDevice; + std::thread mUartRecvThread; + bool mThreadRuning; }; #endif \ No newline at end of file diff --git a/middleware/McuManager/src/McuManagerImpl.cpp b/middleware/McuManager/src/McuManagerImpl.cpp index 49a37a2..7267e80 100644 --- a/middleware/McuManager/src/McuManagerImpl.cpp +++ b/middleware/McuManager/src/McuManagerImpl.cpp @@ -13,6 +13,19 @@ * limitations under the License. */ #include "McuManagerImpl.h" +std::shared_ptr McuManagerImpl::SharedFromThis(void) { return shared_from_this(); } +const StatusCode McuManagerImpl::Init(void) +{ + McuDevice::Init(); + McuProtocol::Init(); + return CreateStatusCode(STATUS_CODE_OK); +} +const StatusCode McuManagerImpl::UnInit(void) +{ + McuDevice::UnInit(); + McuProtocol::UnInit(); + return CreateStatusCode(STATUS_CODE_OK); +} const StatusCode McuManagerImpl::GetIpcMissiony(std::shared_ptr ask) { std::shared_ptr context = std::make_shared>>(ask); diff --git a/middleware/McuManager/src/McuManagerImpl.h b/middleware/McuManager/src/McuManagerImpl.h index 16a3182..6511666 100644 --- a/middleware/McuManager/src/McuManagerImpl.h +++ b/middleware/McuManager/src/McuManagerImpl.h @@ -17,11 +17,14 @@ #include "IMcuManager.h" #include "McuDevice.h" #include "McuProtocol.h" -class McuManagerImpl : public McuDevice, public McuProtocol +class McuManagerImpl : public McuDevice, public McuProtocol, public std::enable_shared_from_this { public: McuManagerImpl() = default; virtual ~McuManagerImpl() = default; + std::shared_ptr SharedFromThis(void) override; + const StatusCode Init(void) override; + const StatusCode UnInit(void) override; const StatusCode GetIpcMissiony(std::shared_ptr ask) override; }; #endif \ 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 48c095a..71ecf8a 100644 --- a/test/middleware/McuManager/src_mock/McuManager_Mock_Test.cpp +++ b/test/middleware/McuManager/src_mock/McuManager_Mock_Test.cpp @@ -37,6 +37,10 @@ public: public: std::shared_ptr mLinuxTest; }; -// ../output_files/test/bin/UartDeviceTest --gtest_filter=McuManagerTest.UNIT_UartDevice_EXAMPLE_AUTO_Demo -TEST_F(McuManagerMockTest, UNIT_UartDevice_EXAMPLE_AUTO_Demo) {} +// ../output_files/test/bin/McuManagerTest --gtest_filter=McuManagerMockTest.UNIT_McuManager_EXAMPLE_AUTO_Demo +TEST_F(McuManagerMockTest, UNIT_McuManager_EXAMPLE_AUTO_Demo) +{ + IMcuManager::GetInstance()->Init(); + IMcuManager::GetInstance()->UnInit(); +} } // namespace McuManagerMockTest \ No newline at end of file diff --git a/test/utils/UartDevice/tool/CMakeLists.txt b/test/utils/UartDevice/tool/CMakeLists.txt index a79a69d..b4b7e1b 100644 --- a/test/utils/UartDevice/tool/CMakeLists.txt +++ b/test/utils/UartDevice/tool/CMakeLists.txt @@ -19,7 +19,7 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON) aux_source_directory(./src TEST_TOOL_SRC_FILES) set(TEST_TOOL_TARGET UartDeviceTestTool) add_library(${TEST_TOOL_TARGET} STATIC ${TEST_TOOL_SRC_FILES}) -target_link_libraries(${TEST_TOOL_TARGET} UartDevice LinuxApiMock Log) +target_link_libraries(${TEST_TOOL_TARGET} LinuxApiMock 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 a5782af..f2d8d3e 100644 --- a/utils/McuProtocol/include/McuProtocol.h +++ b/utils/McuProtocol/include/McuProtocol.h @@ -16,7 +16,11 @@ #define MCU_PROTOCOL_H #include "StatusCode.h" #include +#include #include +#include +#include +#include /** * @brief The context of protocol processing is used for the association binding of protocol data transmission and * reception, ensuring the correct logic of protocol question and answer. @@ -39,15 +43,32 @@ public: public: T mData; }; +class SingleMcuPacket +{ +public: + SingleMcuPacket(const void *buf, const size_t &length) : mBuf(buf), mLength(length) {} + ~SingleMcuPacket() = default; + const void *mBuf; + const size_t mLength; +}; class VProtocolBase { public: VProtocolBase() = default; virtual ~VProtocolBase() = default; -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; } +protected: + virtual size_t GetKeyHeadLength(void) { return 0; } + virtual StatusCode GetDataLength(const void *keyHead, const size_t &headLength, size_t &dataLength) + { + return CreateStatusCode(STATUS_CODE_INVALID_PARAMENTER); + } + virtual void PushMcuData(const void *buf, const size_t &length) {} + public: }; class McuProtocol : virtual public VProtocolBase @@ -55,6 +76,21 @@ class McuProtocol : virtual public VProtocolBase public: McuProtocol() = default; virtual ~McuProtocol() = default; + const StatusCode Init(void); + const StatusCode UnInit(void); const StatusCode GetIpcMissiony(std::shared_ptr &context); + void DataHandleThread(void); + +protected: + size_t GetKeyHeadLength(void) override; + StatusCode GetDataLength(const void *keyHead, const size_t &headLength, size_t &dataLength) override; + void PushMcuData(const void *buf, const size_t &length) override; + +private: + std::mutex mMutex; + sem_t mSem; + std::thread mDataHandleThread; + bool mThreadRuning; + std::list mMcuDataList; }; #endif \ No newline at end of file diff --git a/utils/McuProtocol/src/McuProtocol.cpp b/utils/McuProtocol/src/McuProtocol.cpp index 6392b04..8a90fa0 100644 --- a/utils/McuProtocol/src/McuProtocol.cpp +++ b/utils/McuProtocol/src/McuProtocol.cpp @@ -13,7 +13,29 @@ * limitations under the License. */ #include "McuProtocol.h" +#include "ILog.h" #include "ProtocolHandle.h" +#include +constexpr int THREAD_SHARING = 0; +constexpr int INITIAL_VALUE_OF_SEMAPHORE = 0; +const StatusCode McuProtocol::Init(void) +{ + sem_init(&mSem, THREAD_SHARING, INITIAL_VALUE_OF_SEMAPHORE); + auto dataHandleThread = [](std::shared_ptr handle) { handle->DataHandleThread(); }; + std::shared_ptr handle = std::dynamic_pointer_cast(SharedFromThis()); + mDataHandleThread = std::thread(dataHandleThread, handle); + return CreateStatusCode(STATUS_CODE_OK); +} +const StatusCode McuProtocol::UnInit(void) +{ + mThreadRuning = false; + sem_post(&mSem); + if (mDataHandleThread.joinable()) { + mDataHandleThread.join(); + } + sem_destroy(&mSem); + return CreateStatusCode(STATUS_CODE_OK); +} const StatusCode McuProtocol::GetIpcMissiony(std::shared_ptr &context) { char data = 0; @@ -22,4 +44,37 @@ const StatusCode McuProtocol::GetIpcMissiony(std::shared_ptr & std::shared_ptr handle = ProtocolHandle::CreateProtocolData(param); WriteData(handle->GetProtocolDataBuff(), handle->GetProtocolDataLength()); return CreateStatusCode(STATUS_CODE_OK); +} +void McuProtocol::DataHandleThread(void) +{ + mThreadRuning = true; + while (mThreadRuning) { + sem_wait(&mSem); + if (mMcuDataList.size() == 0) { + continue; + } + mMutex.lock(); + SingleMcuPacket packet = mMcuDataList.front(); + mMutex.unlock(); + ProtocolHandle::ProtocolAnalysis(packet.mBuf, packet.mLength); + mMcuDataList.pop_front(); + free((void *)packet.mBuf); + } +} +size_t McuProtocol::GetKeyHeadLength(void) { return ProtocolHandle::GetKeyHeadLength(); } +StatusCode McuProtocol::GetDataLength(const void *keyHead, const size_t &headLength, size_t &dataLength) +{ + return ProtocolHandle::GetDataLength(keyHead, headLength, dataLength); +} +void McuProtocol::PushMcuData(const void *buf, const size_t &length) +{ + char *data = (char *)malloc(length); + if (nullptr == data) { + LogError("malloc failed, PushMcuData failed.\n"); + return; + } + std::lock_guard locker(mMutex); + SingleMcuPacket packet(data, length); + mMcuDataList.push_back(packet); + sem_post(&mSem); } \ No newline at end of file diff --git a/utils/McuProtocol/src/ProtocolHandle.cpp b/utils/McuProtocol/src/ProtocolHandle.cpp index 2162b86..b547c95 100644 --- a/utils/McuProtocol/src/ProtocolHandle.cpp +++ b/utils/McuProtocol/src/ProtocolHandle.cpp @@ -13,11 +13,15 @@ * limitations under the License. */ #include "ProtocolHandle.h" +#include "ILog.h" +#include constexpr unsigned short PROTOCOL_HEAD = 0xFAC1; +constexpr size_t KEY_HEAD_LENGTH = sizeof(short) + sizeof(unsigned int) + sizeof(short) + sizeof(short); #pragma pack(1) typedef struct protocol_packet { short mHead; + unsigned int mSerialNumber; short mCommand; short mLength; char *mData; @@ -28,4 +32,24 @@ std::shared_ptr ProtocolHandle::CreateProtocolData(const std::sh { std::shared_ptr handle = std::make_shared(); return handle; +} +void ProtocolHandle::ProtocolAnalysis(const void *data, const size_t &length) +{ + // +} +size_t ProtocolHandle::GetKeyHeadLength(void) { return KEY_HEAD_LENGTH; } +StatusCode ProtocolHandle::GetDataLength(const void *keyHead, const size_t &headLength, size_t &dataLength) +{ + if (KEY_HEAD_LENGTH != headLength) { + LogError("key head buf error.\n"); + return CreateStatusCode(STATUS_CODE_NOT_OK); + } + ProtocolPacket packet = {0}; + memcpy(&packet, keyHead, headLength); + if (PROTOCOL_HEAD != packet.mHead) { + LogError("Protocol head unmatch.\n"); + return CreateStatusCode(STATUS_CODE_NOT_OK); + } + dataLength = packet.mLength; + return CreateStatusCode(STATUS_CODE_OK); } \ No newline at end of file diff --git a/utils/McuProtocol/src/ProtocolHandle.h b/utils/McuProtocol/src/ProtocolHandle.h index 9cb5fed..54e1839 100644 --- a/utils/McuProtocol/src/ProtocolHandle.h +++ b/utils/McuProtocol/src/ProtocolHandle.h @@ -14,6 +14,7 @@ */ #ifndef PROTOCOL_HANDLE_H #define PROTOCOL_HANDLE_H +#include "StatusCode.h" #include enum PROTOCOL_COMMAND { @@ -53,5 +54,8 @@ public: public: static std::shared_ptr CreateProtocolData(const std::shared_ptr ¶m); + static void ProtocolAnalysis(const void *data, const size_t &length); + static size_t GetKeyHeadLength(void); + static StatusCode GetDataLength(const void *keyHead, const size_t &headLength, size_t &dataLength); }; #endif \ No newline at end of file