QP(狀態機事件驅動型框架)
1 QP框架為什么簡稱QP
QP 這個簡稱可以理解為:
1)Quantum(量子) + Platform(平臺) = QP
2)量子躍遷是指微觀粒子(如原子或分子)從一個量子態突然轉變到另一個量子態的過程,伴隨能量的吸收或釋放。
3)一個借鑒了“量子躍遷”理念的、用于構建基于層次式狀態機的事件驅動型應用程序的完整開發平臺。
2 QP框架概述

3 層次式狀態機是什么
層次狀態機即HFSM。在開發過程中,角色和系統的行為復雜性不斷增加。傳統狀態機在處理復雜邏輯時,可能導致狀態間的邏輯層次混亂。尤其是當一個狀態需要包含多個子狀態時,維護這些狀態變得非常困難。引入層次狀態機HFSM可以很好地解決這些問題。
層次狀態機的核心思想是,將一個狀態機也作為狀態,這樣就能夠在狀態機內部嵌套多個子狀態機,實現更復雜的狀態切換邏輯,特別是互斥狀態間的隔離,與包含狀態間的共存。例如,角色可以有一個 移動狀態 ,但這個狀態下還可以細分為 行走 和 奔跑 子狀態,明顯的移動狀態與行走和奔跑狀態屬于包含關系。角色還可以有一個 閑置狀態 ,明顯的閑置狀態與移動狀態屬于互斥關系。
層次狀態機可以幫助我們清晰地管理這種復雜邏輯,使代碼的組織結構更加合理,滿足更多更復雜的需求
4 UML狀態機
UML狀態機,即是Unified Modeling Language State Machine。更詳細的說是:用統一的建模語言,更加可視化、更加簡潔、更加清晰的建立狀態機。
5 QP的簡單使用
5.1構造狀態機的步驟
/*************************步驟1:定義狀態機結構體*************************/
typedef struct {
QHsm super; /* 必須作為第一個成員 - 繼承來自QHsm的必要屬性 */
/* 狀態機特定屬性 */
uint32_t pressCount;
uint32_t holdTime;
} ButtonStateMachine;//按鍵狀態機結構體
/*************************步驟2:聲明狀態處理函數*************************/
/* 按鍵狀態機初始偽狀態函數 */
QState ButtonStateMachine_initial(ButtonStateMachine * const me, QEvt const * const e);
/* idle 按鍵狀態機空閑狀態處理函數 */
QState ButtonStateMachine_idle(ButtonStateMachine * const me, QEvt const * const e);
/* pressed 按鍵狀態機按壓狀態處理函數 */
QState ButtonStateMachine_pressed(ButtonStateMachine * const me, QEvt const * const e);
/* held 按鍵狀態機按住狀態處理函數 */
QState ButtonStateMachine_held(ButtonStateMachine * const me, QEvt const * const e);
/*************************步驟3:實現狀態機構造函數*************************/
void ButtonStateMachine_ctor(ButtonStateMachine * const me) {
/* 調用QHsm_ctor()構造狀態機me,并指定偽狀態函數 */
QHsm_ctor(&me->super, Q_STATE_CAST(&ButtonStateMachine_initial));
/* 初始化狀態機屬性 */
me->pressCount = 0;
me->holdTime = 0;
printf("ButtonStateMachine constructed\n");
}
/* 初始偽狀態函數 */
QState ButtonStateMachine_initial(ButtonStateMachine * const me, QEvt const * const e) {
(void)e; /* 避免未使用參數警告 */
/* 執行初始轉換到idle狀態 */
return Q_TRAN(&ButtonStateMachine_idle);
}
/* idle狀態處理函數 */
QState ButtonStateMachine_idle(ButtonStateMachine * const me, QEvt const * const e) {
switch (e->sig) {
case Q_ENTRY_SIG: {
printf("Entering IDLE state\n");
return Q_HANDLED();
}
case BUTTON_PRESSED_SIG: {
me->pressCount++;
printf("Button pressed, count: %lu\n", me->pressCount);
return Q_TRAN(&ButtonStateMachine_pressed);
}
}
return Q_SUPER(&QHsm_top);
}
/* pressed狀態處理函數 */
QState ButtonStateMachine_pressed(ButtonStateMachine * const me, QEvt const * const e) {
switch (e->sig) {
case Q_ENTRY_SIG: {
printf("Entering PRESSED state\n");
me->holdTime = 0;
return Q_HANDLED();
}
case BUTTON_RELEASED_SIG: {
printf("Button released after %lu ms\n", me->holdTime);
return Q_TRAN(&ButtonStateMachine_idle);
}
case TIMEOUT_SIG: {
me->holdTime += 100; /* 假設100ms超時 */
if (me->holdTime >= 1000) { /* 按住1秒進入held狀態 */
return Q_TRAN(&ButtonStateMachine_held);
}
return Q_HANDLED();
}
}
return Q_SUPER(&QHsm_top);
}
/* held狀態處理函數 */
QState ButtonStateMachine_held(ButtonStateMachine * const me, QEvt const * const e) {
switch (e->sig) {
case Q_ENTRY_SIG: {
printf("Entering HELD state - long press detected!\n");
return Q_HANDLED();
}
case BUTTON_RELEASED_SIG: {
printf("Long press released\n");
return Q_TRAN(&ButtonStateMachine_idle);
}
}
return Q_SUPER(&QHsm_top);
}
5.2狀態處理函數如何被QP調用
- 1)在QP中,首先調用狀態機構造函數QHsm_ctor(),用于構建狀態機的靜態結構;然后調用狀態機初始化 QHsm_init(),啟動狀態機并執行初始轉換;最后調用事件分發qhsm_dispatch(),向已初始化的狀態機分發事件。
- 3)狀態處理函數的格式框架:狀態處理函數檢查事件類型,并執行相應的動作。它可能返回以下值之一:
-
Q_RET_HANDLED:數值0,事件已處理。
-
Q_RET_IGNORED:數值1,事件被忽略(未處理)。
-
Q_RET_TRAN:數值2,事件已處理并觸發了狀態轉換,即 響應對應事件,執行相關動作后,需要改變狀態變化,就像關閉狀態 --[開門事件]--> 打開狀態。
-
Q_RET_SUPER:數值3,事件被委托給父狀態處理。
-
Q_RET_UNHANDLED:數值4,表示事件未被當前狀態處理,狀態機會繼續將事件傳遞給父狀態或其他可能的狀態。
- 4)狀態網絡的設計,實際上通過狀態處理函數的格式框架,就可以設計狀態網絡,就可以設計事件在狀態網絡中的路由,就可以設計和事件在狀態網絡中的處理。
- 5)當然狀態網絡的層次結構,還需要超狀態的概念,超狀態是一個包含其他狀態(子狀態)的父狀態。它本身可以包含狀態邏輯,同時管理一組相關的子狀態。
-
事件首先傳遞給當前活動的子狀態
-
如果子狀態不處理,事件會傳遞給超狀態
-
超狀態可以處理子狀態共享的事件邏輯
-
進入超狀態時,會自動進入其初始子狀態
-
退出超狀態時,會退出所有活動的子狀態
-
在 QHSM(分層狀態機)中,需要狀態機結構體中的成員
teep,以達到跟蹤狀態轉換的執行過程的目的。

浙公網安備 33010602011771號