Improve:Mcu manager.

This commit is contained in:
Fancy code 2024-05-16 18:49:34 +08:00
parent 744bf103c9
commit 0eb06e4213
10 changed files with 296 additions and 7 deletions

View File

@ -74,3 +74,7 @@ opt MCU上电
deactivate 大核
end
```
## 1.4. MCU监视器
  MCU监视器必须由其中一个状态继承只有状态机运行之后才能处理串口命令。

View File

@ -0,0 +1,30 @@
/*
* 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 "McuMonitor.h"
void McuMonitor::RecvIpcMissionEvent(std::shared_ptr<VMcuRecv> &recv, const IpcMission &mission)
{
}
void McuMonitor::RecvMcuHeartBeatEvent(std::shared_ptr<VMcuRecv> &recv)
{
}
void McuMonitor::RecvGetIntervalStartEvent(std::shared_ptr<VMcuRecv> &recv)
{
}
void McuMonitor::RecvGetDateTime(std::shared_ptr<VMcuRecv> &recv)
{
}
void McuMonitor::RecvGetPirSensitivity(std::shared_ptr<VMcuRecv> &recv)
{
}

View File

@ -0,0 +1,29 @@
/*
* 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_MONITOR_H
#define MCU_MONITOR_H
#include "IMcuManager.h"
class McuMonitor : public VMcuMonitor
{
public:
McuMonitor() = default;
virtual ~McuMonitor() = default;
void RecvIpcMissionEvent(std::shared_ptr<VMcuRecv> &recv, const IpcMission &mission) override;
void RecvMcuHeartBeatEvent(std::shared_ptr<VMcuRecv> &recv) override;
void RecvGetIntervalStartEvent(std::shared_ptr<VMcuRecv> &recv) override;
void RecvGetDateTime(std::shared_ptr<VMcuRecv> &recv) override;
void RecvGetPirSensitivity(std::shared_ptr<VMcuRecv> &recv) override;
};
#endif

View File

@ -5,7 +5,7 @@
| 版本 | 时间 | 说明 |
| ---- | ---- | ---- |
| V1.0 | 2024-5-14 | 首次评审。 |
| V1.1 | 2024-5-15 | 完善时序图。 |
| V1.1 | 2024-5-16 | 完善时序图。 |
## 1.1. 基本概念

View File

@ -35,6 +35,11 @@ McuManagerImpl::McuManagerImpl()
mMcuAskHandle[OtherSideSendType::SEND_IPC_MISSION] =
std::bind(&McuManagerImpl::McuAskSendIpcMissionHandle, this, _1);
mMcuAskHandle[OtherSideSendType::SEND_HEART_BEAT] = std::bind(&McuManagerImpl::McuAskSendHeartBeatHandle, this, _1);
mMcuAskHandle[OtherSideSendType::GET_INTERVAL_START] =
std::bind(&McuManagerImpl::McuAskGetIntervalStartHandle, this, _1);
mMcuAskHandle[OtherSideSendType::GET_DATE_TIME] = std::bind(&McuManagerImpl::McuAskGetDateTimeHandle, this, _1);
mMcuAskHandle[OtherSideSendType::GET_PIR_SENSITIVITY] =
std::bind(&McuManagerImpl::McuAskGetPirSensitivityHandle, this, _1);
}
std::shared_ptr<VProtocolBase> McuManagerImpl::SharedFromThis(void)
{
@ -57,6 +62,7 @@ const StatusCode McuManagerImpl::UnInit(void)
const StatusCode McuManagerImpl::SetMcuMonitor(std::shared_ptr<VMcuMonitor> &monitor)
{
std::lock_guard<std::mutex> locker(mMutex);
LogInfo("SetMcuMonitor.\n");
mMonitor = monitor;
for (auto ask : mMcuAskList) {
std::shared_ptr<McuRecvImpl> data = std::dynamic_pointer_cast<McuRecvImpl>(ask);
@ -161,6 +167,7 @@ void McuManagerImpl::OtherSideSendIpcMission(const unsigned int &serialNumber, c
~McuRecvIpcMission() = default;
void ReplyFinished(const bool result) override
{
LogInfo("OtherSideSendIpcMission finised.\n");
McuRecvImpl::mMcuManager->ReplyOtherSideSendIpcMission(ASK_RESULT::SUCCEED, McuRecvImpl::mSerialNumber);
}
};
@ -169,6 +176,7 @@ void McuManagerImpl::OtherSideSendIpcMission(const unsigned int &serialNumber, c
std::shared_ptr<VMcuRecv> recv =
std::make_shared<McuRecvIpcMission>(manager, serialNumber, OtherSideSendType::SEND_IPC_MISSION, mission);
if (monitor) {
LogInfo("Mcu manager report recv ipc mission to mcu monitor.\n");
monitor->RecvIpcMissionEvent(recv, static_cast<IpcMission>(mission));
}
else {
@ -190,6 +198,7 @@ void McuManagerImpl::OtherSideSendHearBeat(const unsigned int &serialNumber)
~McuRecvHeartBeat() = default;
void ReplyFinished(const bool result) override
{
LogInfo("OtherSideSendHearBeat finised.\n");
McuRecvImpl::mMcuManager->ReplyOtherSideSendHeartBeat(McuRecvImpl::mSerialNumber);
}
};
@ -290,7 +299,7 @@ void McuManagerImpl::OtherSideSendGetPirSensitivity(const unsigned int &serialNu
std::shared_ptr<VMcuMonitor> monitor = GetMcuMonitor();
std::shared_ptr<McuManagerImpl> manager = std::dynamic_pointer_cast<McuManagerImpl>(SharedFromThis());
std::shared_ptr<VMcuRecv> recv =
std::make_shared<McuRecvGetDateTime>(manager, serialNumber, OtherSideSendType::GET_DATE_TIME);
std::make_shared<McuRecvGetDateTime>(manager, serialNumber, OtherSideSendType::GET_PIR_SENSITIVITY);
if (monitor) {
LogInfo("Mcu manager report get pir sensitivity to mcu monitor.\n");
monitor->RecvGetPirSensitivity(recv);
@ -356,3 +365,24 @@ void McuManagerImpl::McuAskSendHeartBeatHandle(std::shared_ptr<VMcuRecv> &recv)
monitor->RecvMcuHeartBeatEvent(recv);
}
}
void McuManagerImpl::McuAskGetIntervalStartHandle(std::shared_ptr<VMcuRecv> &recv)
{
std::shared_ptr<VMcuMonitor> monitor = GetMcuMonitor();
if (monitor) {
monitor->RecvGetIntervalStartEvent(recv);
}
}
void McuManagerImpl::McuAskGetDateTimeHandle(std::shared_ptr<VMcuRecv> &recv)
{
std::shared_ptr<VMcuMonitor> monitor = GetMcuMonitor();
if (monitor) {
monitor->RecvGetDateTime(recv);
}
}
void McuManagerImpl::McuAskGetPirSensitivityHandle(std::shared_ptr<VMcuRecv> &recv)
{
std::shared_ptr<VMcuMonitor> monitor = GetMcuMonitor();
if (monitor) {
monitor->RecvGetPirSensitivity(recv);
}
}

View File

@ -29,6 +29,7 @@ enum class OtherSideSendType
SEND_HEART_BEAT,
GET_INTERVAL_START,
GET_DATE_TIME,
GET_PIR_SENSITIVITY,
END
};
class McuManagerImpl : public McuDevice, public McuProtocol, public std::enable_shared_from_this<McuManagerImpl>
@ -76,6 +77,9 @@ private: // About mMcuAskList
void AddMcuRecv(std::shared_ptr<VMcuRecv> &recv);
void McuAskSendIpcMissionHandle(std::shared_ptr<VMcuRecv> &recv);
void McuAskSendHeartBeatHandle(std::shared_ptr<VMcuRecv> &recv);
void McuAskGetIntervalStartHandle(std::shared_ptr<VMcuRecv> &recv);
void McuAskGetDateTimeHandle(std::shared_ptr<VMcuRecv> &recv);
void McuAskGetPirSensitivityHandle(std::shared_ptr<VMcuRecv> &recv);
private:
std::mutex mMutex;

View File

@ -894,6 +894,37 @@ TEST_F(McuManagerMockTest, HS_INTEGRATION_McuManager_AUTO_OtherSideSendIpcMissio
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
IMcuManager::GetInstance()->UnInit();
}
/**
* @brief Construct a new test f object
* This test case simulates the state machine receiving serial port data before it is fully started. At this point, the
* serial port data should be cached until the state machine starts and registers the serial port monitor, and reports
* the serial port data when registering the serial port monitor.
* Run: ../output_files/test/bin/McuManagerTest
* --gtest_filter=McuManagerMockTest.HS_INTEGRATION_McuManager_AUTO_OtherSideSendIpcMission2
*/
TEST_F(McuManagerMockTest, HS_INTEGRATION_McuManager_AUTO_OtherSideSendIpcMission2)
{
constexpr unsigned int TEST_SERIAL_NUMBER = 99;
class MonitorTest : public VMcuMonitor
{
public:
MonitorTest() = default;
virtual ~MonitorTest() = default;
void RecvIpcMissionEvent(std::shared_ptr<VMcuRecv> &recv, const IpcMission &mission) override
{
LogInfo("RecvIpcMissionEvent\n");
std::shared_ptr<McuRecv<unsigned char>> recvData = std::dynamic_pointer_cast<McuRecv<unsigned char>>(recv);
recv->ReplyFinished(true);
}
};
IMcuManager::GetInstance()->Init();
MockOtherSideAskIpcMission(mLinuxTest, TEST_SERIAL_NUMBER);
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
std::shared_ptr<VMcuMonitor> monitor = std::make_shared<MonitorTest>();
IMcuManager::GetInstance()->SetMcuMonitor(monitor);
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
IMcuManager::GetInstance()->UnInit();
}
// ../output_files/test/bin/McuManagerTest
// --gtest_filter=McuManagerMockTest.HS_INTEGRATION_McuManager_AUTO_OtherSideGetIntervalStart
TEST_F(McuManagerMockTest, HS_INTEGRATION_McuManager_AUTO_OtherSideGetIntervalStart)
@ -925,6 +956,44 @@ TEST_F(McuManagerMockTest, HS_INTEGRATION_McuManager_AUTO_OtherSideGetIntervalSt
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
IMcuManager::GetInstance()->UnInit();
}
/**
* @brief Construct a new test f object
* This test case simulates the state machine receiving serial port data before it is fully started. At this point, the
* serial port data should be cached until the state machine starts and registers the serial port monitor, and reports
* the serial port data when registering the serial port monitor.
* Run: ../output_files/test/bin/McuManagerTest
* --gtest_filter=McuManagerMockTest.HS_INTEGRATION_McuManager_AUTO_OtherSideGetIntervalStart2
*/
TEST_F(McuManagerMockTest, HS_INTEGRATION_McuManager_AUTO_OtherSideGetIntervalStart2)
{
constexpr unsigned int TEST_SERIAL_NUMBER = 99;
class MonitorTest : public VMcuMonitor
{
public:
MonitorTest() = default;
virtual ~MonitorTest() = default;
void RecvGetIntervalStartEvent(std::shared_ptr<VMcuRecv> &recv) override
{
LogInfo("RecvGetIntervalStartEvent\n");
std::shared_ptr<McuRecv<McuGetIntervalStart>> recvData =
std::dynamic_pointer_cast<McuRecv<McuGetIntervalStart>>(recv);
EXPECT_NE(recvData, nullptr) << "recvData is not McuGetIntervalStart.";
if (recvData) {
recvData->mDataRecvReply.mHour = 10;
recvData->mDataRecvReply.mMin = 10;
recvData->mDataRecvReply.mSecond = 10;
}
recv->ReplyFinished(true);
}
};
IMcuManager::GetInstance()->Init();
MockOtherSideGetIntervalStart(mLinuxTest, TEST_SERIAL_NUMBER);
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
std::shared_ptr<VMcuMonitor> monitor = std::make_shared<MonitorTest>();
IMcuManager::GetInstance()->SetMcuMonitor(monitor);
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
IMcuManager::GetInstance()->UnInit();
}
// ../output_files/test/bin/McuManagerTest
// --gtest_filter=McuManagerMockTest.HS_INTEGRATION_McuManager_AUTO_OtherSideGetDateTime
TEST_F(McuManagerMockTest, HS_INTEGRATION_McuManager_AUTO_OtherSideGetDateTime)
@ -959,6 +1028,47 @@ TEST_F(McuManagerMockTest, HS_INTEGRATION_McuManager_AUTO_OtherSideGetDateTime)
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
IMcuManager::GetInstance()->UnInit();
}
/**
* @brief Construct a new test f object
* This test case simulates the state machine receiving serial port data before it is fully started. At this point, the
* serial port data should be cached until the state machine starts and registers the serial port monitor, and reports
* the serial port data when registering the serial port monitor.
* Run: ../output_files/test/bin/McuManagerTest
* --gtest_filter=McuManagerMockTest.HS_INTEGRATION_McuManager_AUTO_OtherSideGetDateTime2
*/
TEST_F(McuManagerMockTest, HS_INTEGRATION_McuManager_AUTO_OtherSideGetDateTime2)
{
constexpr unsigned int TEST_SERIAL_NUMBER = 99;
class MonitorTest : public VMcuMonitor
{
public:
MonitorTest() = default;
virtual ~MonitorTest() = default;
void RecvGetDateTime(std::shared_ptr<VMcuRecv> &recv) override
{
LogInfo("RecvGetDateTime\n");
std::shared_ptr<McuRecv<McuReplyDateTime>> recvData =
std::dynamic_pointer_cast<McuRecv<McuReplyDateTime>>(recv);
EXPECT_NE(recvData, nullptr) << "recvData is not McuReplyDateTime.";
if (recvData) {
recvData->mDataRecvReply.mYear = 2024;
recvData->mDataRecvReply.mMon = 10;
recvData->mDataRecvReply.mDay = 10;
recvData->mDataRecvReply.mHour = 10;
recvData->mDataRecvReply.mMin = 10;
recvData->mDataRecvReply.mSecond = 10;
}
recv->ReplyFinished(true);
}
};
IMcuManager::GetInstance()->Init();
MockOtherSideGetDateTime(mLinuxTest, TEST_SERIAL_NUMBER);
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
std::shared_ptr<VMcuMonitor> monitor = std::make_shared<MonitorTest>();
IMcuManager::GetInstance()->SetMcuMonitor(monitor);
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
IMcuManager::GetInstance()->UnInit();
}
// ../output_files/test/bin/McuManagerTest
// --gtest_filter=McuManagerMockTest.HS_INTEGRATION_McuManager_AUTO_OtherSideGetPirSensitivity
TEST_F(McuManagerMockTest, HS_INTEGRATION_McuManager_AUTO_OtherSideGetPirSensitivity)
@ -988,4 +1098,40 @@ TEST_F(McuManagerMockTest, HS_INTEGRATION_McuManager_AUTO_OtherSideGetPirSensiti
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
IMcuManager::GetInstance()->UnInit();
}
/**
* @brief Construct a new test f object
* This test case simulates the state machine receiving serial port data before it is fully started. At this point, the
* serial port data should be cached until the state machine starts and registers the serial port monitor, and reports
* the serial port data when registering the serial port monitor.
* Run: ../output_files/test/bin/McuManagerTest
* --gtest_filter=McuManagerMockTest.HS_INTEGRATION_McuManager_AUTO_OtherSideGetPirSensitivity2
*/
TEST_F(McuManagerMockTest, HS_INTEGRATION_McuManager_AUTO_OtherSideGetPirSensitivity2)
{
constexpr unsigned int TEST_SERIAL_NUMBER = 99;
class MonitorTest : public VMcuMonitor
{
public:
MonitorTest() = default;
virtual ~MonitorTest() = default;
void RecvGetPirSensitivity(std::shared_ptr<VMcuRecv> &recv) override
{
LogInfo("RecvGetPirSensitivity\n");
std::shared_ptr<McuRecv<McuGetPirSensitivity>> recvData =
std::dynamic_pointer_cast<McuRecv<McuGetPirSensitivity>>(recv);
EXPECT_NE(recvData, nullptr) << "recvData is not McuGetPirSensitivity.";
if (recvData) {
recvData->mDataRecvReply.mSensitivity = 9;
}
recv->ReplyFinished(true);
}
};
IMcuManager::GetInstance()->Init();
MockOtherSideGetPriSensitivity(mLinuxTest, TEST_SERIAL_NUMBER);
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
std::shared_ptr<VMcuMonitor> monitor = std::make_shared<MonitorTest>();
IMcuManager::GetInstance()->SetMcuMonitor(monitor);
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
IMcuManager::GetInstance()->UnInit();
}
} // namespace McuManagerMockTest

View File

@ -42,6 +42,13 @@ private:
void CheckSerialNumber(const void *buf, const size_t &count);
void ChecCRC16Code(const void *buf, const size_t &count);
void ResetCheckCode(const void *buf, const size_t &count);
/**
* @brief The function of initializing the fx_select function can quickly return when selecting without waiting for
* the timeout to end.
* @param mock
* @param uartFd
*/
void SelectInit(std::shared_ptr<LinuxTest> &mock, const int &uartFd);
void ReplySelectSucceed(std::shared_ptr<LinuxTest> &mock, const int &uartFd);
void ReplySelectTimeOut(std::shared_ptr<LinuxTest> &mock, const int &uartFd);
bool MonitorProtocolPacket(std::shared_ptr<LinuxTest> &mock, const int &uartFd, const void *buf, size_t count);

View File

@ -128,6 +128,7 @@ void McuProtocolTestTool::Init(std::shared_ptr<LinuxTest> &mock, const UartInfo
EXPECT_CALL(*mock.get(), fx_write(uartFd, _, _))
.WillRepeatedly(
DoAll(SaveArg<2>(&WRITE_COUNT), WithArgs<0, 1, 2>(Invoke(api_write)), ReturnPointee(&WRITE_COUNT)));
SelectInit(mock, mUartFd);
}
void McuProtocolTestTool::UnInit(void)
{
@ -206,6 +207,42 @@ void McuProtocolTestTool::ResetCheckCode(const void *buf, const size_t &count)
// checkCode = htons(checkCode);
memcpy((unsigned char *)buf + count - PROTOCOL_CHECK_CODE_LENGTH, &checkCode, PROTOCOL_CHECK_CODE_LENGTH);
}
void McuProtocolTestTool::SelectInit(std::shared_ptr<LinuxTest> &mock, const int &uartFd)
{
auto selectTimeOut =
[=, &mock](int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) {
if (false == mPipeFdMockSelectInit) {
long long timeMs = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
std::this_thread::sleep_for(std::chrono::milliseconds(timeMs));
}
else {
constexpr int READ_BUF_LENGTH = 256;
constexpr int READ_FAILD = -1;
char buf[READ_BUF_LENGTH] = {0};
int selectResult = -1;
fd_set fdsRead;
FD_ZERO(&fdsRead);
FD_SET(mPipeFdMockSelect[PIPE_READ_FD_INDEX], &fdsRead);
selectResult = select(mPipeFdMockSelect[PIPE_READ_FD_INDEX] + 1, &fdsRead, NULL, NULL, timeout);
if (selectResult) {
if (false == mPipeFdMockSelectInit) {
LogWarning("mPipeFdMockSelectInit = false.\n");
return;
}
ssize_t length = read(mPipeFdMockSelect[PIPE_READ_FD_INDEX], buf, READ_BUF_LENGTH);
if (READ_FAILD == length) {
LogError("mPipeFdMockSelect failed.\n");
return;
}
if ((size_t)length != strlen(gPipeBuf)) {
LogWarning("Something wrong happened.\n");
}
}
}
};
EXPECT_CALL(*mock.get(), fx_select(uartFd + 1, _, _, _, _))
.WillRepeatedly(DoAll(WithArgs<0, 1, 2, 3, 4>(Invoke(selectTimeOut)), Return(MOCK_SELECT_TIME_OUT)));
}
void McuProtocolTestTool::ReplySelectSucceed(std::shared_ptr<LinuxTest> &mock, const int &uartFd)
{
auto selectReadable =
@ -229,7 +266,6 @@ void McuProtocolTestTool::ReplySelectSucceed(std::shared_ptr<LinuxTest> &mock, c
FD_SET(mPipeFdMockSelect[PIPE_READ_FD_INDEX], &fdsRead);
selectResult = select(mPipeFdMockSelect[PIPE_READ_FD_INDEX] + 1, &fdsRead, NULL, NULL, timeout);
if (selectResult) {
// Do nothing here.
if (false == mPipeFdMockSelectInit) {
LogWarning("mPipeFdMockSelectInit = false.\n");
return;
@ -705,6 +741,7 @@ void McuProtocolTestTool::OtherSideAskIpcMissionInit(std::shared_ptr<LinuxTest>
const unsigned int &serialNumber)
{
LockProtocolHandle();
LogInfo("OtherSideAskIpcMissionInit start.\n");
unsigned int serialNum = serialNumber;
serialNum = htonl(serialNum);
memcpy(
@ -720,6 +757,7 @@ void McuProtocolTestTool::OtherSideAskIpcMissionInit(std::shared_ptr<LinuxTest>
memcpy(buf, OTHER_SIDE_ASK_SEND_IPC_MISSION_X + PROTOCOL_DATA_KEY_HEAD_LENGTH, LEFT_DATA_LENGTH);
McuProtocolTestTool::PrintHexadecimalData(buf, LEFT_DATA_LENGTH, "OtherSideAskIpcMissionInit read:");
UnlockProtocolHandle();
LogInfo("OtherSideAskIpcMissionInit finished.\n");
};
EXPECT_CALL(*mock.get(), fx_read(uartFd, _, _))
.WillOnce(DoAll(WithArgs<0, 1, 2>(Invoke(apiReadKeyHead)), Return(PROTOCOL_DATA_KEY_HEAD_LENGTH)))

View File

@ -3,9 +3,10 @@
&emsp;&emsp;负责对MCU协议进行封包/解包,负责协议的多态替换。协议数据统一使用网络字节序(大端字节序)。
| 修改 | 说明 |
| ---- | ---- |
| 2024-5-14 | 首次评审。 |
| 版本 | 时间 | 说明 |
| ---- | ---- | ---- |
| V1.0 | 2024-5-14 | 首次评审。 |
| V1.1 | 2024-5-16 | 补充数据同步协议。 |
## 1.1. 协议格式