今天重點(diǎn)給大家分析下機(jī)智云整個(gè)程序的數(shù)據(jù)格式,機(jī)智云運(yùn)行這么穩(wěn)定得益于整個(gè)數(shù)據(jù)格式合理規(guī)范命名,我們直接進(jìn)入主題
首先定義了一個(gè)數(shù)據(jù)類型為gizwitsProtocol_t 的全局變量,如下
/** 協(xié)議全局變量 **/
gizwitsProtocol_t gizwitsProtocol;
我們追蹤下結(jié)構(gòu)體的定義
__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狀態(tài) 事件
volatile gizwitsReport_t lastReportData;
gizwitsIssued_t issuedData; //云端下發(fā)控制報(bào)文數(shù)據(jù)
moduleStatusInfo_t wifiStatusData; //WIFI 狀態(tài)信息(信號(hào)強(qiáng)度)
}gizwitsProtocol_t;
之前一直沒見過(guò)__packed,百度下才知道__packed是字節(jié)對(duì)齊的意思, 比如說(shuō)int float double char它的總大小是4 + 4 + 8 + 1 = 17
但如果不用__packed的話,系統(tǒng)將以默認(rèn)的方式對(duì)齊(假設(shè)是4字節(jié)),那么它占4 + 4 + 8 + 4 = 20;(不足4字節(jié)以4字節(jié)補(bǔ)齊)。
這里主要定義了一些gizwits協(xié)議的下發(fā)報(bào)文標(biāo)志、緩沖區(qū)、數(shù)據(jù)長(zhǎng)度、sn、系統(tǒng)時(shí)間、上次上報(bào)數(shù)據(jù)的時(shí)間、重發(fā)機(jī)制定義、控制事件、WiFi狀態(tài)事件、上次上報(bào)的數(shù)據(jù)、云端下發(fā)的控制報(bào)文以及WiFi狀態(tài)信息這些數(shù)據(jù)的定義,這里我們重點(diǎn)關(guān)注幾個(gè)就行了。
首先是 gizwitsIssued_t ,這個(gè)結(jié)構(gòu)體里面定義了2個(gè)結(jié)構(gòu)體,一個(gè)是控制功能Flag,一個(gè)是對(duì)應(yīng)的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值,以及電機(jī)轉(zhuǎn)速這6個(gè)功能可以被控制,那么這個(gè)結(jié)構(gòu)體是在哪里被賦值的呢?我們這主函數(shù)的while循環(huán)中找到gizwitsHandle這個(gè)函數(shù),進(jìn)去之后追蹤到protocolGetOnePacket這個(gè)函數(shù),這個(gè)函數(shù)就是從gizwits的接收緩沖中拿一個(gè)完整的數(shù)據(jù)包出來(lái),不懂的可以結(jié)合我們第二講的串口環(huán)形buff,進(jìn)去一看就明白了。好,到這里我們就接到一幀從WiFi模塊發(fā)送到MCU的信號(hào)幀了,協(xié)議是將接收的數(shù)據(jù)放gizwitsProtocol的protocolBuf這個(gè)數(shù)組的,我們接著往下看,
recvHead = (protocolHead_t*)gizwitsProtocol.protocolBuf;
我們往上看recvHead的定義,是一個(gè)protocolHead_t的指針,顧名思義,這個(gè)應(yīng)該是協(xié)議頭,我們進(jìn)去看看
/******************************************************
* 協(xié)議標(biāo)準(zhǔn)頭
********************************************************/
__packed typedef struct
{
uint8_t head[2];
uint16_t len;
uint8_t cmd;
uint8_t sn;
uint8_t flags[2];
} protocolHead_t;
協(xié)議頭包括5部分,包頭header固定為0xFFFF,len指從cmd開始到整個(gè)數(shù)據(jù)包結(jié)束所占用的字節(jié),命令字節(jié)cmd表示具體的命令定義,sn由發(fā)送方給出,原路返回就是,標(biāo)志位flag默認(rèn)0,之后便是數(shù)據(jù)區(qū)與校驗(yàn)和了,這里將gizwitsProtocol.protocolBuf強(qiáng)制轉(zhuǎn)換成protocolHead_t格式 賦給recvHead ,之后就可以通過(guò)recvHead 調(diào)用協(xié)議頭的各項(xiàng)成員數(shù)據(jù)了,然后通過(guò)recvHead-》cmd判斷相應(yīng)的命令進(jìn)去相應(yīng)的語(yǔ)句中去執(zhí)行不同的命令,這里我們看下CMD_ISSUED_P0,這個(gè)的意思是命令為WiFi向MCU發(fā)送數(shù)據(jù)的命令,我們繼續(xù)執(zhí)行,來(lái)到protocolIssuedProcess這個(gè)函數(shù),進(jìn)去之后,我們看看數(shù)據(jù)是怎么定義的
protocolReport_t *protocolIssuedData = (protocolReport_t *)inData;
首先,將gizwitsProtocol.protocolBuf強(qiáng)制轉(zhuǎn)換成protocolReport_t這個(gè)類型的指針,我們看看protocolReport_t的定義,看表面,應(yīng)該是協(xié)議上報(bào)數(shù)據(jù)格式的定義
__packed typedef struct
{
protocolHead_t head;
actionType_t action;
gizwitsReport_t reportData;
uint8_t sum;
} protocolReport_t;
這里包括協(xié)議頭、動(dòng)作、上報(bào)數(shù)據(jù)與校驗(yàn)和四部分,我們重點(diǎn)看看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;
這個(gè)結(jié)構(gòu)體的定義符合了MCU 主動(dòng)發(fā)送狀態(tài)時(shí)或者回復(fù) wifi 模塊的狀態(tài)查詢時(shí)攜帶 p0 命令和完整數(shù)據(jù)區(qū) 之后,issuedAction = protocolIssuedData-》action;通過(guò)issuedAction 判斷 P0 command 命令碼,這里我們進(jìn)入ACTION_CONTROL_DEVICE,將P0區(qū)的數(shù)據(jù)轉(zhuǎn)換成事件格式,由下面這行代碼實(shí)現(xiàn)
dataPoint2Event((gizwitsIssued_t *)(inData+sizeof(protocolP0Head_t)), &gizwitsProtocol.issuedProcessEvent);
這個(gè)函數(shù)將P0數(shù)據(jù)區(qū)的數(shù)據(jù)強(qiáng)制轉(zhuǎn)換成gizwitsIssued_t格式的數(shù)據(jù),也就是我們上面介紹的事件Flag和事件Value。 我們還看到有一個(gè)gizwitsProtocol.issuedProcessEvent作為實(shí)參傳到函數(shù)中,這個(gè)也是在gizwitsProtocol_t結(jié)構(gòu)體中定義的,我們看下其結(jié)構(gòu)體定義
__packed typedef struct {
uint8_t num;
uint8_t event[EVENT_MAX];
}eventInfo_t;
這個(gè)結(jié)構(gòu)體將上面?zhèn)魅氲臄?shù)據(jù)轉(zhuǎn)換成相應(yīng)的時(shí)間格式,每個(gè)num對(duì)應(yīng)一個(gè)事件,處理完之后直接進(jìn)入對(duì)應(yīng)num處理對(duì)應(yīng)時(shí)間就OK了。
處理完這些之后,將gizwitsProtocol.issuedFlag置1, 然后判斷gizwitsProtocol.issuedFlag,進(jìn)入下面函數(shù)
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
}
接下來(lái)就看到控制LED的實(shí)際出處了
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);
}
下面的處理函數(shù)大家就都可以看懂了,可能講的有點(diǎn)亂,但是如果跟著代碼看的話還是很容易理解的,我們看下面這幅圖就一目了然了,我將協(xié)議中所有的結(jié)構(gòu)體定義以及連接關(guān)系都詳細(xì)的標(biāo)注出來(lái)不了,參考這個(gè)理解會(huì)事半功倍!
-
源代碼
+關(guān)注
關(guān)注
96文章
2943瀏覽量
66618 -
結(jié)構(gòu)體
+關(guān)注
關(guān)注
1文章
129瀏覽量
10823 -
機(jī)智云
+關(guān)注
關(guān)注
2文章
573瀏覽量
26361
原文標(biāo)題:Gokit3.0 STM32源代碼分析之三
文章出處:【微信號(hào):IoTMaker,微信公眾號(hào):機(jī)智云開發(fā)者】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論