五月天青色头像情侣网名,国产亚洲av片在线观看18女人,黑人巨茎大战俄罗斯美女,扒下她的小内裤打屁股

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

STM32MP157開發(fā)板Linux+Qt項目實戰(zhàn):智慧家庭---上

2023-02-03 15:10 作者:華清遠(yuǎn)見研發(fā)中心  | 我要投稿

stm32mp157開發(fā)板FS-MP1A是華清遠(yuǎn)見自主研發(fā)的一款高品質(zhì)、高性價比的Linux+單片機二合一的嵌入式教學(xué)級開發(fā)板。開發(fā)板搭載ST的STM32MP157高性能微處理器,集成2個Cortex-A7核和1個Cortex-M4 核,A7核上可以跑Linux操作系統(tǒng),M4核上可以跑FreeRTOS、RT-Thread等實時操作系統(tǒng)。開發(fā)板搭配仿真器、顯示屏、攝像頭、資源擴展板等豐富的擴展模塊,可拓展物聯(lián)網(wǎng)、人工智能等相關(guān)技術(shù)學(xué)習(xí),還可以拓展豐富的項目實戰(zhàn),非常貼合企業(yè)當(dāng)下開發(fā)需求,是一款嵌入式Linux入門進階必備開發(fā)板!?

可學(xué)習(xí)技術(shù):嵌入式Linux應(yīng)用/系統(tǒng)/驅(qū)動開發(fā)、ARM裸機開發(fā)、Qt界面編程、STM32單片機、FreeRTOS、人工智能機器視覺等。其中ARM Cortex-A7裸機開發(fā)課程是華清遠(yuǎn)見獨有特色課程,可關(guān)注:https://www.bilibili.com/video/BV1Xe4y1i7vm/,持續(xù)更新中。

可實戰(zhàn)項目:14個Linux+Qt綜合項目案例,8個MP1A物聯(lián)網(wǎng)拓展項目

關(guān)注公眾號“華清遠(yuǎn)見V智能有料”,回復(fù)“mp157項目”,索取項目配套文檔及源碼。?

1、Linux+Qt綜合項目案例:華清遠(yuǎn)見stm32mp157開發(fā)板優(yōu)勢特色部分,包括音樂播放器、智慧家庭、智能工業(yè)電表、智能出行助手、智能貓眼、環(huán)境監(jiān)測、智能安防、智能語音識別等10余個項目案例,涉及家居、醫(yī)療、農(nóng)業(yè)多種應(yīng)用方向,在案例中使用了多種物聯(lián)網(wǎng)和嵌入式技術(shù),包括OT開發(fā)、linux應(yīng)用開發(fā)、linux驅(qū)動開發(fā)、物聯(lián)網(wǎng)云端接入、MQTT協(xié)議、json字符串等知識點。

基于Linux+Qt的智慧家庭項目

項目簡介:

智慧家庭又可稱為智慧家庭服務(wù)平臺,是智慧城市的最小單元,是以家庭為載體,以家庭成員之間的親情為紐帶。智慧家庭綜合利用物聯(lián)網(wǎng)、云計算、移動互聯(lián)網(wǎng)和大數(shù)據(jù)等新一代信息技術(shù),結(jié)合自動控制技術(shù),將家庭設(shè)備智能控制、家庭環(huán)境感知、家人健康感知、家居安全感知以及信息交流、消費服務(wù)等家居生活有效地結(jié)合起來,創(chuàng)造出健康、安全、舒適、低碳、便捷、個性化和充滿關(guān)愛的家庭生活方式。

開發(fā)平臺:

華清遠(yuǎn)見stm32mp157開發(fā)板豪華套餐(開發(fā)板+仿真器+五寸屏+攝像頭+資源擴展板+tf卡+讀卡器)

項目功能展示:

Wifi 模塊

點擊刷新按鈕,可以實時更新附近的 wifi,選擇要連接的 wifi,會彈出輸入密碼的頁面,輸入密碼,點擊連接即可連接成功。

選擇要查看天氣的城市,點擊獲取按鈕

?環(huán)境監(jiān)測模塊

設(shè)備控制模塊

選擇按鈕即可完成設(shè)備的控制

開啟和關(guān)閉按鈕控制智能監(jiān)測的開啟和關(guān)閉,提交按鈕上的輸入框輸入的是智能監(jiān)測觸發(fā)的閾值。

?連接百度云模塊

輸入百度云連接三元組,點擊獲取時間戳,點擊計算、連接,即可實現(xiàn)向云端發(fā)送環(huán)境進而轉(zhuǎn)發(fā)到微信小程序,并且通過微信小程序控制設(shè)備。

在微信小程序顯示溫濕度。并且控制開發(fā)板 led 燈

遮擋光電開關(guān),會自動彈出門禁系統(tǒng)。

Qt開發(fā)環(huán)境搭建

主機開發(fā)環(huán)境說明

1) 本文檔主要介紹 linux 環(huán)境下的 Qt 程序開發(fā);

2) 主機 Qt 版本為 5.14.1;

主機 Qt 環(huán)境搭建及使用

Qt Creator 安裝

將 qt-creator-opensource-linux-x86_64-4.10.1.run(Qt 實驗源碼\工具軟件) 復(fù)制到 ubuntu 主機中,可以采用共享文件夾的方式也可以使用 tfp方式將文 件存入家目錄下的 Downloads 目錄。我們需要在終端中賦予安裝程序可執(zhí)行的權(quán)限

我們可以使用圖形化的文件管理器來查看

雙擊“qt-creator-opensource-linux-x86_64-4.10.1.run”圖標(biāo)運行安裝程序。

出現(xiàn)如下界面:

等待程序驗證完成后點擊“Next”

這里我們需要登錄或者注冊一個賬號,如果我們之前已經(jīng)注冊過直接登錄就可以。如果沒有注冊過則需要新注冊有一個賬號后登錄。這里筆者已經(jīng)注冊過賬號,所以直接登錄。

登錄成功后出現(xiàn)如下界面,點擊 Next

這里選擇安裝路徑

可以直接默認(rèn),Next

這路選擇安裝的組件,直接默認(rèn)即可

這里我們需要同意用戶協(xié)議

這個界面告訴我們安裝完成后需要占用的空間。點擊”Install”按鈕后開始安裝。

安裝完成后出現(xiàn)如下界面

點擊“Finish”按鈕后將彈出 Qt Creator 主界面

點擊“Cancel”按鈕后即可正常使用

?

Qt5.14.1 安裝

復(fù)制到 qt-opensource-linux-x64-5.14.1.run(Qt 實驗源碼\工具軟件)到 ubuntu 主機中,可以采用共享文件夾的方式也可以使用 tfp 方式將文件存入家目錄下的 Downloads 目錄。進入所在文件夾,先給執(zhí)行權(quán)限輸入命令

chmod +x ./qt-opensource-linux-x64-5.14.1.run

安裝在命令行輸入

./qt-opensource-linux-x64-5.14.1.run

會有可視化引導(dǎo)安裝,一直 next 就行了

在選擇安裝組件的時候要是不知道選擇那些就全選了 大概有 4 個 G 左右

下載 gcc 和 g++

sudo apt-get install gcc g++

下載 cmake

sudo apt-get install cmake

下載鏈接庫

sudo apt-get install libgl1-mesa-dev libglu1-mesa-dev

?

Qt Creator 配置

1)配置 GCC

運行 QtCreator 后,依次點擊"Tool"->"Options",出現(xiàn)選項對話框,在左側(cè)點擊"Kits",右 邊選擇"Compilers"標(biāo)簽。 檢查有沒有下圖標(biāo)注的 C++和 C ,一般按上面步驟執(zhí)行后都會有

