diff --git a/middleware/McuManager/README.md b/middleware/McuManager/README.md
index 2bc02a9..9779f41 100644
--- a/middleware/McuManager/README.md
+++ b/middleware/McuManager/README.md
@@ -4,21 +4,6 @@
## 1.1. 基本概念
-* **启动模式:决定CPU单次启动的任务内容;**
-
- 每次启动的时间都是有限的,由CPU完成单次启动完成任务后发送断电关机指令给MCU,MCU给CPU断开物理电源;启动模式可以由CPU主动询问,也可以由MCU主动发送。
-
-| 启动模式 | 说明 |
-| ---- | ---- |
-| PIR启动 | PIR触发启动。 |
-| TEST启动 | 三档拨键拨到“TEST”,常通电的工作模式。 |
-| 连拍启动 | PIR触发场景下,用户可以设置连拍的张数和连拍的间隔,CPU通过协议告诉MCU在多少时间之后进行连拍启动。 |
-| PIR延时启动 | 同PIR启动,只是PIR触发后,需要延时一段时间再给CPU上电。 |
-| 定时启动 | 间隔固定时间启动一次,例如:60min/次 |
-| 关机启动 | 某种场景下需要关机,给CPU上电一次,由CPU正式下发“关机”指令。 |
-| 低电关机 | 电池低电需要关机,给CPU上电一次,由CPU正式下发“关机”指令。 |
-| 异常启动 | CPU不正常时断电重启,例如:喂狗异常,心跳异常。 |
-
* **工作状态:**
| 工作状态 | 说明 |
@@ -27,12 +12,37 @@
| TEST状态 | 非正常工作状态,此时主控常通电,除非无操作时自动切换到ON状态。 |
| ON状态 | 设备正常工作状态,必须保证低功耗性能,PIR触发抓拍后必须快速关机(主控断电)。 |
+**评审补充:**
+
+1. 首次整机上电,必须CPU物理上电,完成SD卡产测文件检测,实现产测功能;
+2. 动态切换到TEST/ON状态,需要CPU物理上电;
+
+* **启动模式:决定CPU单次启动的任务内容;**
+
+ 每次启动的时间都是有限的,由CPU完成单次启动完成任务后发送断电关机指令给MCU,MCU给CPU断开物理电源;启动模式可以由CPU主动询问,也可以由MCU主动发送。
+
+| 启动模式 | 说明 |
+| ---- | ---- |
+| PIR启动 | PIR触发启动。 |
+| TEST启动 | 三档拨键拨到“TEST”,常通电的工作模式。 |
+| ON启动 | 三档拨键拨到“ON”,正常工作模式。 |
+| 连拍启动 | PIR触发场景下,用户可以设置连拍的张数和连拍的间隔,CPU通过协议告诉MCU在多少时间之后进行连拍启动。 |
+| PIR延时启动 | 同PIR启动,只是PIR触发后,需要延时一段时间再给CPU上电。 |
+| 定时启动 | 间隔固定时间启动一次,例如:60min/次 **待定** |
+| 关机启动 | 某种场景下需要关机,给CPU上电一次,由CPU正式下发“关机”指令。 |
+| 低电关机 | 电池低电需要关机,给CPU上电一次,由CPU正式下发“关机”指令。 |
+| 异常启动 | CPU不正常时断电重启,例如:喂狗异常,超时启动异常。 |
+
工作模式对应板子上的三档拨键,有三个工作模式:关机/TEST/ON。
+**评审补充:**
+
+* 一个PIR连拍周期内忽略PIR触发;
+
## 1.2. MCU基本功能
-* 外围连接RTC,PIR传感器;
-* 保存数据包括:CPU的启动模式,CPU定时启动时间,工作时间周期;
+* 外围连接RTC,PIR传感器,电量计;
+* 保存数据包括:CPU的启动模式,CPU定时启动时间,工作时间周期,PIR灵敏度;
* 使用串口协议与CPU进行数据/功能协议交互;
| 需要保存的数据 | 说明 |
@@ -52,6 +62,10 @@
整机物理上电时,根据实际情况刷新设备的工作状态。
+补充:
+如果掉电无法保存数据,首次物理上电向主控获取;
+默认开启喂狗;
+
```mermaid
sequenceDiagram
participant CPU
@@ -89,6 +103,8 @@ note over MCU:休眠后进入正常工作模式:当发生PIR触发时,
合理的休眠设计,最大降低产品功耗,延长单次换电的使用周期。
+定时中断待确认;
+
```mermaid
sequenceDiagram
participant CPU
@@ -167,6 +183,8 @@ end
外置MCU充当硬件狗,在系统异常时断电重启系统。喂狗逻辑和启动模式无关。
+默认开启喂狗;
+
```mermaid
sequenceDiagram
participant CPU
@@ -202,6 +220,9 @@ note over MCU:休眠后进入正常工作模式:当发生PIR触发时,
**注意:** 整机上电之后如果从来未开启过喂狗功能,此功能不生效。避免调试版本不停重启。
+取消心跳,默认开启喂狗。喂狗线程模拟主线程心跳;
+单次上电时间异常重启,总时间3min;
+
```mermaid
sequenceDiagram
participant CPU
diff --git a/middleware/McuManager/include/IMcuManager.h b/middleware/McuManager/include/IMcuManager.h
index 2d46625..097e49d 100644
--- a/middleware/McuManager/include/IMcuManager.h
+++ b/middleware/McuManager/include/IMcuManager.h
@@ -122,5 +122,6 @@ public:
virtual const StatusCode SetPirSensitivity(std::shared_ptr &ask, const unsigned char &sensitivity);
virtual const StatusCode ContorlInfraredLight(std::shared_ptr &ask, const ControlLight &control);
virtual const StatusCode GetPhotosensitivityValue(std::shared_ptr &ask);
+ virtual const char *PrintIpcMissionString(const IpcMission &mission);
};
#endif
\ No newline at end of file
diff --git a/middleware/McuManager/src/IMcuManager.cpp b/middleware/McuManager/src/IMcuManager.cpp
index fa53a80..1248b4b 100644
--- a/middleware/McuManager/src/IMcuManager.cpp
+++ b/middleware/McuManager/src/IMcuManager.cpp
@@ -78,4 +78,8 @@ const StatusCode IMcuManager::ContorlInfraredLight(std::shared_ptr &ask
const StatusCode IMcuManager::GetPhotosensitivityValue(std::shared_ptr &ask)
{
return CreateStatusCode(STATUS_CODE_VIRTUAL_FUNCTION);
+}
+const char *IMcuManager::PrintIpcMissionString(const IpcMission &mission)
+{
+ return "VIRTUAL FUNCTION";
}
\ No newline at end of file
diff --git a/middleware/McuManager/src/McuManagerImpl.cpp b/middleware/McuManager/src/McuManagerImpl.cpp
index 69fc538..d9ef88c 100644
--- a/middleware/McuManager/src/McuManagerImpl.cpp
+++ b/middleware/McuManager/src/McuManagerImpl.cpp
@@ -125,6 +125,29 @@ const StatusCode McuManagerImpl::GetPhotosensitivityValue(std::shared_ptr context = std::make_shared>>(ask);
return McuProtocol::GetPhotosensitivityValue(context);
}
+const char *McuManagerImpl::PrintIpcMissionString(const IpcMission &mission)
+{
+ switch (mission) {
+ case IpcMission::PIR_TRIGGERED: {
+ return "PIR_TRIGGERED";
+ }
+ case IpcMission::TEST: {
+ return "TEST";
+ }
+ case IpcMission::CONTINUOUS_SHOOTING: {
+ return "CONTINUOUS_SHOOTING";
+ }
+ case IpcMission::PIR_TRIGGERED_DELAY: {
+ return "PIR_TRIGGERED_DELAY";
+ }
+ case IpcMission::REGULAR_START: {
+ return "REGULAR_START";
+ }
+ default: {
+ return "UNKNOWN";
+ }
+ }
+}
std::shared_ptr McuManagerImpl::GetMcuMonitor(void)
{
auto monitor = mMonitor.lock();
diff --git a/middleware/McuManager/src/McuManagerImpl.h b/middleware/McuManager/src/McuManagerImpl.h
index c89c13e..448c6bb 100644
--- a/middleware/McuManager/src/McuManagerImpl.h
+++ b/middleware/McuManager/src/McuManagerImpl.h
@@ -47,6 +47,7 @@ public:
const StatusCode SetPirSensitivity(std::shared_ptr &ask, const unsigned char &sensitivity) override;
const StatusCode ContorlInfraredLight(std::shared_ptr &ask, const ControlLight &control) override;
const StatusCode GetPhotosensitivityValue(std::shared_ptr &ask) override;
+ const char *PrintIpcMissionString(const IpcMission &mission) override;
private:
std::shared_ptr GetMcuMonitor(void);
diff --git a/test/middleware/McuManager/src/McuManager_Test.cpp b/test/middleware/McuManager/src/McuManager_Test.cpp
index b2cddbe..b9edfe9 100644
--- a/test/middleware/McuManager/src/McuManager_Test.cpp
+++ b/test/middleware/McuManager/src/McuManager_Test.cpp
@@ -51,7 +51,7 @@ public:
}
};
// ../output_files/test/bin/McuManagerTest
-// --gtest_filter=McuManagerTest.INTEGRATION_McuManager_AUTO_GetIpcMission
+// --gtest_filter=McuManagerTest.RH_INTEGRATION_McuManager_AUTO_GetIpcMission
TEST_F(McuManagerTest, RH_INTEGRATION_McuManager_AUTO_GetIpcMission)
{
class McuAskTest : public McuAsk, public McuAskBaseTestTool
@@ -82,4 +82,173 @@ TEST_F(McuManagerTest, RH_INTEGRATION_McuManager_AUTO_GetIpcMission)
IMcuManager::GetInstance()->GetIpcMission(ask);
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
+// ../output_files/test/bin/McuManagerTest
+// --gtest_filter=McuManagerMockTest.RH_INTEGRATION_McuManager_AUTO_OtherSideSendIpcMission
+TEST_F(McuManagerTest, RH_INTEGRATION_McuManager_AUTO_OtherSideSendIpcMission)
+{
+ class MonitorTest : public VMcuMonitor
+ {
+ public:
+ MonitorTest() = default;
+ virtual ~MonitorTest() = default;
+ void RecvIpcMissionEvent(std::shared_ptr &recv, const IpcMission &mission) override
+ {
+ LogInfo("RecvIpcMissionEvent %s\n", IMcuManager::GetInstance()->PrintIpcMissionString(mission));
+ std::shared_ptr> ask = std::dynamic_pointer_cast>(recv);
+ ask->mDataReply = ASK_RESULT::SUCCEED;
+ recv->ReplyFinished(true);
+ }
+ };
+ IMcuManager::GetInstance()->Init();
+ std::shared_ptr monitor = std::make_shared();
+ IMcuManager::GetInstance()->SetMcuMonitor(monitor);
+ std::this_thread::sleep_for(std::chrono::milliseconds(2000));
+ IMcuManager::GetInstance()->UnInit();
+}
+// ../output_files/test/bin/McuManagerTest
+// --gtest_filter=McuManagerMockTest.RH_INTEGRATION_McuManager_AUTO_CutOffPowerSupply
+TEST_F(McuManagerTest, RH_INTEGRATION_McuManager_AUTO_CutOffPowerSupply)
+{
+ class McuAskTest : public McuAskBaseTestTool
+ {
+ public:
+ McuAskTest()
+ : McuAskBaseTestTool(McuAskBlock::UNRELATED,
+ McuAskReply::NEED_NOT_REPLY) // using McuAskReply::NEED_NOT_REPLY
+ {
+ }
+ virtual ~McuAskTest() = default;
+ };
+ IMcuManager::GetInstance()->Init();
+ std::shared_ptr ask = std::make_shared();
+ std::shared_ptr testTool = std::dynamic_pointer_cast(ask);
+ testTool->McuAskDefaultFeatures(testTool);
+ StatusCode code = IMcuManager::GetInstance()->CutOffPowerSupply(ask);
+ EXPECT_EQ(code.mStatusCode, STATUS_CODE_OK); // STATUS_CODE_OK means write data to mcu succeed.
+ std::this_thread::sleep_for(std::chrono::milliseconds(2000));
+ IMcuManager::GetInstance()->UnInit();
+}
+// ../output_files/test/bin/McuManagerTest
+// --gtest_filter=McuManagerMockTest.RH_INTEGRATION_McuManager_AUTO_SetFeedingCycleForWatchDog
+TEST_F(McuManagerTest, RH_INTEGRATION_McuManager_AUTO_SetFeedingCycleForWatchDog)
+{
+ class McuAskTest : public McuAsk, public McuAskBaseTestTool
+ {
+ public:
+ McuAskTest() : McuAskBaseTestTool(McuAskBlock::BLOCK,
+ McuAskReply::NEED_REPLY) // using McuAskBlock::BLOCK,
+ {
+ }
+ virtual ~McuAskTest() = default;
+ void ReplyFinished(const bool result) override
+ {
+ McuAskBaseTestTool::ReplyFinished(result);
+ if (result) {
+ LogInfo("Ask data succeed, mDataReply = %d.\n", static_cast(mDataReply));
+ EXPECT_LT(static_cast(mDataReply), static_cast(ASK_RESULT::SUCCEED));
+ }
+ else {
+ LogError("Ask data falied.\n");
+ }
+ }
+ };
+ IMcuManager::GetInstance()->Init();
+ std::shared_ptr ask = std::make_shared();
+ std::shared_ptr testTool = std::dynamic_pointer_cast(ask);
+ testTool->McuAskDefaultFeatures(testTool);
+ StatusCode code = IMcuManager::GetInstance()->SetFeedingCycleForWatchDog(ask, 1, 1, 1);
+ EXPECT_EQ(code.mStatusCode, STATUS_CODE_OK); // STATUS_CODE_OK means write data to mcu succeed.
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+ IMcuManager::GetInstance()->UnInit();
+}
+// ../output_files/test/bin/McuManagerTest
+// --gtest_filter=McuManagerMockTest.RH_INTEGRATION_McuManager_AUTO_FeedWatchDog
+TEST_F(McuManagerTest, RH_INTEGRATION_McuManager_AUTO_FeedWatchDog)
+{
+ class McuAskTest : public McuAskBaseTestTool
+ {
+ public:
+ McuAskTest()
+ : McuAskBaseTestTool(McuAskBlock::UNRELATED,
+ McuAskReply::NEED_NOT_REPLY) // using McuAskReply::NEED_NOT_REPLY
+ {
+ }
+ virtual ~McuAskTest() = default;
+ };
+ IMcuManager::GetInstance()->Init();
+ std::shared_ptr ask = std::make_shared();
+ std::shared_ptr testTool = std::dynamic_pointer_cast(ask);
+ testTool->McuAskDefaultFeatures(testTool);
+ StatusCode code = IMcuManager::GetInstance()->FeedWatchDog(ask);
+ EXPECT_EQ(code.mStatusCode, STATUS_CODE_OK); // STATUS_CODE_OK means write data to mcu succeed.
+ std::this_thread::sleep_for(std::chrono::milliseconds(2000));
+ IMcuManager::GetInstance()->UnInit();
+}
+// ../output_files/test/bin/McuManagerTest
+// --gtest_filter=McuManagerMockTest.RH_INTEGRATION_McuManager_AUTO_SetDataTime
+TEST_F(McuManagerTest, RH_INTEGRATION_McuManager_AUTO_SetDataTime)
+{
+ class McuAskTest : public McuAsk, public McuAskBaseTestTool
+ {
+ public:
+ McuAskTest() : McuAskBaseTestTool(McuAskBlock::BLOCK,
+ McuAskReply::NEED_REPLY) // using McuAskBlock::NOT_BLOCK
+ {
+ }
+ virtual ~McuAskTest() = default;
+ void ReplyFinished(const bool result) override
+ {
+ McuAskBaseTestTool::ReplyFinished(result);
+ if (result) {
+ LogInfo("Ask data succeed, mDataReply = %d.\n", static_cast(mDataReply));
+ EXPECT_LT(static_cast(mDataReply), static_cast(ASK_RESULT::SUCCEED));
+ }
+ else {
+ LogError("Ask data falied.\n");
+ }
+ }
+ };
+ IMcuManager::GetInstance()->Init();
+ std::shared_ptr ask = std::make_shared();
+ std::shared_ptr testTool = std::dynamic_pointer_cast(ask);
+ testTool->McuAskDefaultFeatures(testTool);
+ McuAskDateTime value(2014, 1, 15, 0, 0, 0);
+ StatusCode code = IMcuManager::GetInstance()->SetDateTime(ask, value);
+ EXPECT_EQ(code.mStatusCode, STATUS_CODE_OK); // STATUS_CODE_OK means write data to mcu succeed.
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+ IMcuManager::GetInstance()->UnInit();
+}
+// ../output_files/test/bin/McuManagerTest
+// --gtest_filter=McuManagerMockTest.RH_INTEGRATION_McuManager_AUTO_SetPirSensitivity
+TEST_F(McuManagerTest, RH_INTEGRATION_McuManager_AUTO_SetPirSensitivity)
+{
+ class McuAskTest : public McuAsk, public McuAskBaseTestTool
+ {
+ public:
+ McuAskTest() : McuAskBaseTestTool(McuAskBlock::BLOCK,
+ McuAskReply::NEED_REPLY) // using McuAskBlock::NOT_BLOCK
+ {
+ }
+ virtual ~McuAskTest() = default;
+ void ReplyFinished(const bool result) override
+ {
+ McuAskBaseTestTool::ReplyFinished(result);
+ if (result) {
+ LogInfo("Ask data succeed, mDataReply = %d.\n", static_cast(mDataReply));
+ EXPECT_LT(static_cast(mDataReply), static_cast(ASK_RESULT::SUCCEED));
+ }
+ else {
+ LogError("Ask data falied.\n");
+ }
+ }
+ };
+ IMcuManager::GetInstance()->Init();
+ std::shared_ptr ask = std::make_shared();
+ std::shared_ptr testTool = std::dynamic_pointer_cast(ask);
+ testTool->McuAskDefaultFeatures(testTool);
+ StatusCode code = IMcuManager::GetInstance()->SetPirSensitivity(ask, 1);
+ EXPECT_EQ(code.mStatusCode, STATUS_CODE_OK); // STATUS_CODE_OK means write data to mcu succeed.
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+ IMcuManager::GetInstance()->UnInit();
+}
} // namespace McuManagerTest
\ No newline at end of file
diff --git a/utils/McuProtocol/README.md b/utils/McuProtocol/README.md
index 097b21f..8849662 100644
--- a/utils/McuProtocol/README.md
+++ b/utils/McuProtocol/README.md
@@ -122,16 +122,16 @@ unsigned short calculate_check_sum(const unsigned char* pData, unsigned short le
4. 问答型协议只有按位最高位相反,其它位相等,例如:0x8101与0x0101是一问一答的协议;
| 命令字 | CPU | MCU | 数据段 | 协议解析 | 备注 |
-|----|----|----|----|----|----|
+| ---- | ---- | ---- | ---- | ---- | ---- |
| 0x8101 | ask | - | - | 获取启动模式 | - |
-| 0x0101 | - | reply | Data[0]:启动模式
0x01:PIR启动
0x02:TEST启动
0x03:连拍启动
0x04:PIR延时启动
0x05:定时(间隔一定时间)启动
0x06:关机
0x07:低电关机
0x08:异常启动 | 回复启动模式 | 异常启动数据:Data[1]
0x00:喂狗异常启动
0x01:心跳异常启动 |
+| 0x0101 | - | reply | Data[0]:启动模式
0x01:PIR启动
0x02:TEST启动
0x03:ON启动
0x04:连拍启动
0x05:PIR延时启动
0x06:定时(间隔一定时间)启动
0x07:关机
0x08:低电关机
0x09:异常启动 | 回复启动模式 | 异常启动数据:Data[1]
0x00:喂狗异常启动
0x01:超时异常启动 |
| 0x8102 | ask | - | - | 断电关机 | - |
| 0x8103 | ask | - | - | 喂狗 | - |
-| 0x8104 | ask | - | Data[0]:Hour
0-23
Data[1]:Min
0-59
Data[2]:Sec
0-59 | 开启狗/设置喂狗周期 | - |
-| 0x0104 | - | reply | Data[0]:结果
0x01:成功
0x02:失败 | 开启狗/设置喂狗周期回复 | - |
-| 0x8105 | ask | - | - | 关闭狗 | - |
-| 0x0105 | - | reply | Data[0]:结果
0x01:成功
0x02:失败 | 关闭狗回复 | - |
-| 0x8106 | ask | - | Data[0]:Hour
0-23
Data[1]:Min
0-59
Data[2]:Sec
0-59 | 设置间隔启动时间 | - |
+| 0x8104 | ask | - | Data[2]:两字节的数字,单位s | 设置喂狗周期 | 0s代表关闭喂狗 修改为两个字节,单位s |
+| 0x0104 | - | reply | Data[0]:结果
0x01:成功
0x02:失败 | 设置喂狗周期回复 | - |
+| 0x8105 | ask | - | - | 关闭狗 | 取消 |
+| 0x0105 | - | reply | Data[0]:结果
0x01:成功
0x02:失败 | 关闭狗回复 | 取消 |
+| 0x8106 | ask | - | Data[0]:Hour
0-23
Data[1]:Min
0-59
Data[2]:Sec
0-59 | 设置间隔启动时间 | 定时启动 |
| 0x0106 | - | reply | Data[0]:结果
0x01:成功
0x02:失败 | 设置间隔启动时间回复 | - |
| 0x8107 | ask | - | Data[0]:Year
Data[1]:Mon
1-12
Data[2]:Day
0-31
Data[3]:Hour
0-23
Data[4]:Min
0-59
Data[5]:Sec
0-59 | 设置日期和时间 | - |
| 0x0107 | - | reply | Data[0]:结果
0x01:成功
0x02:失败 | 设置日期和时间回复 | - |
@@ -145,7 +145,12 @@ unsigned short calculate_check_sum(const unsigned char* pData, unsigned short le
| 0x010B | - | reply | Data[0]:结果
0-100 | 获取光敏值回复 | 取消 |
| ====== | === | ====== | ============================ | ==================== | ======= |
| 0xC101 | reply | - | Data[0]:结果
0x01:成功
0x02:失败 | 发送启动模式回复 | - |
-| 0x4101 | - | ask | Data[0]:启动模式
0x01:PIR启动
0x02:TEST启动
0x03:连拍启动
0x04:PIR延时启动
0x05:定时(间隔一定时间)启动
0x06:关机
0x07:低电关机
0x08:异常启动 | 发送启动模式 | 异常启动数据:Data[1]
0x00:喂狗异常启动
0x01:心跳异常启动 |
-| 0xC102 | reply | - | - | 回复心跳包 | - |
-| 0x4102 | - | ask | - | 发送心跳包 | - |
+| 0x4101 | - | ask | Data[0]:启动模式
0x01:PIR启动
0x02:TEST启动
0x03:ON启动
0x04:连拍启动
0x05:PIR延时启动
0x06:定时(间隔一定时间)启动
0x07:关机
0x08:低电关机
0x09:异常启动 | 发送启动模式 | 异常启动数据:Data[1]
0x00:喂狗异常启动
0x01:超时异常启动 |
+| 0xC102 | reply | - | - | 回复心跳包 | 取消 |
+| 0x4102 | - | ask | - | 发送心跳包 | 取消 |
+### 1.2.1. 名词解析
+
+| 名词 | 解析 |
+| ---- | ---- |
+| 超时异常启动 | MCU给主控上电后(**非TEST启动**),不管主控是否正常喂狗,如果单次上电时长超过3min未关机,给主控断电重启一次。 |
\ No newline at end of file