快速接入阿里云物聯(lián)網(wǎng)平臺(tái)技術(shù)方案分享
上一篇網(wǎng)文,我們實(shí)現(xiàn)ESP8266固件的下載、一鍵配網(wǎng)和云智能APP綁定設(shè)備。
Windows下AliOS Things環(huán)境搭建及ESP8266 固件下載
隨著物聯(lián)網(wǎng)設(shè)備的普及,物聯(lián)網(wǎng)操作系統(tǒng)也成了廣大開發(fā)者熱烈討論的話題之一,很多的組織和廠商都推出了在物聯(lián)網(wǎng)節(jié)點(diǎn)上的基礎(chǔ)軟件——物聯(lián)網(wǎng)操作系統(tǒng),如國(guó)內(nèi)云服務(wù)供應(yīng)商Alibaba推出的AliOS Things ,Amazon公司的Amazon FreeRTOS,再如開源社區(qū)領(lǐng)袖Linux基金會(huì)推出的Zephyr,以及在國(guó)內(nèi)知名度很高的RT-Thread等等。
今天我們來對(duì)AliOS Things中的示例linkkitapp例程進(jìn)行一下解析,希望可以為你解惑一二。
系統(tǒng)架構(gòu)
AliOS Things是什么?
AliOS Things是面向IoT領(lǐng)域的輕量級(jí)物聯(lián)網(wǎng)嵌入式操作系統(tǒng)。致力于搭建云端一體化IoT基礎(chǔ)設(shè)備。具備極致性能,極簡(jiǎn)開發(fā)、云端一體、豐富組件、安全防護(hù)等關(guān)鍵能力,并支持終端設(shè)備連接到阿里云Link,可廣泛應(yīng)用在智能家居、智慧城市、新出行等領(lǐng)域。
AliOS Things是阿里巴巴推出的物聯(lián)網(wǎng)設(shè)備端軟件框架,物聯(lián)網(wǎng)設(shè)備可以通過AliOS Things設(shè)備框架接入阿里云,使用云服務(wù)器提供的相關(guān)物聯(lián)網(wǎng)設(shè)備服務(wù)。
AliOS Things軟件框架是基于APACHE2.0協(xié)議的開源軟件,項(xiàng)目地址為:https://github.com/alibaba/AliOS-Things
AliOS Things軟件架構(gòu)可以從下到上分為四層,硬件和硬件抽象層、AOS操作系統(tǒng)層、應(yīng)用框架層和應(yīng)用層,下層組件為上層業(yè)務(wù)邏輯的實(shí)現(xiàn)提供支撐機(jī)制。
從底部到頂部,AliOS Things包括:
-
板級(jí)支持包(BSP):主要由SoC供應(yīng)商開發(fā)和維護(hù) -
硬件抽象層(HAL):比如WiFi和UART -
內(nèi)核:包括Rhino實(shí)時(shí)操作系統(tǒng)內(nèi)核、Yloop, VFS, KV 存儲(chǔ) -
協(xié)議棧:包括TCP/IP協(xié)議棧(LwIP),uMesh網(wǎng)絡(luò)協(xié)議棧 -
安全:安全傳輸層協(xié)議(TLS),可信服務(wù)框架(TFS)、可信運(yùn)行環(huán)境(TEE) -
AOS API:提供可供應(yīng)用軟件和中間件使用的API -
中間件:包括常見的物聯(lián)網(wǎng)組件和阿里巴巴增值服務(wù)中間件 -
示例應(yīng)用:阿里自主開發(fā)的示例代碼,以及通過了完備測(cè)試的應(yīng)用程序(比如Alinkapp) 所有的模組都已經(jīng)被組織成組件,且每個(gè)組件都有自己的.mk文件,用于描述它和其它組件間的依賴關(guān)系,方便應(yīng)用開發(fā)者按需選用。
我們一般只需要關(guān)心示例應(yīng)用部分,找一個(gè)跟自己的需求接近的示例,然后在其上進(jìn)行更改即可,我們使用的示例就是linkkitapp。
結(jié)構(gòu)框圖
目錄結(jié)構(gòu)
文件夾名稱 | 內(nèi)容描述 |
---|---|
3rdparty | 第三方庫(kù)相關(guān)功能代碼 |
app | 示例程序相關(guān)代碼 |
board | 評(píng)估板(如我們使用的ESP8266) |
build | 編譯框架 |
include | 系統(tǒng)頭文件 |
kernel | 包括Rhino和協(xié)議棧 |
Middleware | 阿里巴巴增值和常用的物聯(lián)網(wǎng)組件,包括Linkkit,OTA(安全差分升級(jí)),ulog(日志服務(wù)),uData(傳感器框架),uLocation(定位框架),WiFi配網(wǎng) 等 |
Network | 包括LwIP 輕量級(jí)TCP/IP協(xié)議棧,uMesh 自組網(wǎng)協(xié)議棧,BLE 低功耗藍(lán)牙協(xié)議棧,LoRaWAN 協(xié)議棧,AT Commands Module 等 |
osal | AOS API,提供可供應(yīng)用軟件和中間件使用的API |
out | 編譯輸出目錄 |
platform | 芯片架構(gòu)支持的相關(guān)文件;該目錄下包含了mcu與arch文件夾;mcu:該目錄主要存放廠商提供的芯片底層軟件庫(kù)代碼(如ESP8266庫(kù)),主要由SoC供應(yīng)商開發(fā)和維護(hù),以及二進(jìn)制文件,如系統(tǒng)啟動(dòng)、驅(qū)動(dòng)、編譯/鏈接腳本等。mcu下的目錄結(jié)構(gòu)按“廠商/芯片系列”進(jìn)行區(qū)分。arch:主要存放硬件體系架構(gòu)所需要的移植接口實(shí)現(xiàn)文件,如任務(wù)切換、啟動(dòng)、開關(guān)中斷等,硬件體系架構(gòu)如arm、xtensa…。 |
security | 包括TLS,TFS, TEE在內(nèi)的安全組件 |
utility | IoT通用軟件庫(kù),比如 cjson、libc等 |
為什么D5(GPIO14)是一鍵配網(wǎng)的引腳?
首先我們看一下,D5引腳在哪里?
官方介紹: WeMos D1 mini pins and diagram
https://escapequotes.net/esp8266-wemos-d1-mini-pins-and-diagram/
D5是WeMos D1 mini模塊的引腳,GPIO14是ESP8266的引腳,兩個(gè)標(biāo)識(shí)對(duì)應(yīng)的一個(gè)引腳。
那linkkitapp代碼中哪里對(duì)應(yīng)著一鍵配網(wǎng)的代碼呢?
程序入口在app_entry.c中的int application_start(int argc, char ** argv) 函數(shù)。
在application_start函數(shù)中有這樣一行:
從函數(shù)名上看,這是一個(gè)注冊(cè)事件過濾器的,過濾的目標(biāo)是按鍵點(diǎn)擊事件,并處理按鍵點(diǎn)擊事件的,“l(fā)inkkit按鍵處理”回調(diào)函數(shù)。
該函數(shù)的實(shí)現(xiàn)如下:
事件值為VALUE_KEY_CLICK將進(jìn)入awss配網(wǎng)模式;
事件值為VALUE_KEY_LTCLICK將進(jìn)行awss復(fù)位操作。
經(jīng)過定位排查,我們知道在 key_poll_func(void * arg) 函數(shù)中,實(shí)現(xiàn)了判斷按鍵(短按、長(zhǎng)按、長(zhǎng)長(zhǎng)按),然后分別向系統(tǒng)發(fā)出不同的按鍵事件aos_post_event()。
由上我們知道了AliOS定義的配網(wǎng)按鍵就是GPIO14,也就是mini D1 ESP8266模塊的D5腳。。
詳細(xì)請(qǐng)參考:ESP8266配網(wǎng)--key.c之按鍵事件分析
https://www.jianshu.com/p/fab0ea9e9ad3
ESP8266與主單片機(jī)之間的關(guān)系
STM32-->ESP8266-->阿里云物聯(lián)網(wǎng)平臺(tái)-->手機(jī)等終端
我們使用ESP8266模塊,只是把ESP8266當(dāng)做一個(gè)數(shù)據(jù)傳輸?shù)拿浇?,STM32與ESP8266模塊通過串口進(jìn)行通信。
STM32獲得外部傳感器的狀態(tài),然后通過串口發(fā)送狀態(tài)至ESP8266模塊。
經(jīng)ESP8266模塊內(nèi)部的AliOS Things對(duì)數(shù)據(jù)包進(jìn)行打包,然后將數(shù)據(jù)包通過WiFi網(wǎng)絡(luò)發(fā)送至阿里云物聯(lián)網(wǎng)平臺(tái)。
由于手機(jī)端與阿里云物聯(lián)網(wǎng)平臺(tái)保持著長(zhǎng)連接,所以阿里云物聯(lián)網(wǎng)平臺(tái)獲得到的傳感器數(shù)據(jù)能夠及時(shí)推送至手機(jī)端,進(jìn)而保持設(shè)備端的傳感器數(shù)據(jù)和手機(jī)端的數(shù)據(jù)保持一致性。
手機(jī)等終端-->阿里云物聯(lián)網(wǎng)平臺(tái)-->ESP8266-->STM32
反過來,通過手機(jī)端的云智能APP對(duì)設(shè)備進(jìn)行操作,首先會(huì)將操作設(shè)備的指令推送至阿里云物聯(lián)網(wǎng)平臺(tái),阿里云物聯(lián)網(wǎng)平臺(tái)會(huì)及時(shí)將指令推送至ESP8266模塊,ESP8266模塊會(huì)對(duì)收到的指令進(jìn)行數(shù)據(jù)轉(zhuǎn)發(fā),將指令通過串口傳輸給STM32。
由于阿里云物聯(lián)網(wǎng)平臺(tái)推薦數(shù)據(jù)格式為ICA標(biāo)準(zhǔn)數(shù)據(jù)格式(Alink JSON),STM32端需要對(duì)接收到的串口信息進(jìn)行解析,即對(duì)接收到的JSON字符串進(jìn)行解析,然后對(duì)解析后的結(jié)果進(jìn)行判斷,根據(jù)指令不同進(jìn)而做不同的動(dòng)作。
有人可能會(huì)說,ESP8266這個(gè)單片機(jī)性能這么好,不利用它浪費(fèi)了;
還有人會(huì)說對(duì)于智能風(fēng)扇這樣的簡(jiǎn)單應(yīng)用,只需要ESP8266作為主芯片即可,加上外圍電路,多省事多節(jié)約成本呀。
的確ESP8266性能很好,只是使用ESP8266的確夠用。那我們?yōu)槭裁催€要使用上面這種方式,額外浪費(fèi)一個(gè)STM32單片機(jī)呢?
這種方式最大的好處就是,降低物聯(lián)網(wǎng)模塊的使用門檻,為什么這么說呢?
上面的通信方式,只需要一個(gè)具有串口功能的單片機(jī)就可以與ESP8266配合使用,而一般的單片機(jī)都有1-2個(gè)以上的串口,所以條件很容易就滿足了。
這樣,我們只需要在你原有的設(shè)計(jì)方案的基礎(chǔ)上,額外占用一個(gè)串口,就可以在不改變整體電路設(shè)計(jì)的基礎(chǔ)上,添加物聯(lián)網(wǎng)功能。
而外圍單片機(jī)的選擇就很自由了,可以根據(jù)功能需要,選擇便宜的或者性能比ESP8266更優(yōu)的作為主單片機(jī)。
另外一點(diǎn),如果拿ESP8266作為主單片機(jī)的話,那么就要對(duì)ESP8266有比較深入的了解,這樣無疑增大了難度,當(dāng)某天需求改變或者ESP8266性能無法滿足的時(shí)候,我們更換了ESP8266的芯片,那么整體方案都要改,而且你還要重新熟悉一個(gè)新的物聯(lián)網(wǎng)芯片,學(xué)習(xí)成本太高了。
需要解決的問題
ESP8266 有兩個(gè)UART:UART0和UART1。
UART0有TX、RX,可以作為系統(tǒng)的打印信息輸出接口和數(shù)據(jù)收發(fā)口。
UART1的RX被Flash占用,只有發(fā)送引腳TX(GPIO2,即UART1_TXD)可供使用,所以一般作為打印信息輸出接口(調(diào)試用)。
通常情況下,我們使用UART0和外設(shè)通訊,而使用UART1作為日志打印端口。
D1 mini ESP8266模塊兩個(gè)串口的所在位置:
我們使用一個(gè)Micro USB線與D1 mini ESP8266模塊相連,使用串口會(huì)收到如下打印信息:
我們可以看到默認(rèn)的linkkitapp示例,Log信息是通過UART0發(fā)送出來的,而且里面有很多咱們不關(guān)心的信息,應(yīng)該將此部分信息進(jìn)行屏蔽。
所以我們需要做如下幾個(gè)工作:
-
將串口的比特率由921600修改為115200(此部分工作可不做); -
交換UART0和UART1,讓UART1輸出Log日志;UART0與STM32進(jìn)行通信; -
將STM32發(fā)上來的信息,通過UART0接收并發(fā)送到云端;將云端下發(fā)的有用的信息通過UART0轉(zhuǎn)發(fā)給STM32。
解決問題1. 串口的初始化api在platform\mcu\esp8266\bsp\driver\uart.c 中,目前的代碼是默認(rèn)如果不設(shè)置,uart0波特率是921600。但是一旦初始化了uart1,uart0的波特率會(huì)被改為和uart1一樣。
void
uart_init_new(uart_dev_t *uart)
{
UART_WaitTxFifoEmpty(UART0);
UART_WaitTxFifoEmpty(UART1);
if (uart == NULL)
{
return;
}
if (uart->port == 1)
{
//printf("port= 1\n ");
//uart1 setting
UART_ConfigTypeDef uart_config;
uart_config.baud_rate = uart->config.baud_rate;
uart_config.data_bits = UART_WordLength_8b;
uart_config.parity = USART_Parity_None;
uart_config.stop_bits = USART_StopBits_1;
uart_config.flow_ctrl = USART_HardwareFlowControl_None;
uart_config.UART_RxFlowThresh = 120;
uart_config.UART_InverseMask = UART_None_Inverse;
//UART_ParamConfig(UART0, &uart_config);
//uart2 setting for log
//uart_config.baud_rate = uart->config.baud_rate;
UART_ParamConfig(UART1, &uart_config);
UART_SetPrintPort(UART1);
//UART_intr_handler_register(uart0_rx_isr, NULL);
ETS_UART_INTR_ENABLE();
}
else
{
//printf("port= 0 \n ");
UART_ConfigTypeDef uart_config;
uart_config.baud_rate = uart->config.baud_rate;
// uart_config.baud_rate = BIT_RATE_921600;
uart_config.data_bits = UART_WordLength_8b;
uart_config.parity = USART_Parity_None;
uart_config.stop_bits = USART_StopBits_1;
uart_config.flow_ctrl = USART_HardwareFlowControl_None;
uart_config.UART_RxFlowThresh = 120;
uart_config.UART_InverseMask = UART_None_Inverse;
UART_ParamConfig(UART0, &uart_config);
UART_IntrConfTypeDef uart_intr;
uart_intr.UART_IntrEnMask = UART_RXFIFO_TOUT_INT_ENA | UART_FRM_ERR_INT_ENA | UART_RXFIFO_FULL_INT_ENA | UART_TXFIFO_EMPTY_INT_ENA;
uart_intr.UART_RX_FifoFullIntrThresh = 100;//10
uart_intr.UART_RX_TimeOutIntrThresh = 10;//2
uart_intr.UART_TX_FifoEmptyIntrThresh = 20;
UART_IntrConfig(UART0, &uart_intr);
UART_SetPrintPort(UART0);
UART_intr_handler_register(uart0_rx_isr, NULL);
ETS_UART_INTR_ENABLE();
}
}
解決問題2. 交換UART0和UART1:修改此文件:AliOS-Things\platform\mcu\esp8266\hal\uart.c
解決問題3.
-
下發(fā)有用信息:
-
上發(fā)有用信息:
模擬上傳屬性
經(jīng)過上面的改造之后,我們只需要向UART0發(fā)送JSON格式的數(shù)據(jù),即可修改服務(wù)器端的數(shù)值,比如串口助手中發(fā)送:
{"CurrentTemperature":26}
發(fā)送完畢,服務(wù)器端的當(dāng)前溫度值將會(huì)修改為26℃,在運(yùn)行狀態(tài)中可以實(shí)時(shí)看出來當(dāng)前溫度值是實(shí)時(shí)變化的。
模擬設(shè)置屬性
手機(jī)端APP點(diǎn)擊某個(gè)按鈕之后,將會(huì)將數(shù)據(jù)包發(fā)送至ESP8266,ESP8266將有用信息通過UART0的TX引腳發(fā)送給STM32,STM32將收到服務(wù)器端指令,對(duì)此指令進(jìn)行解析,進(jìn)而做相應(yīng)的動(dòng)作,具體邏輯類似下圖所示。
調(diào)試真實(shí)設(shè)備中,對(duì)電源開關(guān)設(shè)置為1,即{"PowerSwitch":1},在串口助手中我們收到指令{"PowerSwitch":1};
我們對(duì)電源開關(guān)設(shè)置為0,即{"PowerSwitch":0},可以看到串口助手中,收到對(duì)應(yīng)的指令{"PowerSwitch":0}。
STM32中我們使用cJSON對(duì)上面字符串進(jìn)行解析即可,然后做相應(yīng)的動(dòng)作,即完成了云端對(duì)設(shè)備的遠(yuǎn)程控制。
細(xì)心的人可能發(fā)現(xiàn)了,為什么我們用CurrentTemperature或者PowerSwitch來設(shè)置屬性呢?其實(shí)他們就是我們創(chuàng)建產(chǎn)品的時(shí)候,進(jìn)行功能定義的時(shí)候,設(shè)置的標(biāo)識(shí)符。
到此為止,本月的“智能風(fēng)扇”涉及到的知識(shí)點(diǎn)基本都已經(jīng)講過了,下一篇網(wǎng)文,就對(duì)此項(xiàng)目進(jìn)行最后的收尾,大家敬請(qǐng)期待哈。
三千多字的網(wǎng)文,一個(gè)字也舍不得刪了,喜歡的幫忙點(diǎn)個(gè)“在看”吧。
免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場(chǎng),如有問題,請(qǐng)聯(lián)系我們,謝謝!