點擊右側(cè)"Add"按鈕,彈出下拉列表后,選擇"GCC"的"C"

填寫信息如下,"Name"為"Auto-GCC","Compiler path"點擊旁邊的"Browse.."按鈕選擇編譯器的路徑,例子中的路徑是 “/usr/bin/gcc”

2)配置 G++

點擊右側(cè)"Add"按鈕,彈出下拉列表后,選擇"GCC"的"C++",下面的文本框填寫"Name" 為"Auto-G++","Compiler path"點擊旁邊的"Browse.."按鈕選擇編譯器的路徑,例子中的路徑是" /usr/bin/g++"。

填寫完成后,點擊"Apply"。

3)配置 qmake

選擇"Qt Versions"標(biāo)簽,如果有下面紅框中的文本,可以跳過下面步驟

如果沒有,在右側(cè)點擊"Add..."

會彈出 qmake 路徑選擇對話框,這里以"/home/linux/Qt5.14.1/5.14.1/gcc_64/bin/qmake"為例子。 選擇”qmake”文件后,擊"Open"按鈕

"Version name"改為" Qt %{Qt:Version} GCC"。然后點擊"Apply"按鈕。

4)配置 Kits

點擊左側(cè)"Kits",右側(cè)選擇"Kits"標(biāo)簽。檢查有沒有下圖紅框選中的文本,如果有可以跳過下面步驟

然后沒有,點擊 Add:

在彈出的對話框中"Name"為"Desktop","Device Type"選擇"Desktop"選項, "Sysroot"選擇目標(biāo)設(shè)備的系統(tǒng)目錄,"Compiler"選擇之前配置的名稱

"Auto-GCC"和"Auto-G++","Qt version"選擇之前配 置的名稱"Qt 5.14.1

GCC",其它默認(rèn)即可,最后點擊"Apply"和"OK"按鈕

?

?Qt Creator 新建工程

注意:工程路徑最好不要包含中文、特殊字符、空格等

我們可以新建一個“qt”文件夾,該文件夾用作我們以后存放源代碼。

打開 Qt Creator,在歡迎頁面點擊 “New”按鈕,來新建一個工程。

在出現(xiàn)的新建項目窗口中,我們選則“Application”->“Qt Widgets

Application”,然后點擊右下方“Choose…”按鈕,來創(chuàng)建一個桌面 Qt 應(yīng)用。

我們在這里設(shè)置項目介紹和源碼位置,我們這里創(chuàng)建一個名為

“HelloWorld”的示例項目,設(shè)置完成之后點擊 next

直接點擊 next

隨后進行細(xì)節(jié)設(shè)置,主要設(shè)置要創(chuàng)建的源碼文件的基本類信息,包括類名等。這里我們可以根據(jù)自己的項目特點進行設(shè)置。需要說明的一點就是基類的選擇,這里基類有 QMainWindow、QWidget、QDialog 三種,它們的不同之處如下:

? QMainWindow 類提供一個帶有菜單條,工具條和一個狀態(tài)條的主應(yīng)用程序窗口。主窗口通常提供一個大的中央窗口部件,以及周圍菜單,工具條,和一個狀態(tài)欄。QMainWindow 窗口經(jīng)常被繼承,使得封裝中央部件,菜單,工具條,狀態(tài)欄等都變得很容易,當(dāng)用戶點擊它的時候,相應(yīng)的槽就會被調(diào)用;

? QWidget 類是所有用戶界面對象的基類,窗口部件是用戶界面的一個基本單元,它從窗口系統(tǒng)接收鼠標(biāo),鍵盤和其他消息,并在屏幕上繪制自己。一個窗口部件可以被他的父窗口或者是其他窗口擋住一部分;

? QDialog 類是對話框窗口的基類,對話框窗口主要用于短期任務(wù)和用戶進行短期通訊的頂級窗口,QDialog 可以是模態(tài)對話框或者是非模態(tài)對話框。QDialog 支持?jǐn)U展并帶有返回值,他們可以帶有默認(rèn)值;我們在這里選擇 QDialog 類即可,點擊 next 完成類信息設(shè)置

直接點擊 next 按鈕即可。

然后進行工具選擇,該頁面可以選擇我們創(chuàng)建的工程可以使用的工具,選擇想要使用的編譯器模塊,例如下圖 。點擊 next

最后我們設(shè)置匯總信息,如果不需要版本控制等功能,直接點擊完成finish 即可

隨后我們就進入到了主界面,這時候 Qt 已經(jīng)幫我們做好了一些準(zhǔn)備工作,包括創(chuàng)建了一些文件,寫好了一些前置代碼等等。

我們可以點擊左邊 protect 欄,來查看我們的編譯選項

我們可以在左下角選擇編譯 Debug 版或者 Release 版,即調(diào)試版或發(fā)行版。

左下角綠色剪頭是編譯并運行,錘子是僅編譯,我們可以直接點擊綠色小箭頭將我們導(dǎo)入的工程編譯并運行起來。

點擊運行按鈕后,我們可以看到 HelloWorld 窗口運行起來了。

導(dǎo)入工程

我們可以將已存在的 Qt 程序項目直接打開,這里以上一章節(jié)的HelloWorld 程序為例。首先我們確定源碼存在的位置,如 HelloWorld 程序源碼在 /home/linux/qt/helloworld 路徑下。

點擊歡迎頁面的“Open” 按鈕可以打開已有的工程。

找到我們剛才解壓好的源碼,選擇“helloworld.pro”文件并點擊打開

接下來我們就可以進入到代碼編輯界面了。

左上角是項目欄,點擊項目名稱左邊的小箭頭可以展開項目目錄。

我們可以點擊左邊項目欄,來查看我們的編譯選項。需注意的是構(gòu)建設(shè)置中的路徑應(yīng)與工程路徑處于同級目錄下。

我們可以在左下角選擇編譯 Debug 版或者 Release 版,即調(diào)試版或發(fā)行版。

左下角綠色剪頭是編譯并運行,錘子是僅編譯,我們可以直接點擊綠色小箭頭將我們導(dǎo)入的工程編譯并運行起來。

點擊運行按鈕后,我們可以看到 HelloWorld 窗口運行起來了。

文件說明

通過上面兩個章節(jié),我們學(xué)習(xí)到了 Qt 程序的新建與導(dǎo)入的方法,也知道了Qt 會幫我們做一些基礎(chǔ)工作,比如幫我們建立了一些文件,那么這些文件都是干什么用的呢?我們以HelloWorld 程序來說明一下。

以“.pro”為后綴名的文件,為 Qt 的項目管理文件,存儲項目設(shè)置的文件;

“Qt += core gui”表示項目中加入 core gui 模塊。core gui 是 Qt 用于GUI 設(shè)計的類庫模塊,如果創(chuàng)建的是控制臺(console)應(yīng)用程序,就不需要添加 core gui。

Qt 類庫以模塊的形式組織各種功能的類,根據(jù)項目涉及的功能需求,在項目中添加適當(dāng)?shù)念悗炷K支持。例如,如果項目中使用到了涉及數(shù)據(jù)庫操作的類就需要用到 sql(數(shù)據(jù)庫)模塊,在 pro 文件中需要在后面加上 sql:

1 Qt += core gui sql

“greaterThan(QT_MAJOR_VERSION, 4): QT += widgets”,這是個條件執(zhí)行語句,表示當(dāng) Qt 主版本大于 4 時,才加入 widgets 模塊。

“TARGET = HelloWorld”表示生成的目標(biāo)可執(zhí)行文件的名稱,即編譯后生成的可執(zhí)行文件是 HelloWorld.exe。

“TEMPLATE = app”表示項目使用的模板是 app,是一般的應(yīng)用程序。

