今天重點給大家分析下機智云整個程序的數據格式,機智云運行這么穩定得益于整個數據格式合理規范命名,我們直接進入主題
首先定義了一個數據類型為gizwitsProtocol_t 的全局變量,如下
/** 協議全局變量 **/
gizwitsProtocol_t gizwitsProtocol;
我們追蹤下結構體的定義
__packed typedef struct
{
uint8_t issuedFlag;
uint8_t protocolBuf[MAX_PACKAGE_LEN];
uint8_t transparentBuff[MAX_PACKAGE_LEN];
uint32_t transparentLen;
uint32_t sn;
uint32_t lastReportTime;
eventInfo_t issuedProcessEvent; //控制事件
eventInfo_t wifiStatusEvent; //WIFI狀態 事件
volatile gizwitsReport_t lastReportData;
gizwitsIssued_t issuedData; //云端下發控制報文數據
moduleStatusInfo_t wifiStatusData; //WIFI 狀態信息(信號強度)
}gizwitsProtocol_t;
之前一直沒見過__packed,百度下才知道__packed是字節對齊的意思, 比如說int float double char它的總大小是4 + 4 + 8 + 1 = 17
但如果不用__packed的話,系統將以默認的方式對齊(假設是4字節),那么它占4 + 4 + 8 + 4 = 20;(不足4字節以4字節補齊)。
這里主要定義了一些gizwits協議的下發報文標志、緩沖區、數據長度、sn、系統時間、上次上報數據的時間、重發機制定義、控制事件、WiFi狀態事件、上次上報的數據、云端下發的控制報文以及WiFi狀態信息這些數據的定義,這里我們重點關注幾個就行了。
首先是 gizwitsIssued_t ,這個結構體里面定義了2個結構體,一個是控制功能Flag,一個是對應的Value,如下所示
__packed typedef struct {
attrFlags_t attrFlags;
attrVals_t attrVals;
}gizwitsIssued_t;
__packed typedef struct {
uint8_t LED_OnOff:1;
uint8_t LED_Color:1;
uint8_t LED_R:1;
uint8_t LED_G:1;
uint8_t LED_B:1;
uint8_t Motor_Speed:1;
}attrFlags_t;
__packed typedef struct {
uint8_t LED_OnOff:1;
uint8_t LED_Color:2;
uint8_t reserve:5;
uint8_t LED_R;
uint8_t LED_G;
uint8_t LED_B;
uint16_t Motor_Speed;
}attrVals_t;
我們看到,有LED_OnOff、LED_Color、LED的RGB值,以及電機轉速這6個功能可以被控制,那么這個結構體是在哪里被賦值的呢?我們這主函數的while循環中找到gizwitsHandle這個函數,進去之后追蹤到protocolGetOnePacket這個函數,這個函數就是從gizwits的接收緩沖中拿一個完整的數據包出來,不懂的可以結合我們第二講的串口環形buff,進去一看就明白了。好,到這里我們就接到一幀從WiFi模塊發送到MCU的信號幀了,協議是將接收的數據放gizwitsProtocol的protocolBuf這個數組的,我們接著往下看,
recvHead = (protocolHead_t*)gizwitsProtocol.protocolBuf;
我們往上看recvHead的定義,是一個protocolHead_t的指針,顧名思義,這個應該是協議頭,我們進去看看
/******************************************************
* 協議標準頭
********************************************************/
__packed typedef struct
{
uint8_t head[2];
uint16_t len;
uint8_t cmd;
uint8_t sn;
uint8_t flags[2];
} protocolHead_t;
協議頭包括5部分,包頭header固定為0xFFFF,len指從cmd開始到整個數據包結束所占用的字節,命令字節cmd表示具體的命令定義,sn由發送方給出,原路返回就是,標志位flag默認0,之后便是數據區與校驗和了,這里將gizwitsProtocol.protocolBuf強制轉換成protocolHead_t格式 賦給recvHead ,之后就可以通過recvHead 調用協議頭的各項成員數據了,然后通過recvHead-》cmd判斷相應的命令進去相應的語句中去執行不同的命令,這里我們看下CMD_ISSUED_P0,這個的意思是命令為WiFi向MCU發送數據的命令,我們繼續執行,來到protocolIssuedProcess這個函數,進去之后,我們看看數據是怎么定義的
protocolReport_t *protocolIssuedData = (protocolReport_t *)inData;
首先,將gizwitsProtocol.protocolBuf強制轉換成protocolReport_t這個類型的指針,我們看看protocolReport_t的定義,看表面,應該是協議上報數據格式的定義
__packed typedef struct
{
protocolHead_t head;
actionType_t action;
gizwitsReport_t reportData;
uint8_t sum;
} protocolReport_t;
這里包括協議頭、動作、上報數據與校驗和四部分,我們重點看看gizwitsReport_t,其定義為
__packed typedef struct {
devStatus_t devStatus;
}gizwitsReport_t;
__packed typedef struct {
uint8_t LED_OnOff:1;
uint8_t LED_Color:2;
uint8_t reserve_0:5;
uint8_t LED_R;
uint8_t LED_G;
uint8_t LED_B;
uint16_t Motor_Speed;
uint8_t Infrared:1;
uint8_t reserve_1:7;
uint8_t Temperature;
uint8_t Humidity;
uint8_t Alert_1:1;
uint8_t Alert_2:1;
uint8_t reserve_2:6;
uint8_t Fault_LED:1;
uint8_t Fault_Motor:1;
uint8_t Fault_TemHum:1;
uint8_t Fault_IR:1;
uint8_t reserve_3:4;
}devStatus_t;
這個結構體的定義符合了MCU 主動發送狀態時或者回復 wifi 模塊的狀態查詢時攜帶 p0 命令和完整數據區 之后,issuedAction = protocolIssuedData-》action;通過issuedAction 判斷 P0 command 命令碼,這里我們進入ACTION_CONTROL_DEVICE,將P0區的數據轉換成事件格式,由下面這行代碼實現
dataPoint2Event((gizwitsIssued_t *)(inData+sizeof(protocolP0Head_t)), &gizwitsProtocol.issuedProcessEvent);
這個函數將P0數據區的數據強制轉換成gizwitsIssued_t格式的數據,也就是我們上面介紹的事件Flag和事件Value。 我們還看到有一個gizwitsProtocol.issuedProcessEvent作為實參傳到函數中,這個也是在gizwitsProtocol_t結構體中定義的,我們看下其結構體定義
__packed typedef struct {
uint8_t num;
uint8_t event[EVENT_MAX];
}eventInfo_t;
這個結構體將上面傳入的數據轉換成相應的時間格式,每個num對應一個事件,處理完之后直接進入對應num處理對應時間就OK了。
處理完這些之后,將gizwitsProtocol.issuedFlag置1, 然后判斷gizwitsProtocol.issuedFlag,進入下面函數
if(1 == gizwitsProtocol.issuedFlag)
{
gizwitsProtocol.issuedFlag = 0;
eventProcess(&gizwitsProtocol.issuedProcessEvent, (uint8_t *)&gizwitsProtocol.issuedData, sizeof(gizwitsIssued_t));
memset((uint8_t *)&gizwitsProtocol.issuedProcessEvent,0x0,sizeof(gizwitsProtocol.issuedProcessEvent));//WORK_DONE
}
接下來就看到控制LED的實際出處了
case SetLED_OnOff:
if(LED_OnOn == issuedData-》attrVals.LED_OnOff)
{
reportData.devStatus.LED_OnOff = LED_OnOn;
ledRgbControl(254,0,0);
}
else
{
reportData.devStatus.LED_OnOff = LED_OnOff;
ledRgbControl(0,0,0);
}
下面的處理函數大家就都可以看懂了,可能講的有點亂,但是如果跟著代碼看的話還是很容易理解的,我們看下面這幅圖就一目了然了,我將協議中所有的結構體定義以及連接關系都詳細的標注出來不了,參考這個理解會事半功倍!
-
源代碼
+關注
關注
96文章
2949瀏覽量
67556 -
結構體
+關注
關注
1文章
130瀏覽量
11002 -
機智云
+關注
關注
2文章
602瀏覽量
26668
原文標題:Gokit3.0 STM32源代碼分析之三
文章出處:【微信號:IoTMaker,微信公眾號:機智云開發者】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
【GoKit試用體驗】+機智云GoKit開發套件學習分享1之開箱圖
【GoKit試用體驗】利用機智云提供的免費服務自定義遠程控制
【科技亦能傳承】轉贈 Gokit2.0,免費換加強版Gokit3.0
【萬元大獎】機智云智能硬件創新大賽
【Gokit 3試用體驗】(8)微信控制Gokit體驗之機智云寵物屋
重磅| Gokit1.0用戶真情回饋-Gokit3.0免費兌換
如何使用機智云開發一款智能硬件產品
機智云在Amazon Alexa平臺發布Smarthome和Custom Skill,實現亞馬遜Echo直接控制Gokit
機友分享 | 基于Gokit+機智云的低成本MCU紅外遙控器
機智云Gokit3.X源代碼分析之一
機智云Gokit3.0源代碼分析之按鍵處理機制
基于機智云Gokit3.0的智能加濕器APP控制系統
基于機智云Gokit3.0的智能加濕器APP控制系統

評論