后面的 SOURCES、HEADERS、FORMS 記錄了項目中包含的源程序文件、頭文件和窗體文件(.ui 文件)的名稱。這些文件列表是 Qt Creator 自動添加到項目管理文件里面的,用戶不需要手動修改。當(dāng)添加一個文件到項目,或從項目里刪除一個文件時,項目管理文件里的條目會自動修改。

文件夾“Header”中,存放的是所設(shè)計的窗體類的頭文件;

文件夾“Sources”中,存放著源碼文件。main.cpp 是實現(xiàn) main()函數(shù)的程序文件,HelloWorld.cpp 是 widget.h 里定義類的實現(xiàn)文件。C++中,任何窗體或界面組件都是用類封裝的,一個類一般有一個頭文件(.h 文件)和一個源程序文件(.cpp 文件);

文件夾“Forms”中,存放著界面設(shè)計文件,“.ui”文件是一個 XML 格式存儲的窗體上的元件及其布局的文件,雙擊項目文件目錄樹中的文件 ui,會打開一個集成在 Qt Creator 中的 Qt Designer 對窗體進行可視化設(shè)計;

UI 設(shè)計器有以下一些功能區(qū)域:

組件面板:窗口左側(cè)是界面設(shè)計組件面板,分為多個組,如 Layouts、Buttons、Display Widgets 等,界面設(shè)計的常見組件都可以在組件面板里找到。

中間主要區(qū)域是待設(shè)計的窗體。如果要將某個組件放置到窗體上時,從組件面板上拖放一個組件到窗體上即可。

Signals 和 Slots 編輯器與 Action 編輯器是位于待設(shè)計窗體下方的兩個編輯器。Signals 和 Slots 編輯器用于可視化地進行信號與槽的關(guān)聯(lián),Action 編輯器用于可視化設(shè)計 Action。

布局和界面設(shè)計工具欄:窗口上方的一個工具欄,工具欄上的按鈕主要實現(xiàn)布局和界面設(shè)計。

對象瀏覽器(Object Inspector):窗口右上方是 Object Inspector,用樹狀視圖顯示窗體上各組件之間的布局包含關(guān)系,視圖有兩列,顯示每個組件的對象名稱(ObjectName)和類名稱。

屬性編輯器(Property Editor):窗口右下方是屬性編輯器,是界面設(shè)計時最常用到的編輯器。屬性編輯器顯示某個選中的組件或窗體的各種屬性及其取值,可以在屬性編輯器里修改這些屬性的值。屬性編輯器的內(nèi)容分為兩列,左側(cè)為屬性的名稱,右側(cè)為屬性的值。屬性又分為多個組,實際上表示了類的繼承關(guān)系,位于下方的類屬性組繼承自位于上方的類屬性組;如果我們需要新建資源文件、源碼文件等,可以在項目文件夾出點擊鼠標(biāo)右鍵,選擇 Add New;如果我們有新的文件需要添加,可以在項目文件夾出點擊鼠標(biāo)右鍵,選擇 Add Existing Files。

幫助文檔

Qt 的幫助文檔是伴隨我們學(xué)習(xí) Qt 開發(fā)的好伙伴。在 Qt 開發(fā)過程中,我們會面臨圖形接口使用的問題,它不像 C 語言那樣就那么幾個函數(shù)接口,圖形接口的接口數(shù)量可以用海量來形容,常用的我們可能能記住,其它的就沒有必要去記了,用到什么就去幫助文檔查看用法是比較方便的。我們可以按 F1 按鍵,或通過上方導(dǎo)航欄的“help->contects”來進入幫助文檔。

上方的前進后退按鈕方便我們查看文檔,如返回到上一步,返回到下一步。

我們可以通過幫助文檔來查看以下幾個部分:

類使用的相關(guān)介紹;

查看相關(guān)類的使用介紹,我們可以先進入到幫助文檔,然后在左上角選擇“Search”。筆者這里以 QWidget 類為例,輸入我們想要查找的類的名字,然后雙擊查找結(jié)果來查看說明

也可以先將鼠標(biāo)移動到想要查詢的類的位置,如圖所示,將鼠標(biāo)移動至“QWidget”處,然后按“F1”鍵,即可跳轉(zhuǎn)到相應(yīng)的幫助文檔

我們可以通過再按一次“F1”鍵來全窗口查看幫助文檔,按“Esc”鍵可以退出。

部分常用的成員元素包括以下幾項:

? 公有成員函數(shù):操作部件屬性的相關(guān)函數(shù);

? 公有槽函數(shù):Qt 類中已經(jīng)定義好的槽函數(shù),直接可與信號相連接;

? 信號:軟中斷,如按下按鈕觸發(fā) pressed() 信號等;

? 保護成員函數(shù):通常事件所對應(yīng)的虛函數(shù)放在此處;

? 事件:常用事件,如操作鼠標(biāo)觸發(fā)的鼠標(biāo)事件;

滾動鼠標(biāo)滾輪,向下即可看到“Qwdget Class”類的相關(guān)說明了。

1) 查看所用的部件的相應(yīng)成員函數(shù)。

我們可以查找到該類所用部件的相應(yīng)成員函數(shù)的使用方法、功能、參數(shù)、

返回值等等,我們以“按鈕”控件,即“QPushButton Class”類為例,我們通

過索引搜索的方式,來找到這個類

我們可以通過點擊“Public Functions” 來查看“QPushButton”這個類中的成員函數(shù)。

這里以“QPushButton(const QString &text, QWidget *parent =Q_NULLPTR)”為例,我們點擊函數(shù)名字可以進入到函數(shù)詳情中。我們可以看到相應(yīng)的描述為:以“text”為顯示內(nèi)容,以“parent”為父對象,構(gòu)造一個push 按鈕。“text”“parent”為函數(shù)參數(shù),由于是構(gòu)造函數(shù),所以此函數(shù)沒有返回值。

還有一些函數(shù)是繼承自其它類的,例如“Public Functions”中有 21 個繼承自“QAbstractButton”類的函數(shù),我們點擊“QAbstractButton”即可查看。

點擊“QAbstractButton”即可查看。

同樣我們可以點擊相應(yīng)的函數(shù)進入查看詳情。如查看“void setText(const QString &text)”。

2) 查看所用的部件的信號。

我們這里還是以“PushButton”為例,我們點擊“Public Slots”。

可以看到“PushButton”本身有一個“void showMenu()”的信號,并且有很多繼承自其他類的信號。

一般來說我們用的“PushButton”的信號,最多的是用到其繼承自基類“

QAbstractButton”中的幾個信號,分別是點擊(按下后抬起)、按壓(單按下)、釋放(單抬起)等。

我們可以點擊相應(yīng)信號查看詳情

3) 查看所用的部件的事件(所對應(yīng)的虛函數(shù)如何編寫)。部件常用事件主要在 “QWidget”中聲明,選擇“Events”即可查看相關(guān)說明。

每個事件都對應(yīng)著事件函數(shù)。

點擊事件函數(shù)可查看詳情

?

微信小程序開發(fā)環(huán)境搭建

微信小程序開發(fā)工具簡介

微信小程序是小程序中的一種,英文名 Wechat Mini Program,是一種不需要下載安裝即可使用的應(yīng)用,它實現(xiàn)了應(yīng)用“觸手可及”的夢想,用戶掃一掃或搜一下即可打開應(yīng)用。全面開放申請后,主體類型為企業(yè)、政府、媒體、其他組織或個人的開發(fā)者,均可申請注冊小程序。微信小程序、微信訂閱號、微信服務(wù)號、微信企業(yè)號是并行的體系。以下是小程序所涉及的技術(shù)概括:

? JSON

JSON(JavaScript Object Notation)是一種輕量級的數(shù)據(jù)交換格式。它是基于 ECMAScript(w3c 制定的 js 規(guī)范)的一個子集,采用完全獨立于編程語言的文本格式來存儲和表示數(shù)據(jù)。簡潔和清晰的層次結(jié)構(gòu)使得 JSON 成為理想的數(shù)據(jù)交換語言。易于人的閱讀和編寫,同時也易于機器解析和生成,并有效提升網(wǎng)絡(luò)傳輸效率。

? XML

XML(Extensible Markup Language),中文名為可擴展標(biāo)記語言,標(biāo)準(zhǔn)通用標(biāo)記語言的子集,是一種用于標(biāo)記電子文件使其具有結(jié)構(gòu)性的標(biāo)記語言。

? CSS

層疊樣式表(Cascading Style Sheets)是一種用來表現(xiàn) HTML(標(biāo)準(zhǔn)通用標(biāo)記語言的一個應(yīng)用)或 XML(標(biāo)準(zhǔn)通用標(biāo)記語言的一個子集)等文件樣式的計算機語言。CSS 不僅可以靜態(tài)的修飾網(wǎng)頁,還可以配合各種腳本語言動態(tài)的對網(wǎng)頁各元素進行格式化。

? JavaScript

JavaScript,是一種直譯式腳本語言,是一種動態(tài)類型、弱類型、基于原型的語言,內(nèi)置支持類型。它的解釋器被稱為 JavaScript 引擎,是瀏覽器的一部分,廣泛用于客戶端的腳本語言。

申請微信小程序

登錄微信公眾平臺,注冊賬號,選擇小程序。https://mp.weixin.qq.com/

按照步驟依次注冊,輸入郵箱,密碼,驗證碼等,同意協(xié)議進行注冊。

然后登錄自己的郵箱,查閱郵件,點擊鏈接進行激活。進入步驟 3,信息登記,按照網(wǎng)頁要求,依次輸入信息,身份信息,管理員微信信息,即可激活成功。

返回微信公眾平臺,輸入剛剛注冊的賬戶密碼,會需要用管理員微信掃碼登錄,登錄后,下載普通小程序開發(fā)者工具。

點擊開發(fā),選擇開發(fā)設(shè)置,獲取小程序 ID,以備后續(xù)開發(fā)需求。

微信小程序開發(fā)工具下載完成后,進行默認(rèn)安裝即可

創(chuàng)建新項目工程

打開微信小程序開發(fā)者工具,點擊創(chuàng)建新工程,填寫自己的 APPID,選擇默認(rèn)模板,語言選擇 JavaScript,點擊新建。

新建工程完成為如下界面:

基本環(huán)境配置

打開主界面的右上角的詳情按鈕,找到本地設(shè)置,將“增強編譯”和“不校驗合法域名”這兩個選項進行勾選,因為在小程序的開發(fā)階段,盡量把這兩勾選上。

編譯、調(diào)試

打開 app.json 文件,可以更改微信小程序的標(biāo)題,改為“工程 demo”。然后按下 Ctrl + S 快捷鍵進行保存,即可完成編譯,調(diào)試輸出。查看現(xiàn)象。

?

項目總體設(shè)計介紹

總體框架

智慧家庭系統(tǒng)的設(shè)計基于物聯(lián)網(wǎng)的思想,物聯(lián)網(wǎng)是新一代信息技術(shù)的重要組成部分,其英文名稱是“The Internet of things”。其基本思想是以互聯(lián)網(wǎng)為媒介,實現(xiàn)遠(yuǎn)程監(jiān)督、控制。它在各個領(lǐng)域有著非常廣泛的應(yīng)用。

總體框架如下:

該項目分為 WIFI 連接模塊、智能門禁模塊、數(shù)據(jù)采集模塊、智能檢測模塊、設(shè)備控制模塊、天氣預(yù)報模塊、與百度云交互模塊:下面具體介紹幾個模塊的功能。

WIFI 連接模塊

該模塊實現(xiàn)的原理是使用 wpa_supplicant 工具對無線網(wǎng)絡(luò)進行管理和控制的功能。wpa_supplicant 是一個開源項目,已經(jīng)被移植到 Linux,Windows 以及很多嵌入式系統(tǒng)上。它是 WPA 的應(yīng)用層認(rèn)證客戶端,負(fù)責(zé)完成認(rèn)證相關(guān)的登錄、加密等工作。

wpa_supplicant 工具包含 wpa_supplicant 和 wpa_cli 這 2 個程序,其中wpa_supplicant 程序作為服務(wù)端在后臺運行,服務(wù) wpa_cli 客戶端的請求,從而實現(xiàn) WiFi 的配置連接。下面是通過 shell 命令去進行 WIFI 的配置及連接。

1.打開 wlan0 接口:

root@fsmp1c:~# ifconfig wlan0 up

2.啟動 wpa_supplicant 進程并在后臺運行

root@fsmp1c:~# wpa_supplicant -D nl80211 -i wlan0 -c /etc/wpa_supplicant.conf-B

3.掃描周邊 WiFi 熱點:

wpa_cli -i wlan0 scan

4.查看掃描結(jié)果:

root@fsmp1c:~# wpa_cli -i wlan0 scan_results

5.添加一個網(wǎng)絡(luò)連接

root@fsmp1c:~# wpa_cli -i wlan0 add_network

6.配置 WiFi 熱點的名稱 ssid:

root@fsmp1c:~# wpa_cli -i wlan0 set_network 1 ssid '"FARSIGHT"'

7.配置 WiFi 熱點的密碼 psk:

root@fsmp1c:~# wpa_cli -i wlan0 set_network 1 psk '"fs123456"'

8.列舉所有保存的連接

root@fsmp1c:~# wpa_cli -i wlan0 list_network

9.連接第 1 個保存的連接

root@fsmp1c:~# wpa_cli -i wlan0 select_network 1

10.啟動 wpa_supplicant 應(yīng)用

root@fsmp1c:~#wpa_supplicant -B -c wifi.conf -i wlan0

11.使用 udhcpc 命令動態(tài)獲取 IP

root@fsmp1c:~#udhcpc -i wlan0

?

智能門禁模塊

該模塊是根據(jù)關(guān)電開關(guān)智能識別有沒有人來,當(dāng)有人觸發(fā)光電開關(guān),會自動彈出登陸界面,輸入用戶名和密碼,程序會自動匹配數(shù)據(jù)庫,如果用戶名密碼錯誤超過三次,會自動報警;如果輸入正確,則開門。

數(shù)據(jù)采集模塊

另開一個線程,實時去讀取溫濕度驅(qū)動設(shè)備文件的數(shù)據(jù),進行計算得出溫濕度的數(shù)值同樣的方式得到光照的數(shù)值,通過信號傳參的方式傳給主線程,將數(shù)據(jù)設(shè)置到 ui 界面上。

智能檢測模塊

開啟智能檢測后,程序會根據(jù)你設(shè)定的閾值進行檢測,假如溫度超過你設(shè)定的溫度閾值,會自動開啟風(fēng)扇;或者當(dāng)光照低于你設(shè)定的閾值,會開燈提高照明的亮度。

設(shè)備控制模塊

通過 ui 界面的按鍵去開關(guān)燈或者風(fēng)扇,以及蜂鳴器。

天氣預(yù)報模塊

連接 WIFI 之后,通過 get 方法從網(wǎng)上獲取信息,得到 Json 類型的數(shù)據(jù),對這個數(shù)據(jù)進行解析,將解析到的數(shù)據(jù)設(shè)置到 ui 界面上面。

百度云交互模塊

在 ui 界面輸入在百度云創(chuàng)建設(shè)備時的 IoTCoreld、DeviceKey、DeviceSecret(三元組)通過組合生成 addr 和用戶名,使用 MD5 加密算法計算得到密碼,用于連接,連接成功后開啟定時器,自動向指定好的 topic 發(fā)布采集到的溫度濕度和光照,并且訂閱云端控制設(shè)備的 topic,用戶向云端發(fā)布json 數(shù)據(jù),開發(fā)板接收到云端轉(zhuǎn)發(fā)的 json 數(shù)據(jù)會做出響應(yīng)。如{“l(fā)ed1”,1},開發(fā)板收到數(shù)據(jù)后 led1 會亮

源碼分析

WIFI 連接模塊

在 Qt 程序里使用 system 函數(shù)來執(zhí)行 5.2 的命令來實現(xiàn) WIFI 的配置

建立刷新按鈕信號槽連接,實現(xiàn)點擊刷新按鈕界面顯示附近 wifi。實現(xiàn)原理是啟動 wpa_supplicant 進程并在后臺運行,掃描周邊 WiFi 熱點;

使用wpa_cli -i wlan0 scan_results 命令查看掃描結(jié)果,并將掃描結(jié)果重定向到wifilist 文件中,對 wifilist 文件進行讀操作,將讀到的數(shù)據(jù)直接顯示到 ui界面上面。核心代碼如下

……

system("wpa_supplicant -D nl80211 -i wlan0 -c /etc/wpa_supplicant.conf -

B");

?system("wpa_cli -i wlan0 scan");

?system("wpa_cli -i wlan0 scan_results > ./wifilist");

?usleep(50000);

?QString fileName = "./wifilist";

?QFile file(fileName);

?int f = 0;

?j = 0;

?if(!file.open(QIODevice::ReadOnly | QIODevice::Text))

?{

?QMessageBox::warning(this,"Warnning","can't

open",QMessageBox::Yes);

?}

?QTextStream in(&file);

?QString str;

?while (!((str = in.readLine()).isEmpty ()))

……

選中刷新后顯示的 wifi 名后,點擊連接會進入二級界面。二級界面輸入密碼正確后點擊連接,等待幾 s 后即可完成連接。這里輸入框使用自定義類MylineEdit,繼承自 QlineEdit,增加了鼠標(biāo)點擊事件,當(dāng)觸摸屏點擊輸入框的時候,會彈出軟鍵盤,用來輸入密碼

這里連接 wifi 的核心代碼如下:

……

sprintf(set_ssid,"wpa_cli -i wlan0 set_network %d ssid

'\"%s\"'",i,wifiName.toLatin1().data());

?sprintf(set_password, "wpa_cli -i wlan0 set_network %d psk '\"%s\"' >

TorF.ini",i,password_edit->text().toLatin1().data());

sprintf(select_wlan, "wpa_cli -i wlan0 select_network %d ",i);

?system(set_ssid);

?system(set_password);

?system("wpa_cli -i wlan0 list_network");

?system(select_wlan);

?system("wpa_supplicant -B -c wifi.conf -i wlan0");

?qDebug()<< get_TorF().data()->toUpper();

?if(get_TorF().data()->toUpper()=="F")

?{

?QMessageBox::warning(this,tr("Connect information"), tr("密碼

錯誤"));

?return ;

?}

?system("udhcpc -i wlan0 -B");

?char echo_1[64];

?char echo_2[64];

?sprintf(echo_1,"echo \"nameserver 114.114.114.114\" >

/etc/resolv.conf");

?system(echo_1);

?sprintf(echo_2,"echo \"nameserver 8.8.8.8\" > /etc/resolv.conf");

?system(echo_2);

?close();

?QMessageBox::information(this,tr("Connect information"), tr("連接成

功"));

?}

……

?

智能門禁模塊

PanGu 開發(fā)板有多個 GPIO 組,查看 GPIO 組信息,可以使用 gpiodetect 命令。

# gpiodetect

gpiochip0 [GPIOA] (16 lines)

gpiochip1 [GPIOB] (16 lines)

gpiochip10 [GPIOK] (16 lines)

gpiochip11 [GPIOZ] (16 lines)

gpiochip2 [GPIOC] (16 lines)

gpiochip3 [GPIOD] (16 lines)

gpiochip4 [GPIOE] (16 lines)

gpiochip5 [GPIOF] (16 lines)

gpiochip6 [GPIOG] (16 lines)

gpiochip7 [GPIOH] (16 lines)

gpiochip8 [GPIOI] (16 lines)

gpiochip9 [GPIOJ] (16 lines)

通過查擴展板的原理圖可以看到 :光電開關(guān)的 GPIO 管腳是 PE15

讀取 PE15 的狀態(tài)

# gpioget gpiochip4 15

當(dāng)有東西遮擋光電開關(guān)時,執(zhí)行以上命令得到的是 0;沒有東西遮擋。得

到的是 1.

所以我們開一個線程讓它一直去讀取光 PE15 的狀態(tài),當(dāng)讀到為 0 時,說明

有人,發(fā)送信號給主線程,使主線程開啟登陸界面。

void ReadPE15Thread::run()

{

?system("touch pe15.txt");

?system("gpioget gpiochip4 15 > pe15.txt");

?int fd;

?char buf[32];

?while (1) {

?fd = open("./pe15.txt",O_RDONLY);

?system("gpioget gpiochip4 15 > pe15.txt");

?read(fd,buf,sizeof(buf));

?if(strcmp(buf,"1\n")==0)

?{

?qDebug()<<tr("login !!");

?emit pesig();

?}

?sleep(1);

?close(fd);

?}

}

建立信號槽連接

void MainWindow::loginSlot()

{

?disconnect(&pe15thread,SIGNAL(pesig()),this,SLOT(loginSlot()));

?login->show();

?connect(login,SIGNAL(loginsuccess()),this,SLOT(loginsuccessSlot()));

?connect(login,SIGNAL(loginfailed()),this,SLOT(loginfailedSlot()));

?connect(login,SIGNAL(loginclose()),this,SLOT(logincloseSlot()));

}

登陸界面的編寫

編譯 UI 界面。

創(chuàng)建 usr.db 數(shù)據(jù)庫文件

# sqlit3 usr.db

創(chuàng)建表

sqlite> CREATE TABLE usr(

?

?usrname TEXT PRIMARY KEY ,

?password NOT NULL

);

向數(shù)據(jù)庫中添加用戶名和密碼

sqlite> INSERT INTO usr values(“usr”,“123”);

login.cpp

打開數(shù)據(jù)庫 驗證密碼

bool Login::openDb()

{

?QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");

?db.setDatabaseName("usr.db");

?if(!db.open())

?{

?QMessageBox::warning(0, tr("Warning"), db.lastError().text());

?return false;

?}

?QSqlQuery query(db);

?if(!query.exec("select usrname,password from usr"))

?{

?db.close();

?return false;

?}

while(query.next())

?{

?QString UserName = query.value(0).toString();

?QString Password = query.value(1).toString();

// qDebug()<< UserName;

// qDebug()<< Password;

?if(UserName == usr_edit->text() &&Password ==password_edit->text())

?return true;

?}

?db.close();

?return false;

}

登陸成功發(fā)送成功信號,登陸失敗發(fā)送失敗信號

void MainWindow::loginSlot()

{

?disconnect(&pe15thread,SIGNAL(pesig()),this,SLOT(loginSlot()));

?login->show();

?connect(login,SIGNAL(loginsuccess()),this,SLOT(loginsuccessSlot()));

?connect(login,SIGNAL(loginfailed()),this,SLOT(loginfailedSlot()));

?connect(login,SIGNAL(loginclose()),this,SLOT(logincloseSlot()));

}

void MainWindow::loginsuccessSlot()

{

?QMessageBox::information(this, tr("information"),"密碼正確,門鎖已打開");

// 重置錯誤次數(shù)

?Numberoferrors =3;

?login->close();

?beepunring();

connect(&pe15thread,SIGNAL(pesig()),this,SLOT(loginSlot()));

}

void MainWindow::loginfailedSlot()

{

?QString info;

?Numberoferrors--;

?switch(Numberoferrors)

?{

?case 2:

?info ="密碼錯誤,還有 3 次機會";

?break;

?case 1:

?info ="密碼錯誤,還有 2 次機會";

?break;

?case 0:

?info ="密碼錯誤,還有 1 次機會";

?break;

?default:

?info ="即將報警";

?break;

?}

?QMessageBox::warning(this, tr("warning"),info);

?if(Numberoferrors <0)

?{

qDebug() << Numberoferrors;

?beepring();

?}

}

驗證密碼錯誤三次后蜂鳴器報警

?

數(shù)據(jù)采集和智能檢測模塊

系統(tǒng)啟動后可以查看目錄/sys/bus/iio/devices/

root@fsmp1c:~# ls /sys/bus/iio/devices/ iio:device0

如果系統(tǒng)中有多個 iio 設(shè)備,這里可能會有很多個 iio 目錄,確定哪個

目錄是我們的設(shè)備對應(yīng)目錄,可以通過查看

/sys/bus/iio/devices/iio\:device0/name 信息確認(rèn):

root@fsmp1c:~# cat /sys/bus/iio/devices/iio\:device0/name

0-0040

由顯示信息每個驅(qū)動對應(yīng)設(shè)備可能有所不同,當(dāng)前顯示內(nèi)容為設(shè)備的物理

地址,與設(shè)備樹中地址一致,可以確認(rèn) iio:device0 是當(dāng)前設(shè)備對應(yīng)目錄查看

當(dāng)目錄下內(nèi)容:

root@fsmp1c:~# ls -l /sys/bus/iio/devices/iio\:device0/

total 0

-r--r--r-- 1 root root 4096 Feb 7 15:51 dev

-rw-r--r-- 1 root root 4096 Feb 7 15:51 in_humidityrelative_offset

-rw-r--r-- 1 root root 4096 Feb 7 15:51 in_humidityrelative_raw

-rw-r--r-- 1 root root 4096 Feb 7 15:51 in_humidityrelative_scale

-rw-r--r-- 1 root root 4096 Feb 7 15:51 in_temp_offset

-rw-r--r-- 1 root root 4096 Feb 7 15:51 in_temp_raw

-rw-r--r-- 1 root root 4096 Feb 7 15:51 in_temp_scale

-r--r--r-- 1 root root 4096 Feb 7 15:51 name

drwxr-xr-x 2 root root 0 Feb 7 15:51 power

lrwxrwxrwx 1 root root 0 Feb 7 15:50 subsystem -> ../../../../../../../bus/iio

-rw-r--r-- 1 root root 4096 Feb 7 15:50 uevent

文件說明:

文件 in_ temp_scale 為溫度標(biāo)尺,計算公式如下,公式來自與驅(qū)動對應(yīng)代碼:

?????????????????? =

175.72 × 1000 × 4

65535 = 10.725097656

in_ temp_offset 為數(shù)據(jù)偏移,計算公式如下,公式來自于驅(qū)動對應(yīng)代碼

???????????????????? =

?46.85 × 65536

4 × 175.72 = ?4368

in_ temp_raw 為原始數(shù)據(jù),計算公式如下,公式來自于驅(qū)動對應(yīng)代碼:

?????????????? =

????????????????

4

閱讀 SI7006 芯片手冊可以看到溫度的計算公式為:

??????????????????????(℃) =

175.72 × ????????????????

65535 ? 46.85

上述公式與驅(qū)動返回值看不出直接對應(yīng)關(guān)系,所以我們按照驅(qū)動提供的 scale、

offset 及 Raw 的計算公式對公式進行處理,得到最終公式計算過程如下:

??????????????????????(℃) × 65536 = 175.72 × ???????????????? ? 46.85 × 65536

??????????????????????(℃) × 65536 = 175.72 × (????????????????+

?46.85 × 65536

175.72 )

??????????????????????(℃) =

175.72

65536 × (????????????????+

?46.85 × 65536

175.72 )

??????????????????????(℃) =

175.72 × 1000

65536 × (????????????????+

?46.85 × 65536

175.72 ) ÷ 1000

??????????????????????(℃) =

175.72 × 1000 × 4

65536 × (

????????????????

4

?46.85 × 65536

175.72 × 4

) ÷ 1000

最終確定溫度的計算公式為:

??????????????????????(℃) = (?????????????? + ????????????????????) × ?????????????????? ÷ 1000

同理濕度的計算公式為:

????????????????(%????) = (??????????? + ?????????????????) × ??????????????? ÷ 1000

主要代碼如下:

開一個線程去讀取設(shè)備文件的信息并計算,得到溫度濕度光照,通過信號傳參的方式

傳給主線程。

子線程:

……

void CollentdataThread::run()

{

?int temp_raw = 0;

?int temp_offset = 0;

?float temp_scale = 0;

?int hum_raw = 0;

?int hum_offset = 0;

?float hum_scale = 0;

?float tem_float =0;

?float hum_float =0;

?float ill_float =0;

?QString hum;

?QString tem;

?QString ill;

?const char *device1 ="iio:device0";//溫濕度

?const char *device2 ="iio:device1";//光照

?while (1)

?{

/*read temp data*/

?read_sysfs_int(device1, "in_temp_raw", &temp_raw);

?read_sysfs_int(device1, "in_temp_offset", &temp_offset);

?read_sysfs_float(device1, "in_temp_scale", &temp_scale);

?tem_float =(temp_raw + temp_offset) * temp_scale / 1000;

?tem =QString::number(tem_float,'f', 2);

?read_sysfs_int(device1, "in_humidityrelative_raw", &hum_raw);

?read_sysfs_int(device1, "in_humidityrelative_offset", &hum_offset);

?read_sysfs_float(device1, "in_humidityrelative_scale", &hum_scale);

?hum_float = (hum_raw + hum_offset) * hum_scale / 1000;

?hum =QString::number(hum_float,'f', 2);

?read_sysfs_float(device2, "in_illuminance_input", &ill_float);

?ill =QString::number(ill_float,'f', 2);

?emit send(tem,hum,ill);

?sleep(2);

?}

}

int CollentdataThread::read_sysfs_float(const char *device, const char *filename, float

*val)

{

?int ret = 0;

?FILE *sysfsfp;

?char temp[128];

?memset(temp, '0', 128);

?ret = sprintf(temp, "/sys/bus/iio/devices/%s/%s", device, filename);

?if (ret < 0)

?goto error;

?sysfsfp = fopen(temp, "r");

?if (!sysfsfp)

{

?ret = -errno;

?goto error;

?}

?errno = 0;

?if (fscanf(sysfsfp, "%f\n", val) != 1)

?{

?ret = errno ? -errno : -ENODATA;

?if (fclose(sysfsfp))

?perror("read_sysfs_float(): Failed to close dir");

?goto error;

?}

?if (fclose(sysfsfp))

?ret = -errno;

error:

?return ret;

}

int CollentdataThread::read_sysfs_int(const char *device, const char *filename, int *val)

{

?int ret = 0;

?FILE *sysfsfp;

?char temp[128];

?memset(temp, '0', 128);

?ret = sprintf(temp, "/sys/bus/iio/devices/%s/%s", device, filename);

?if (ret < 0)

?goto error;

?sysfsfp = fopen(temp, "r");

?if (!sysfsfp)

?{

ret = -errno;

?goto error;

?}

?errno = 0;

?if (fscanf(sysfsfp, "%d\n", val) != 1)

?{

?ret = errno ? -errno : -ENODATA;

?if (fclose(sysfsfp))

?perror("read_sysfs_float(): Failed to close dir");

?goto error;

?}

?if (fclose(sysfsfp))

?ret = -errno;

error:

return ret;

}

主線程:

信號槽連接

connect(&thread_collentdata,SIGNAL(send(QString,QString,QString)),this,SLOT(set_

humAdte

mAdill(QString,QString,QString)));

槽函數(shù):

void MainWindow::set_humAdtemAdill(QString tem,QString hum,QString ill)

{

?// 將線程采集的數(shù)據(jù)賦值給成員變量

?this->tem =tem;

this->hum =hum;

?this->ill =ill;

/************** 異常處理 ********/

if(abnormalSwitch == true)

{

?if(this->tem.toFloat() >tem_max.toFloat())

?{

?system("echo 255 > /sys/class/hwmon/hwmon1/pwm1");

?}

?else

?system("echo 0 > /sys/class/hwmon/hwmon1/pwm1");

?if(this->ill.toFloat() < ill_lv1.toFloat()&&this->ill.toFloat() > ill_lv2.toFloat())

?{

?system("echo 1 > /sys/class/leds/led1/brightness");

?}

?else if(this->ill.toFloat() < ill_lv2.toFloat()&&this->ill.toFloat() > ill_lv3.toFloat())

?{

?system("echo 1 > /sys/class/leds/led1/brightness");

?system("echo 1 > /sys/class/leds/led2/brightness");

?}

?else if(this->ill.toFloat() < ill_lv3.toFloat())

?{

?system("echo 1 > /sys/class/leds/led1/brightness");

?system("echo 1 > /sys/class/leds/led2/brightness");

?system("echo 1 > /sys/class/leds/led3/brightness");

?}

?else

?{

system("echo 0 > /sys/class/leds/led1/brightness");

?system("echo 0 > /sys/class/leds/led2/brightness");

?system("echo 0 > /sys/class/leds/led3/brightness");

?}

}

else

{

?

/*************************************************************************/

?tem.append("℃");

?hum.append("%");

?ill.append("Candela");

?ui->illTextBrowser->setText(ill);

?ui->humTextBrowser_2->setText(hum);

?ui->temTextBrowser_2->setText(tem);

}

}

//開啟/關(guān)閉智能檢測

void MainWindow::abn_pushbutton_ONSlot()

{

?abnormalSwitch = true;

?QMessageBox::information(this, tr("information"),"開啟智能檢測成功");

}

void MainWindow::abn_pushbutton_OFFSlot()

{

?abnormalSwitch =false;

QMessageBox::information(this, tr("information"),"關(guān)閉智能檢測成功");

}

其中 abnormalSwitch 這個變量是全局變量,通過兩個按鈕來改變這個變量的值,如果關(guān)

閉按鈕點擊這個值變成 false

If 語句就不會執(zhí)行。直接將信息顯示到 ui 界面

?

設(shè)備控制模塊

這個模塊很簡單,直接上命令。

Led1 亮/滅

Led2 亮/滅

Led3 亮/滅

root@fsmp1c:~# echo 1 > /sys/class/leds/user1/brightness

root@fsmp1c:~# echo 0 > /sys/class/leds/ user1/brightness

root@fsmp1c:~# echo 1> /sys/class/leds/ user2/brightness

root@fsmp1c:~# echo 0 > /sys/class/leds/ user2/brightness

root@fsmp1c:~# echo 1 > /sys/class/leds/ user3/brightness

root@fsmp1c:~# echo 0 > /sys/class/leds/ user3/brightness

蜂鳴器響

void MainWindow::beepring()

{

int fd;

?struct input_event event;

?struct timeval time;

?fd = open("/dev/input/by-path/platform-beeper-event", O_RDWR);

?event.type = EV_SND;

?event.code = SND_TONE;

?event.value = 1000;

?time.tv_sec = 1;

?time.tv_usec = 0;

?event.time = time;

?write(fd, &event, sizeof(struct input_event));

}

讓蜂鳴器關(guān)的話把 event.value 的值置成 0,將結(jié)構(gòu)體對象再寫到

/dev/input/by-path/platform-beeper-event 文件里

天氣預(yù)報模塊

使用 QNetworkAccessManager 類定義一個請求句柄;使用 QNetworkRequest 類

定義一個操作請求。

QNetworkAccessManager *manager;

QNetworkRequest quest;

QNetworkAccessManager 是用來協(xié)調(diào)網(wǎng)絡(luò)操作的,即用來操作 QNetworkRequest

請求的 。QNetworkRequest 是 Network Access API 的一部分,是在網(wǎng)絡(luò)上保

存著發(fā)送一個請求的必要信息.它包含一個 URL 和一些輔助信息,可以被用來去

修改請求。打個比方: 你想要帶一些水給朋友,這個水就好比

QNetWorkRequest 你的請求,而裝水的容器就是 QNetworkAccessManager.。有

了容器你才可以帶走水,同理你想要發(fā)送請求就需要

QNetworkAccessManager。

這里,在 ui 界面的 comboBox 選擇要查看的城市,填充到 QnetWorkRequest

里,使用 get 方法發(fā)送請求。

/*********************** 天氣模塊 *********************/

//點擊查詢請求天氣數(shù)據(jù)

void MainWindow::weather_cilcked_Slot()

{

?QString local_city = ui->comboBox->currentText().trimmed(); //獲得需要查詢

天氣的城市名稱

?sendQuest(local_city);

}

//get 方法獲取信息

void MainWindow::sendQuest(QString cityStr)

{

?char quest_array[256] = "http://wthrcdn.etouch.cn/weather_mini?city=";

?QNetworkRequest quest;

?sprintf(quest_array, "%s%s", quest_array, cityStr.toUtf8().data());

?quest.setUrl(QUrl(quest_array));

?quest.setHeader(QNetworkRequest::UserAgentHeader, "RT-Thread ART");

?manager->get(quest); /*發(fā)送 get 網(wǎng)絡(luò)請求*/

}

建立信號槽連接

?connect(manager, SIGNAL(finished(QNetworkReply*)), this,

SLOT(replyFinished(QNetworkReply*)));

?

當(dāng)發(fā)送請求后,會收到網(wǎng)絡(luò)的回復(fù)信號,只需要使用 QJsonDocument 解析 Json

類型的數(shù)據(jù)就好了。具體代碼如下。

//天氣數(shù)據(jù)處理槽函數(shù)

void MainWindow::replyFinished(QNetworkReply *reply)

{

?QString all = reply->readAll();

QJsonParseError err;

//解析 json 對象

QJsonDocument json_recv = QJsonDocument::fromJson(all.toUtf8(), &err);

?qDebug() << "recv weather data! error:"<< err.error;

?if (!json_recv.isNull())

?{

?QJsonObject object = json_recv.object();

?if (object.contains("data"))

?{

?QJsonValue value = object.value("data"); // 獲取指定 key 對應(yīng)的 value

?if (value.isObject())

?{

?QJsonObject object_data = value.toObject();

?if (object_data.contains("forecast"))

?{

?QJsonValue value = object_data.value("forecast");

?if (value.isArray())

?{

?QJsonObject today_weather = value.toArray().at(0).toObject();

?QString weather_type = today_weather.value("type").toString();

?QString tuijian = object.value("data").toObject().value("ganmao").toString();

?QString low = today_weather.value("low").toString();

?QString high = today_weather.value("high").toString();

?QString wendu = low.mid(low.length() - 4, 4) + "~" + high.mid(high.length()

- 4, 4);

?QString strength = today_weather.value("fengli").toString();

?strength.remove(0, 8);

?strength.remove(strength.length() - 2, 2);

?QString fengli = today_weather.value("fengxiang").toString() + strength;

?ui->label_weather_2->setText(weather_type); //顯示天氣類型

ui->label_temperature_2->setText(wendu);

?ui->label_wind_2->setText(fengli);

?ui->label_recommend_2->setText(tuijian);

?}

?}

?}

?}

?}

?else

?ui->label_recommend_2->setText( "json_recv is NULL or is not a object !");

?reply->deleteLater(); //銷毀請求對象

}

?

百度云交互模塊

通過 ui 界面輸入建立云端設(shè)備時生成的 ioTcoreid、DeviceKety、DeviceSecret。使用代碼進行組合生成 brokerAddr、以及用戶名密碼,再使用

MD5 加密算法對密碼進行加密得到連接需要的信息。點擊計算按鈕就將計算的結(jié)果復(fù)制給成員變量,便于連接時使用。

void MainWindow::pushButton_calculateSlot()

{

?username.clear();

?password.clear();

?password_md5.clear();

?brokerAddr.clear();

?ioTCoreld = lineEdit_coreid->text();

?deviceKey = lineEdit_devkey->text();

?deviceSecret = lineEdit_devsecret->text();

?brokerPort = "1883";

?if(ui->comboBox_city->currentText() =="廣州")

?brokerAddr =

brokerAddr.append(ioTCoreld).append(".iot.").append("gz").append(".baidubce.com"

);

?else

?brokerAddr =

brokerAddr.append(ioTCoreld).append(".iot.").append("bj").append(".baidubce.com");

?clientId = "zhjt123";

?username =

username.append("thingidp").append("@").append(ioTCoreld).append("|").append(de

viceKey)\

?.append("|").append(currentTimestamp).append("|").append("MD5");

?password =

password.append(deviceKey).append("&").append(currentTimestamp).append("&").a

ppend("MD5")\

?.append(deviceSecret);

?QByteArray password_md5result;

?QCryptographicHash md(QCryptographicHash::Md5);

?md.addData(password.toUtf8());

?password_md5result = md.result();

password_md5.append(password_md5result.toHex());

}

在 pro 文件里加入

QT += mqtt

然后在 mainwindow.h 加入頭文件

#include <QtMqtt/qmqttclient.h>

使用 QmqttClient 定義 m_client 對象用于連接。

QMqttClient *m_client;//mqtt client 指針

將上一步計算好的信息設(shè)置到 m_client 對象中,使用

m_client->connectToHost();

進行連接。

void MainWindow::pushButton_connectmqttSlot()

{

?//未連接服務(wù)器則連接

?if (m_client->state() == QMqttClient::Disconnected) {

?ui->pushButton_connectmqtt->setText(tr("斷開"));

?m_client->setHostname(brokerAddr);

?m_client->setPort(brokerPort.toInt());

?m_client->setUsername(username);

?m_client->setPassword(password_md5);

?m_client->connectToHost();

?// 定時器初始化

?InitTimer();

?connect(m_client,SIGNAL(connected()),this,SLOT(mqttconnectSlot()));

?connect(m_client, SIGNAL(messageReceived(const QByteArray, const

QMqttTopicName)),

?this, SLOT(messageReceived(const QByteArray, const

QMqttTopicName)));

?} else {//斷開連接

?ui->pushButton_connectmqtt->setText(tr("連接"));

?m_client->disconnectFromHost();

?}

}

發(fā)布信息

使用定時器設(shè)置定時時間,這里設(shè)置的是 5s,每隔 5s 會向云端指定的

topic 發(fā)布溫濕度的數(shù)據(jù)。

void MainWindow::InitTimer()

{

?m_timer = new QTimer;

?//設(shè)置定時器是否為單次觸發(fā)。默認(rèn)為 false 多次觸發(fā)

?m_timer->setSingleShot(false);

?//啟動或重啟定時器, 并設(shè)置定時器時間:毫秒

?m_timer->start(5000);

?//定時器觸發(fā)信號槽

?connect(m_timer,SIGNAL(timeout()),this,SLOT(TimertimeOut()));

}

void MainWindow::TimertimeOut()

{

?mqttTopic ="$iot/zhjt/user/fortest";

?mqttMessage.clear();

?mqttMessage.append("{\"temperature").append("\"").append(":").append(tem)\

?.append(",").append("\"humidity").append("\"").append(":").append(hu

m)\

.append(",").append("\"illumination").append("\"").append(":").append

(ill)\

?.append("}");

?//執(zhí)行定時器觸發(fā)時需要處理的業(yè)務(wù)

?// 發(fā)布

?if(m_client->publish(mqttTopic,mqttMessage.toUtf8()) == -1)

?{

?QMessageBox::critical(this,"Error","連接斷開或輸入的 topic 有誤,無法

發(fā)布",QMessageBox::Yes);

?m_timer->stop(); //停止定時器

?}

}

訂閱信息

訂閱 Topic 為 $iot/zhjt/user/control

當(dāng)有客戶端發(fā)送 Topic 為 $iot/zhjt/user/control 的數(shù)據(jù)時,會接收到

數(shù)據(jù)并進行處理。

void MainWindow::mqttconnectSlot()

{

?QString subScribeTopic ="$iot/zhjt/user/control";

?m_client->subscribe(subScribeTopic);

}

void MainWindow::messageReceived(const QByteArray &message, const

QMqttTopicName &topic)

{

?qDebug()<<"messageReceived:"<<topic.name()<<QString(message);

?QJsonObject json_object = QJsonDocument::fromJson(message).object();

?if(json_object.value("led1").toInt() ==1)

system("echo 1 > /sys/class/leds/led1/brightness");

?else

?system("echo 0 > /sys/class/leds/led1/brightness");

?if(json_object.value("led2").toInt() ==1)

?system("echo 1 > /sys/class/leds/led2/brightness");

?else

?system("echo 0 > /sys/class/leds/led2/brightness");

?if(json_object.value("led3").toInt() ==1)

?system("echo 1 > /sys/class/leds/led3/brightness");

?else

?system("echo 0 > /sys/class/leds/led3/brightness");

?if(json_object.value("fan").toInt() ==0)

?system("echo 0 > /sys/class/hwmon/hwmon1/pwm1");

?else

?{

?char fan_on[64];

?sprintf(fan_on,"echo %d >

/sys/class/hwmon/hwmon1/pwm1",json_object.value("fan").toInt());

?system(fan_on);

?}

?if(json_object.value("beep").toInt() ==1)

?beepring();

?else

?beepunring();

}

微信小程序設(shè)計

創(chuàng)建新項目

打開微信開發(fā)者工具,新建項目,填寫自己的 AppID,新建。

注意:創(chuàng)建工程的路徑一定不能有中文。

準(zhǔn)備圖片

下載幾個圖標(biāo),可以去阿里巴巴矢量圖標(biāo)庫進行下載。下載好的圖片放在

pages 文件夾下得 image 文件夾中。(沒有可以自己新建一個文件夾)

https://www.iconfont.cn/home/index?spm=a313x.7781069.1998910419.2


STM32MP157開發(fā)板Linux+Qt項目實戰(zhàn):智慧家庭---上的評論 (共 條)

分享到微博請遵守國家法律
富锦市| 定陶县| 石门县| 汝城县| 云南省| 六枝特区| 策勒县| 原阳县| 黑龙江省| 镇坪县| 定州市| 商河县| 卢氏县| 丰镇市| 遂川县| 平遥县| 长岭县| 无为县| 定西市| 抚顺县| 盖州市| 河东区| 礼泉县| 徐州市| 石城县| 奎屯市| 宁海县| 荃湾区| 泾阳县| 将乐县| 中方县| 吴堡县| 泰兴市| 饶阳县| 通榆县| 南昌市| 聂拉木县| 百色市| 石嘴山市| 独山县| 庆安县|