你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

基于STM32MP157开发板做的Linux+Qt项目实战之智慧家庭---上

[复制链接]
STMCU小助手 发布时间:2023-2-10 15:21
QUYJ`TB]SDY048IU{DTGNPI.png 6 D" e) a2 y8 c# H- F2 @" h; n
8 w: O; i0 c* a  B) P; ~
stm32mp157开发板FS-MP1A是华清远见自主研发的一款高品质、高性价比的Linux+单片机二合一的嵌入式教学级开发板。开发板搭载ST的STM32MP157高性能微处理器,集成2个Cortex-A7核和1个Cortex-M4 核,A7核上可以跑Linux操作系统,M4核上可以跑FreeRTOS、RT-Thread等实时操作系统。开发板搭配仿真器、显示屏、摄像头、资源扩展板等丰富的扩展模块,可拓展物联网、人工智能等相关技术学习,还可以拓展丰富的项目实战,非常贴合企业当下开发需求,是一款嵌入式Linux入门进阶必备开发板! . T/ }4 j# N8 w! t) b7 f2 N3 ^, G" z

1 S3 h2 m- o9 C6 S可学习技术:嵌入式Linux应用/系统/驱动开发、ARM裸机开发、Qt界面编程、STM32单片机、FreeRTOS、人工智能机器视觉等。
( |% t  {% P9 b, S* ~8 g  \* A+ X1 n. k
QWI[0A~{`_9QWBZAXQ[Q@@P.png & U' R# r& Z, ]- E! d7 o2 f) A8 \

2 Q/ @) s# ?2 c4 P+ F# q可实战项目:14个Linux+Qt综合项目案例,8个MP1A物联网拓展项目) X/ K1 D: J! s9 u
; X/ C7 w# y" w! s1 T% C8 k
1、Linux+Qt综合项目案例:华清远见stm32mp157开发板优势特色部分,包括音乐播放器、智慧家庭、智能工业电表、智能出行助手、智能猫眼、环境监测、智能安防、智能语音识别等10余个项目案例,涉及家居、医疗、农业多种应用方向,在案例中使用了多种物联网和嵌入式技术,包括OT开发、linux应用开发、linux驱动开发、物联网云端接入、MQTT协议、json字符串等知识点。# m7 Z& Z( ?& B2 R: V: B; ~

7 A/ a6 y, [0 k基于Linux+Qt的智慧家庭项目

; [" {$ e/ W. Y" H& t; h+ x项目简介:
' n# g2 U, {$ O智慧家庭又可称为智慧家庭服务平台,是智慧城市的最小单元,是以家庭为载体,以家庭成员之间的亲情为纽带。智慧家庭综合利用物联网、云计算、移动互联网和大数据等新一代信息技术,结合自动控制技术,将家庭设备智能控制、家庭环境感知、家人健康感知、家居安全感知以及信息交流、消费服务等家居生活有效地结合起来,创造出健康、安全、舒适、低碳、便捷、个性化和充满关爱的家庭生活方式。
5 T" t# V$ z( |1 c1 ?9 v0 g, Y/ d5 O( ?, `8 g

7 P4 K7 ?+ x/ c* I4 C  B5 ]+ Q! `! t开发平台:
, }$ W' _  q/ D3 n华清远见stm32mp157开发板豪华套餐(开发板+仿真器+五寸屏+摄像头+资源扩展板+tf卡+读卡器)9 y- c/ b. ]' [; h3 z
( m! n5 \0 N9 ~2 z' H9 m' {
项目功能展示:1 L, |! N! r  _( E
Wifi 模块5 A% [; m0 x. p' U4 B/ K
点击刷新按钮,可以实时更新附近的 wifi,选择要连接的 wifi,会弹出输入密码的页面,输入密码,点击连接即可连接成功。
3 ?# N3 K+ O/ H. M
- f1 Y* u0 Q5 r6 K& E* k
SVCIYPP{%K$@1`6~12X]]1P.png * Z0 x2 R: S& p3 D! C+ K8 b( d  h

- y9 K% m2 X0 Q2 ?1 z  _
{5BP8C5(JF(]MIQO$@UM}UP.png 5 J% Y, P. K4 w* }6 J

+ t  q3 B& l- l  t* k6 k
选择要查看天气的城市,点击获取按钮0 y& M0 l# l2 ?- f0 U- O
8 e* c4 f( j1 l
_@89SPX3E4B4@QA{AZOGZ]3.png
- o5 x4 T3 z* o% u$ E
* R2 o9 P3 c# z8 S) r6 T
环境监测模块
2 J* {4 V9 X. C/ U% {6 C1 d7 x, a0 L
YC)~A94I08EQ`YH~KL4IL{2.png
% J1 X$ J1 H+ `" |  F
/ O0 q* T" N: J0 k9 g3 [% d
设备控制模块4 k" R: f1 ?0 h# o+ h* Q6 w
选择按钮即可完成设备的控制
6 X" \- x3 ?6 q1 _7 t2 T5 j2 m- n8 p. F2 ]3 w/ d2 V
%~KKPI%Y@F**BCOP($M2W6.png
+ a. L* |' ?/ d. C
" p+ I) e3 b- K9 e) r: \
开启和关闭按钮控制智能监测的开启和关闭,提交按钮上的输入框输入的是智能监测触发的阈值。# i# s7 n) w! H$ D$ L

/ \% }; w& E4 X8 D! l
URPIE04H]F}THLY2KYHAKI8.png $ h: Y! k$ b2 l5 @; r7 U( Y. ~
. |- m) f8 ^7 c6 V4 B/ G5 ?1 z
连接百度云模块$ L! C1 [" [$ i0 d9 u- l, z8 q
输入百度云连接三元组,点击获取时间戳,点击计算、连接,即可实现向云端发送环境进而转发到微信小程序,并且通过微信小程序控制设备。/ t2 ^% `0 O5 N3 h: P0 P1 p% _- v

1 _0 g" A0 y& N* _( L8 h9 h
TK48WOBRWP_6KDF~_6TQ{7H.png # [, \, ^  U# h* Y' B' y/ O9 L
! [1 G3 A( ]* _* s: P. q* E
在微信小程序显示温湿度。并且控制开发板 led 灯- K$ i2 Q2 f+ g# @
. x9 K3 \) w- K/ X0 o
KD_XW~VN`6_F[EMWXHC@3VL.png " d: k9 F* G& @9 ?' M

2 R. i' I# d6 g* Q) A遮挡光电开关,会自动弹出门禁系统。
0 \$ I9 Q: P# m( P' N& ]2 T; V, g5 d/ J; p9 {& U$ e
$W0}X6H@4MJE]2C5(E9JHSY.png 8 k2 F2 R1 U9 d9 E& X
( O) @% U' @3 H1 u" r" F
Qt开发环境搭建
3 {* |, B% r* d; X5 ?主机开发环境说明

: \$ q) a+ \) a$ s6 C5 P1) 本文档主要介绍 linux 环境下的 Qt 程序开发;
/ u) g. A. n4 z! G/ u2) 主机 Qt 版本为 5.14.1;( ?, p2 s2 y& v% X
$ C% s* a( j5 T/ ?( e; V
主机 Qt 环境搭建及使用
9 L9 p% q- ]/ {3 }2 ^, A) UQt Creator 安装7 O  }1 s+ Y  |) f: c) c
将 qt-creator-opensource-linux-x86_64-4.10.1.run(Qt 实验源码\工具软件) 复制到 ubuntu 主机中,可以采用共享文件夹的方式也可以使用 tfp方式将文 件存入家目录下的 Downloads 目录。我们需要在终端中赋予安装程序可执行的权限+ ?: B* |0 c: O* d

# s+ O  ^( J0 g
YXM}@[HAVEZBR9%5NX[_)6H.png
3 R0 W" s5 r& l, M' M% a) W. h
! I) p" N# `; i+ t" R
我们可以使用图形化的文件管理器来查看6 j8 E7 U6 }5 j3 F

; Q( L7 \/ O# ]0 v, H' P' ^0 h
P2FS$@N$$EAOMI@MNC[MV7U.png 8 f, w" e" o/ ]) G! W& H) g
- q* F+ M( \' C0 u$ y3 D
双击“qt-creator-opensource-linux-x86_64-4.10.1.run”图标运行安装程序。
; F2 _8 A7 \' R/ P0 ?
' d2 j5 s' a) S& i  Q
出现如下界面:
! z8 X5 {; M9 _+ |
$ l  d# `8 J: T% l" V0 A
4ID8XA`Z(`ODSHHTIKPBCNQ.png - l1 u5 B, u+ O  ?8 @
4 J! V# u( `6 h/ f+ _" o7 V
等待程序验证完成后点击“Next”
/ A+ f3 V% b$ u3 t2 ~. b3 ]2 ?% X
0]VQY9LZ[`6SKA9RTFNRE23.png
2 E. x$ T3 A1 O0 Y6 G. T. w- H
% e4 B- `/ H" F4 q
这里我们需要登录或者注册一个账号,如果我们之前已经注册过直接登录就可以。如果没有注册过则需要新注册有一个账号后登录。这里笔者已经注册过账号,所以直接登录。
* o% V+ j7 ^. r+ K, d7 b' u  T/ C" X" @0 g0 {* l& n
登录成功后出现如下界面,点击 Next
% U* o* F! B) {
# X% `+ ]9 n7 ?
[~}4K%%{O06AWV40[8HYKAJ.png
5 K$ y& R% z$ O
! R/ d/ o, k- T# N2 e  N
这里选择安装路径, f- M7 M# X( a

" {% Z4 ?4 Z$ A% M; X) g4 m
02@}`7QZ}W)QEA`PA5LA4TU.png ) n) }, Y# u' j  ^* D
可以直接默认,Next
8 E- }$ b6 _% {1 j* ?& x! h3 B7 j0 L3 @( u- c
}VRQS6H_]G@Y](SHYD$J24J.png
2 F: k  W* j  v
3 _, D+ g+ ?: [
这路选择安装的组件,直接默认即可5 Q" v3 C! I: F7 y! }. X9 m

3 m+ Y1 E% X% D8 j9 e
LGFW1HZB5M9AJH@TH%$C4.png % S8 Y4 _) g/ B' q* E& y' K" f
" L, g0 W3 K/ p
这里我们需要同意用户协议
+ Q; L2 k9 r8 G* F$ |+ B, n$ i* L. f; K$ {
HBUXY`$%YNWN7Y3M1~__R(A.png
- T( d4 j) [0 R+ ^. g+ @4 \
5 G0 g! ?5 O+ u
这个界面告诉我们安装完成后需要占用的空间。点击”Install”按钮后开始安装。
' l( R7 v+ [! z/ M* ~/ O0 e
- \' Z* s4 a* e1 f9 {
4 S7 f# C5 E* O8 @

9 m- L4 [, V+ F2 b. }) \安装完成后出现如下界面- X& j. ?- J; g4 ]

4 j- U7 |& F& J! \% K) d. d
4 G/ d$ Z, ?  V  j  ?; t. }

4 h" x: x, N: A, G( D
点击“Finish”按钮后将弹出 Qt Creator 主界面# T  D! v) b# P& o0 l' f

6 n) ~# S3 q. ^4 A. H# [
7S(9~_~$~L)90NE1B)8XZD9.png
  a, o/ _8 s- ]: @, j2 t2 u. i5 S/ {/ B# p3 C; w/ Q! I* Q1 I
点击“Cancel”按钮后即可正常使用+ E0 I9 _6 z3 D" \; v
* ~2 H4 t' M  Z9 J2 d. ~

+ t- U: g, c4 FQt5.14.1 安装: q8 ]7 A( Y( E9 _7 C7 ]3 o! C  G* m* t
复制到 qt-opensource-linux-x64-5.14.1.run(Qt 实验源码\工具软件)到 ubuntu 主机中,可以采用共享文件夹的方式也可以使用 tfp 方式将文件存入家目录下的 Downloads 目录。进入所在文件夹,先给执行权限输入命令8 F8 w: ?3 S# Y( A
* L! f# o' P* ^7 Z3 I
chmod +x ./qt-opensource-linux-x64-5.14.1.run* j7 m3 n; \$ B9 J0 |
" Q. f1 [$ j$ D" B& H5 Z+ f
安装在命令行输入
2 A3 v& B, A' G0 G+ A: t1 z$ i. G% T' L8 Y9 r- V
./qt-opensource-linux-x64-5.14.1.run* w0 }0 S6 ^  a3 H5 p1 ]

* ~  b" L. b) _! v8 W; S4 Q4 n
会有可视化引导安装,一直 next 就行了8 g, w1 F- V* u$ h( T% f

; f) B& A9 p# ?9 y( u
在选择安装组件的时候要是不知道选择那些就全选了 大概有 4 个 G 左右- m- i$ F/ y. v$ W

$ d& b; S/ ~* P; T% d& y/ u9 m% \4 ^  y
下载 gcc 和 g++
, U2 s* ~+ [3 G8 h) {" _4 G1 v* l. j9 F
sudo apt-get install gcc g++
( g' x4 v9 \: ]& ]
& P; P1 l1 U0 g7 [8 @% c: \
下载 cmake
) e5 W  H  |# i3 L) ]; a# g8 J1 p
sudo apt-get install cmake
7 U4 N$ `6 h- K# s* F8 x8 y8 b8 t9 C5 m- u# d
下载链接库
& l9 S2 E# L* {8 m
4 A: M' ?- y) Y0 y" z$ @5 fsudo apt-get install libgl1-mesa-dev libglu1-mesa-dev
# @3 C1 x7 q$ M# Z5 ^5 f1 i/ O& ]9 C2 f% z
Qt Creator 配置0 p8 s$ y$ s" q* ]5 T
1)配置 GCC
$ _5 C3 l0 h- O8 E5 p8 C运行 QtCreator 后,依次点击"Tool"->"Options",出现选项对话框,在左侧点击"Kits",右 边选择"Compilers"标签。 检查有没有下图标注的 C++和 C ,一般按上面步骤执行后都会有
- q3 _; a) V5 _0 D
+ ~6 Q: @% g" f# z1 t. O
`TM6{[`YAQ@]B`FV1%EGNER.png ; C6 w4 B3 R- w0 a

* o# D$ y( B7 f% _7 v点击右侧"Add"按钮,弹出下拉列表后,选择"GCC"的"C"- q% m9 w0 \0 n# ^- r4 r% I0 X7 x/ g

/ O9 r( U) V' B6 ?5 C7 t
1EROYSYWYNFAKNG){AQAI_3.png
9 Q, b! u' P4 r5 q: Y; n
+ q/ g  A% o) ^. x6 M1 p填写信息如下,"Name"为"Auto-GCC","Compiler path"点击旁边的"Browse.."按钮选择编译器的路径,例子中的路径是 “/usr/bin/gcc”2 Q/ K' Z  A1 i8 t1 D
8 ]. Y  f- \* @# u+ m
U~6B}]8(%(L0$CWOE6CT.png
9 N* i0 ]/ ^& j/ [& ?/ x. W
% ?5 j: ~& h0 s  Y1 `3 N
2)配置 G++) v2 B% o, v( c4 C- g
点击右侧"Add"按钮,弹出下拉列表后,选择"GCC"的"C++",下面的文本框填写"Name" 为"Auto-G++","Compiler path"点击旁边的"Browse.."按钮选择编译器的路径,例子中的路径是" /usr/bin/g++"。+ g3 y5 d0 [# N+ b1 z. w# J

; x) y5 b! y- w4 G
0 ~! M, C0 i4 O' `
8 ?* ?/ |. X, V

6 W4 w* g6 V6 A4 @& Q
2 Q9 s) d& F+ F5 j. G; ?2 \" Y3 c* ~填写完成后,点击"Apply"。
( H- O9 m0 Y9 v0 I8 ^3 j8 k! B" j" G2 `% [) [5 Z
3)配置 qmake' O9 \) ^" b  w7 f$ X2 f4 M3 q% p; s
选择"Qt Versions"标签,如果有下面红框中的文本,可以跳过下面步骤+ o" R& z. d; x3 Y5 C1 d# a: ]; V
: X( c3 q1 _; {1 @' I: L4 R1 W
(_WYIV~I3(WLN)UZL}L24A0.png
5 B6 {. g* \$ i8 s
3 k, O/ |! [. v5 x
如果没有,在右侧点击"Add..."2 G* ?1 O: l7 B% L# {/ [- a

- A; l- {- I! C  W' X
8A9O1FTB_`48Y]IQI@X){HM.png
- [- `) H& z) G" K8 X$ q( ^6 i, r' k" L' I0 @0 _, i: G
会弹出 qmake 路径选择对话框,这里以"/home/linux/Qt5.14.1/5.14.1/gcc_64/bin/qmake"为例子。 选择”qmake”文件后,击"Open"按钮0 t* q4 ~" ?2 Y' c6 q- M) G9 u

6 {0 }4 Y, Z& x. J  b
VWR%~DF7DT9O`@N}X{5V(MO.png
  i+ @& d5 p* r, H
3 c; U0 @5 z" V" i5 a"Version name"改为" Qt %{Qt:Version} GCC"。然后点击"Apply"按钮。* b4 [* S9 H% U9 ?9 Z3 s
& e6 ~' i) j5 U# f
4)配置 Kits
* U3 g/ j" X' H点击左侧"Kits",右侧选择"Kits"标签。检查有没有下图红框选中的文本,如果有可以跳过下面步骤6 u7 f& ?- A2 U) z3 X$ R9 q: ?
+ C$ M4 D. I, Z9 F
2}FWK{5CA{K0)S4(3OH8G8C.png   J+ Y, E9 j8 {6 ~( J

0 Y; b9 p9 m: g3 c9 f# d然后没有,点击 Add:
$ N* ]0 o0 W& s4 z7 Y6 T" H! P. H) U: j
在弹出的对话框中"Name"为"Desktop","Device Type"选择"Desktop"选项, "Sysroot"选择目标设备的系统目录,"Compiler"选择之前配置的名称
( _# m6 T; E0 C. d( u0 e1 G; y* ~& H8 R" q
"Auto-GCC"和"Auto-G++","Qt version"选择之前配 置的名称"Qt 5.14.19 G5 b: o8 l: M0 x9 P0 x6 m

5 Y8 p8 E  y. PGCC",其它默认即可,最后点击"Apply"和"OK"按钮/ Z: }0 s6 k" f6 r6 |8 @5 s- w+ D: H

% x) Q" p; N% h  S+ w$ u/ y
& ?; x; {" q9 d, @, w% p* b Qt Creator 新建工程
. U* |2 Y! \, t% |* m2 F注意:工程路径最好不要包含中文、特殊字符、空格等
1 \* [6 X0 _$ v9 n2 X$ j& J
1 z) U  y0 c/ {) h' g
我们可以新建一个“qt”文件夹,该文件夹用作我们以后存放源代码。
5 ^$ T/ Q( X4 Q2 W/ v
& O* C( ^! _; h4 w4 z
P(YSDLLU7HPN]O[$(E9J~YC.png 9 I* b% O2 I4 P5 c! R2 {* r

$ s! x8 p6 f- s6 J6 g打开 Qt Creator,在欢迎页面点击 “New”按钮,来新建一个工程。
, k% R- a% _) {9 v. R9 x0 y' K
- b5 H" ?8 B1 A. A1 @: B
W0`CL}D(SP}G1_M9MVSHEC9.png
$ u6 x- q" m* z8 T" w5 C( p
) v* Z( j; s0 `2 p7 ]4 }% v2 V
在出现的新建项目窗口中,我们选则“Application”->“Qt Widgets5 q6 G- |/ z6 x5 {; s) H  @5 \

/ _, n( t. A4 a3 K9 b% YApplication”,然后点击右下方“Choose…”按钮,来创建一个桌面 Qt 应用。; K4 V- H, Q' Y4 c% m( W  G

/ ^; Z6 h% a! f" u. v! m
$_YRN3RR@G(1EDQ`GD78[3L.png
0 C; t6 s  \) I8 E- B6 K

: ?4 L8 r4 }2 n我们在这里设置项目介绍和源码位置,我们这里创建一个名为0 X2 u6 j9 E9 S+ m5 F/ u
“HelloWorld”的示例项目,设置完成之后点击 next
8 p- ]& x8 T9 G% D6 o
5 z- t* S) q  [2 y+ L9 m1 i+ O" ^
ZB}(]4PU0$C07V}NU8_Z4OK.png / B6 Y7 o; P/ p  d! V% O
9 u1 D2 i- l6 W+ v! k
直接点击 next5 B$ \( T4 }. K# T0 e! r' f& W

; ~/ v( N) X9 N' R, |0 Q% I' s
Q(K%H9VD4}Y`J_C)PT~D{N6.png
  _; D. j' r: a+ f6 ?; \% J, O& y8 l/ o+ p+ Q0 d
随后进行细节设置,主要设置要创建的源码文件的基本类信息,包括类名等。这里我们可以根据自己的项目特点进行设置。需要说明的一点就是基类的选择,这里基类有 QMainWindow、QWidget、QDialog 三种,它们的不同之处如下:4 R# W- O+ H8 r* E, W. K
⚫ QMainWindow 类提供一个带有菜单条,工具条和一个状态条的主应用程序窗口。主窗口通常提供一个大的中央窗口部件,以及周围菜单,工具条,和一个状态栏。QMainWindow 窗口经常被继承,使得封装中央部件,菜单,工具条,状态栏等都变得很容易,当用户点击它的时候,相应的槽就会被调用;4 b: f8 g3 f5 X* W7 J& H" K; l
⚫ QWidget 类是所有用户界面对象的基类,窗口部件是用户界面的一个基本单元,它从窗口系统接收鼠标,键盘和其他消息,并在屏幕上绘制自己。一个窗口部件可以被他的父窗口或者是其他窗口挡住一部分;
) z/ g7 H" U3 g; q. _0 F⚫ QDialog 类是对话框窗口的基类,对话框窗口主要用于短期任务和用户进行短期通讯的顶级窗口,QDialog 可以是模态对话框或者是非模态对话框。QDialog 支持扩展并带有返回值,他们可以带有默认值;我们在这里选择 QDialog 类即可,点击 next 完成类信息设置
. s& x3 e6 [) @3 O! S: n  f* J1 z
' k# A7 M) C' a& Y# g
X$%UAH}$)FO(J3BIU])@3_T.png
  J, ~; d$ @2 C# `4 j1 m6 V
5 z6 E& S/ s7 |" ]直接点击 next 按钮即可。/ h' I, l. f0 b( F+ G
- m6 I; Q& I0 R/ r. [+ Q
6TH61]SII0LQ691FQVLPOBB.png
: ^+ _1 c# F, k- n) x2 I( A
) N) I: v) E, J& B) B6 x, `4 G然后进行工具选择,该页面可以选择我们创建的工程可以使用的工具,选择想要使用的编译器模块,例如下图 。点击 next  R+ P9 O! B$ g3 ]8 W* E' r

- }$ q0 J; G4 v# @. y
_JKKWR6U67_L@75WZVPMKFU.png
7 ~, V+ o* ]8 w8 l3 R% W
+ g9 `- C+ ^- X- n% R% p最后我们设置汇总信息,如果不需要版本控制等功能,直接点击完成finish 即可
* Y4 R  \6 _% |2 l, ^" E2 U+ z; n; Y4 I3 O, q& x. w  G
XZ_C0WTB7XYG[9{94G4~~RJ.png ; S/ O) x2 o- E' u$ B3 }$ Y

& \% x' D) M5 Y) _随后我们就进入到了主界面,这时候 Qt 已经帮我们做好了一些准备工作,包括创建了一些文件,写好了一些前置代码等等。: U2 a- F1 @' A1 S6 d5 q! f
4 _, |% L; z1 w
我们可以点击左边 protect 栏,来查看我们的编译选项
9 Z: ^$ u/ Q8 f# X9 G& a. b, t* c: U* V1 m8 V; `
)CP44_~VJY0J)I1LUVE)1NL.png : L4 v* y6 C5 _
1 r6 x) x1 ?! L- X  J; T1 K
我们可以在左下角选择编译 Debug 版或者 Release 版,即调试版或发行版。( u7 Q1 X0 ?! k* z% u
" E9 K# C: ?, u) Y+ R
3ULZA9%8G{[14G%{VQH7.png
+ `0 G! t0 ?+ {: o, k4 Z  k

. C* B% r6 ]* j! ?5 V5 E( T左下角绿色剪头是编译并运行,锤子是仅编译,我们可以直接点击绿色小箭头将我们导入的工程编译并运行起来。
" `" y' f2 |) M' O
8 }8 P9 o7 g5 P9 ?' \
1NBIR0`F@3ZSU2REX5ZK4$K.png 8 W7 P) c; p2 H/ j% F$ I; X
; S4 n; U* d# I% S) |
点击运行按钮后,我们可以看到 HelloWorld 窗口运行起来了。
5 }. }! f+ b8 b# t! A  H
! y' E4 m9 y. Y+ p. Q/ K
(15RO4%(RD}A_@I2Z72R[]R.png
) n& ^* p9 B& ]4 V: s9 [/ g2 O4 M& \
导入工程3 _7 r. d* ~7 d) M# f: Y# p0 Z2 U
我们可以将已存在的 Qt 程序项目直接打开,这里以上一章节的HelloWorld 程序为例。首先我们确定源码存在的位置,如 HelloWorld 程序源码在 /home/linux/qt/helloworld 路径下。
2 n5 _% l8 y/ ^( y  n4 o8 B; T$ }
点击欢迎页面的“Open” 按钮可以打开已有的工程。; k+ d4 e9 a( f4 _8 l- w
/ N1 B9 X0 x5 f: U# d
YO_SU(4O5X8B$UJ_M2F.png
; y% W" Y0 f; D& o1 d( t
4 b+ E5 H* v+ m* Y8 a  b6 m7 `8 l找到我们刚才解压好的源码,选择“helloworld.pro”文件并点击打开! z' k9 u7 B8 |) h7 W

+ P2 C$ |$ l4 G/ t' B- y0 ]
) e% y! ?) u- h9 C. R) ^
4 ~4 {# r, [  U$ ~
接下来我们就可以进入到代码编辑界面了。$ {2 c$ Q# C% u

: x% T5 b9 v3 a* L6 t
BZEPY[_6ZZK~V59`XL7%XV2.png
& z& K/ U$ s, ?: B0 x4 C# L: C" z' J- J* s- `2 H1 V/ q
左上角是项目栏,点击项目名称左边的小箭头可以展开项目目录。
1 x: S2 y: l- W( G8 ^( Q2 Z9 s0 b0 l& K+ T8 S
_~OX6IL7)EGWXZCWSKQU6.png
5 o+ f  b  H8 l
0 b' U- o7 e) ~$ {* f1 r% s8 f
我们可以点击左边项目栏,来查看我们的编译选项。需注意的是构建设置中的路径应与工程路径处于同级目录下。# E3 Q+ I" K; F# ^
1 l4 Y* p+ s" M& T' m
[%~`0NJ~]M(GDU(R_IQ)R}X.png
) ^$ V1 b+ I# t2 J2 w3 m+ `% F6 E" J

, N; M4 y) \' H5 Z) n+ Z我们可以在左下角选择编译 Debug 版或者 Release 版,即调试版或发行版。
; u9 r+ V. I- ^2 Q- i& d. T. f" f) `% [* o( p
72BZ`U_6]LTC)W5L2PR0J%J.png + Y# |2 @% a' y6 K4 P  c+ I

" ^! |& Y6 q  L& p左下角绿色剪头是编译并运行,锤子是仅编译,我们可以直接点击绿色小箭头将我们导入的工程编译并运行起来。8 t0 M9 E! q8 p* D  `

" M5 i  ?4 ?4 M

6 W4 R$ ~! m" B
' P( H' P! }0 L* x$ |, F% X* z
点击运行按钮后,我们可以看到 HelloWorld 窗口运行起来了。
, d8 G- v& h& ~0 u; B& x
  M' ^' H/ C9 V1 m4 V
0 g) S6 i9 C& T& A4 E
& @$ J+ m- D" M
文件说明1 [* x: |$ ~' U" T: n- c3 S
通过上面两个章节,我们学习到了 Qt 程序的新建与导入的方法,也知道了Qt 会帮我们做一些基础工作,比如帮我们建立了一些文件,那么这些文件都是干什么用的呢?我们以HelloWorld 程序来说明一下。
5 @0 B) S% l: k# Z/ U6 q- [4 o+ @/ C% E5 Y- i

4 h# J& \! [! E: M( ?4 D0 v0 @5 _+ m- \* y/ g! U6 M% p4 L! s
以“.pro”为后缀名的文件,为 Qt 的项目管理文件,存储项目设置的文件;; \; f+ l/ {9 L5 `6 ?9 y5 j$ b
! L8 L; m+ m3 j1 k% J5 [( g- [
NIL}HI4FU0OAUV1]VKODRZ3.png & [6 q6 k) |5 |; [/ L& T* ^) Y

2 M  ]5 J. @: E# ~2 q
“Qt += core gui”表示项目中加入 core gui 模块。core gui 是 Qt 用于GUI 设计的类库模块,如果创建的是控制台(console)应用程序,就不需要添加 core gui。- h; v/ P) G* ]) h6 p
3 R$ d& F3 v7 l2 s
Qt 类库以模块的形式组织各种功能的类,根据项目涉及的功能需求,在项目中添加适当的类库模块支持。例如,如果项目中使用到了涉及数据库操作的类就需要用到 sql(数据库)模块,在 pro 文件中需要在后面加上 sql:
% e: O" D: V0 a1 `6 W. m7 O8 v1 u: q7 S
1 Qt += core gui sql
( r$ ?% p. A/ P" f# i4 M+ T; T# R# `: S2 N& Y
“greaterThan(QT_MAJOR_VERSION, 4): QT += widgets”,这是个条件执行语句,表示当 Qt 主版本大于 4 时,才加入 widgets 模块。( P; B3 F. h) U. y6 J7 {+ D

6 [- m  y; {& w1 V8 i
“TARGET = HelloWorld”表示生成的目标可执行文件的名称,即编译后生成的可执行文件是 HelloWorld.exe。
* Y" F& y, H  r( L8 R( m# ^  \+ A7 L2 t3 u! g9 m0 h3 o
“TEMPLATE = app”表示项目使用的模板是 app,是一般的应用程序。; d# t* T+ ]; H/ q- }' o
6 R9 ]& O: f) ^4 S9 v( p
后面的 SOURCES、HEADERS、FORMS 记录了项目中包含的源程序文件、头文件和窗体文件(.ui 文件)的名称。这些文件列表是 Qt Creator 自动添加到项目管理文件里面的,用户不需要手动修改。当添加一个文件到项目,或从项目里删除一个文件时,项目管理文件里的条目会自动修改。8 Y$ T7 q* ^0 d* n; {5 b" X
! m2 w; E: z- N3 ~$ @! E5 C
文件夹“Header”中,存放的是所设计的窗体类的头文件;
$ b+ d8 N7 ^' e) U0 H
0 h2 L/ h1 U' a  }* v
文件夹“Sources”中,存放着源码文件。main.cpp 是实现 main()函数的程序文件,HelloWorld.cpp 是 widget.h 里定义类的实现文件。C++中,任何窗体或界面组件都是用类封装的,一个类一般有一个头文件(.h 文件)和一个源程序文件(.cpp 文件);  b1 V/ r. \9 K7 E" R/ S
* S1 s3 L. A5 D" ?7 D
文件夹“Forms”中,存放着界面设计文件,“.ui”文件是一个 XML 格式存储的窗体上的元件及其布局的文件,双击项目文件目录树中的文件 ui,会打开一个集成在 Qt Creator 中的 Qt Designer 对窗体进行可视化设计;9 E6 `8 ]4 G; G" O% @) d" H. s

( q( H8 A! u" o' `( O" O. |" r
~0O849UB9NT(C(C6S2$Z7R9.png - e1 {& a' j+ \% B! Q  a2 K4 f& ?! h

4 T* z- Y- P% E% PUI 设计器有以下一些功能区域:, ?  l+ e$ Q; M' i$ b

- ^* ^- M3 ]6 r  e4 d) Z
组件面板:窗口左侧是界面设计组件面板,分为多个组,如 Layouts、Buttons、Display Widgets 等,界面设计的常见组件都可以在组件面板里找到。5 P6 ^% F9 Y0 C
% |7 Y% ^& k( U# y
中间主要区域是待设计的窗体。如果要将某个组件放置到窗体上时,从组件面板上拖放一个组件到窗体上即可。$ f  k! ^' `: ?4 F3 g
$ E6 }) t6 @$ X3 S! V5 u8 p! i- p3 i3 q
Signals 和 Slots 编辑器与 Action 编辑器是位于待设计窗体下方的两个编辑器。Signals 和 Slots 编辑器用于可视化地进行信号与槽的关联,Action 编辑器用于可视化设计 Action。
1 Q) I+ ~5 L' p: B# C( E* D; ^
5 T3 F' J6 s! Y+ }+ ]. _7 B
布局和界面设计工具栏:窗口上方的一个工具栏,工具栏上的按钮主要实现布局和界面设计。( I$ U: i+ z: j. F  w$ l. P

+ I: B$ T* @  s' g% B% J: ~
对象浏览器(Object Inspector):窗口右上方是 Object Inspector,用树状视图显示窗体上各组件之间的布局包含关系,视图有两列,显示每个组件的对象名称(ObjectName)和类名称。- W' X, z; B. b6 t
1 `2 u. V7 e9 x7 X
属性编辑器(Property Editor):窗口右下方是属性编辑器,是界面设计时最常用到的编辑器。属性编辑器显示某个选中的组件或窗体的各种属性及其取值,可以在属性编辑器里修改这些属性的值。属性编辑器的内容分为两列,左侧为属性的名称,右侧为属性的值。属性又分为多个组,实际上表示了类的继承关系,位于下方的类属性组继承自位于上方的类属性组;如果我们需要新建资源文件、源码文件等,可以在项目文件夹出点击鼠标右键,选择 Add New;如果我们有新的文件需要添加,可以在项目文件夹出点击鼠标右键,选择 Add Existing Files。
. z: }3 I2 E! W! \6 ^4 I  x$ {/ M0 f2 o+ ?' U
E5LXC5(Q61T$$LY8RXFN2_L.png
% Y3 l7 D0 S  }8 P" L3 V
( d3 s9 F) q1 w, n
帮助文档: l+ M" p0 {9 X
Qt 的帮助文档是伴随我们学习 Qt 开发的好伙伴。在 Qt 开发过程中,我们会面临图形接口使用的问题,它不像 C 语言那样就那么几个函数接口,图形接口的接口数量可以用海量来形容,常用的我们可能能记住,其它的就没有必要去记了,用到什么就去帮助文档查看用法是比较方便的。我们可以按 F1 按键,或通过上方导航栏的“help->contects”来进入帮助文档。
" [* t0 h. ]' L  F8 O- s9 A0 L, W  R- u+ y- Y# w7 c6 s0 [
LNUOL]PXQ$_U192L}P_YWR7.png : [" Q7 q: e6 g
8 H+ p, \8 q( u8 |3 A$ _9 }% e
上方的前进后退按钮方便我们查看文档,如返回到上一步,返回到下一步。. x4 L. L. ~1 x  r+ w/ n  R0 y
' c8 N" _% j0 D8 w
$~}K$@TWUD8XGKFOZ5WMLF7.png ( A8 p( _, y2 V6 g. e5 Y; I

. A6 s! U9 I% {6 g% I5 `
我们可以通过帮助文档来查看以下几个部分:
. q+ C& r/ B- T类使用的相关介绍;
, E, C3 R9 a; h查看相关类的使用介绍,我们可以先进入到帮助文档,然后在左上角选择“Search”。笔者这里以 QWidget 类为例,输入我们想要查找的类的名字,然后双击查找结果来查看说明
# C: R$ U( r/ V  u; d; A0 A: \, w4 }! {3 J1 |
PP2)_IDX51I7ZA)[@R(YYB6.png
# }' P9 q$ J' u+ F, L( K9 p
8 J6 D- b+ B! O6 J. W
也可以先将鼠标移动到想要查询的类的位置,如图所示,将鼠标移动至“QWidget”处,然后按“F1”键,即可跳转到相应的帮助文档: l& O/ \/ V, s
0 p1 C/ f6 {4 b) i, ]
ZHZC%A(RJ_L{DLXA{KCH]6P.png
7 P  z1 _9 b; ?( [
; }% C8 ~! G2 Z
我们可以通过再按一次“F1”键来全窗口查看帮助文档,按“Esc”键可以退出。
+ x3 N7 ^  W+ c+ W7 L: m0 k' c  F  Y2 h! }# T
3C33W5PFOAWO$_[8%NJ~Z5O.png
! k2 @2 m' |4 r( k; f$ v8 Z9 A/ n* E+ c! C! {
部分常用的成员元素包括以下几项:
/ v( Z9 D. c0 d2 m$ P4 g⚫ 公有成员函数:操作部件属性的相关函数;6 z9 _5 c8 t: u, K( S" ~
⚫ 公有槽函数:Qt 类中已经定义好的槽函数,直接可与信号相连接;
3 L* q3 e/ k, f9 c- a⚫ 信号:软中断,如按下按钮触发 pressed() 信号等;5 X0 l9 o: L3 b$ D8 W0 V* j
⚫ 保护成员函数:通常事件所对应的虚函数放在此处;
( `9 h- a! r5 q/ s3 n/ @8 L$ y⚫ 事件:常用事件,如操作鼠标触发的鼠标事件;+ Z, @$ G, x0 h) h2 h
. D4 F: U% v4 [
滚动鼠标滚轮,向下即可看到“Qwdget Class”类的相关说明了。
  X9 K4 K$ V# X3 S) w1 k8 b7 i3 }: h( r* n- P+ I
O{GSH6}@YO_Q_78])68O}8I.png : f$ G8 e4 [1 U  R  r1 w
# N: Q, O3 q1 H  h( F
1) 查看所用的部件的相应成员函数。
( k* E5 ?) [: A# _) i1 E' g我们可以查找到该类所用部件的相应成员函数的使用方法、功能、参数、6 \( N9 f  K2 ~- k" Z. y* T1 n) P- `& V
返回值等等,我们以“按钮”控件,即“QPushButton Class”类为例,我们通
5 b4 Y5 U5 q( S6 a; b& C0 A% Q过索引搜索的方式,来找到这个类
4 a1 r5 h% N2 C& l' a! ?
+ R- C; I' ~# B) _/ e! ?. U
1U%_{~7$WAI~)NLNJLYTQ(I.png 3 S; V6 k& s# k% ?. r

$ ?3 ], S5 C' a' Z# |4 O! u5 c2 H
我们可以通过点击“Public Functions” 来查看“QPushButton”这个类中的成员函数。
7 {$ V( n2 Q5 d3 I8 A% c" h) o8 i, @: B+ J" l: T9 Y3 O  R- p# l
F2HWVYXAL7P}5]A@)~D(DFP.png
0 W/ j( t' Y/ S5 r5 s  ]: F" c: [1 `( L+ c2 t' ]  j8 X
这里以“QPushButton(const QString &text, QWidget *parent =Q_NULLPTR)”为例,我们点击函数名字可以进入到函数详情中。我们可以看到相应的描述为:以“text”为显示内容,以“parent”为父对象,构造一个push 按钮。“text”“parent”为函数参数,由于是构造函数,所以此函数没有返回值。
0 j) a% K# R, {. ?: ^$ o
' e3 i6 ?- S( |0 h8 U9 o( i
QAS29X5%LXF`@YPFW}FH0JH.png 9 g# W5 \5 _/ W2 D1 |; w( M

* A5 z1 d5 R5 v还有一些函数是继承自其它类的,例如“Public Functions”中有 21 个继承自“QAbstractButton”类的函数,我们点击“QAbstractButton”即可查看。9 F+ v, U- ~9 a* }" k5 G
- ~. q. p6 x" S! U4 Q
点击“QAbstractButton”即可查看。  B3 C1 o$ [! @% e4 h
4 o& M1 l* L2 [# v1 A' T
NUUS]2Z5YS4SE53GVKL5EB6.png , E$ c8 m' C8 t" z

; D8 F3 H$ x8 D- X/ I2 \" _- Q0 j
@]Y`O$(`[D9NGB~15`~E8)G.png
/ N$ N+ L3 P. W- b0 \  O* W1 C+ k* n7 r: }- B" R$ s" C
同样我们可以点击相应的函数进入查看详情。如查看“void setText(const QString &text)”。  O( Z- Z5 v' j" m
; w$ R, w9 c! N# G- B
CYEU7TXQ]_[)LH9`_Z6_GYA.png / |6 P& d: R' k  D: g

! P6 Y% _4 O6 W- t2 {

9 x# E0 w. m2 w2 p* [: ^+ O2) 查看所用的部件的信号。" g0 O$ l( X' @! j! h% x
我们这里还是以“PushButton”为例,我们点击“Public Slots”。
& k" g4 l. E- q) x2 h  M$ J. e8 d" F1 t2 v" W( _: Y8 F5 h4 y
GM[Z[8OJW)I1Q7HF[9Z2]G6.png
5 b7 C/ I; U, _1 p2 m9 \" F可以看到“PushButton”本身有一个“void showMenu()”的信号,并且有很多继承自其他类的信号。
. Y) N& v' o) `) A
! i6 ^0 a6 x: y" x& E9 A
{1CRC40MNF539L{UHLA48JX.png . P! _$ P- \0 V9 r0 f- w1 V' l

9 M& j0 [) ?2 k0 U7 n8 C/ m) {

0 \" J" e8 w. V. @7 J0 H一般来说我们用的“PushButton”的信号,最多的是用到其继承自基类“
* k3 F  t" J/ L, q* `* m! Y( [' K, |0 G6 Y( K
QAbstractButton”中的几个信号,分别是点击(按下后抬起)、按压(单按下)、释放(单抬起)等。
! ~. R5 ?' H* w1 [6 ]
8 R) g! z/ C& i5 o6 Q$ _! A4 G
~B1FTK{5$GSFKI)O9TN9.png 8 y* q) x  A" ?: F

  \" ^5 D+ W% I5 W& e' [/ A: T! f6 f
我们可以点击相应信号查看详情
0 ^& ~6 ^7 f* v# M- {' q
# e/ _4 O) p8 c) m9 P7 A$ q( \
]PTTEU3FAWQNKQ5GAP82OWT.png & M$ ^* t2 K1 C" Y2 s
  F" ?* [/ u" z1 G

' l9 Z4 J3 |; p1 g+ F% n" `3) 查看所用的部件的事件(所对应的虚函数如何编写)。部件常用事件主要在 “QWidget”中声明,选择“Events”即可查看相关说明。) h& `0 J2 l" K4 x& I9 {
每个事件都对应着事件函数。
; G9 w3 U2 {! }# G# U5 M1 d/ J, G' s; k
97P10BOBQ%B)W9R{0207OFO.png
. a* Y$ b2 W0 S1 S+ ]4 D
2 X- l0 S/ y6 _$ n
点击事件函数可查看详情
( U9 W7 E% t# i+ {% a0 _: ]$ b, f) Z# ~9 p9 V
W(PX5{9X[32V@J5XL41(~1Q.png 7 X+ F5 L# _" b$ Q; V
; j& h* N$ E+ p4 O
微信小程序开发环境搭建; A- h& y# Y" M' }' O9 @
微信小程序开发工具简介

. m- P- S8 g1 T! Q! k1 \' `微信小程序是小程序中的一种,英文名 Wechat Mini Program,是一种不需要下载安装即可使用的应用,它实现了应用“触手可及”的梦想,用户扫一扫或搜一下即可打开应用。全面开放申请后,主体类型为企业、政府、媒体、其他组织或个人的开发者,均可申请注册小程序。微信小程序、微信订阅号、微信服务号、微信企业号是并行的体系。以下是小程序所涉及的技术概括:- D- |9 c3 G# |0 Y

/ n) h* h% \7 r. z/ E5 ^1 W- z
, s3 ]' F! s' k! N* Q& f2 }3 _
⚫ JSON
0 T5 A3 c* I: h  x! uJSON(JavaScript Object Notation)是一种轻量级的数据交换格式。它是基于 ECMAScript(w3c 制定的 js 规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。易于人的阅读和编写,同时也易于机器解析和生成,并有效提升网络传输效率。2 q& p8 C4 D! P: E* M+ c! h9 _
& p: z2 X+ |/ g: K5 A
⚫ XML# }. S1 N- \; W- I# F1 X: ]) q
XML(Extensible Markup Language),中文名为可扩展标记语言,标准通用标记语言的子集,是一种用于标记电子文件使其具有结构性的标记语言。; k& ~; u1 p7 o$ U0 x
/ ?% @6 b* t4 {7 e! E# v
⚫ CSS' J" B/ v! u/ H' R
层叠样式表(Cascading Style Sheets)是一种用来表现 HTML(标准通用标记语言的一个应用)或 XML(标准通用标记语言的一个子集)等文件样式的计算机语言。CSS 不仅可以静态的修饰网页,还可以配合各种脚本语言动态的对网页各元素进行格式化。
/ t5 J$ E% ^0 w' U
. \  O$ G" I! t$ g4 |7 l; N
⚫ JavaScript( H3 e2 V$ Z' d
JavaScript,是一种直译式脚本语言,是一种动态类型、弱类型、基于原型的语言,内置支持类型。它的解释器被称为 JavaScript 引擎,是浏览器的一部分,广泛用于客户端的脚本语言。) q8 Y7 A( j$ j2 L; }  C. G( B
3 x! E7 \% W/ }+ n' Z5 [
申请微信小程序
% ^+ n9 p9 w1 o2 E# C% v: U& S登录微信公众平台,注册账号$ I4 Z; X$ `. w. p! g  c

3 A# z$ E8 I* u
GUQ$V671RLHKCGUL13@71_T.png
8 y: R& h  G, e; s1 D
- b! G) `* ], [* S* X
按照步骤依次注册,输入邮箱,密码,验证码等,同意协议进行注册。
" j/ b( E5 P( L4 u7 ]5 G5 x
  n( \  ~- M- s. R3 \
50K]YY7QJXWBPHQ_K(5}G20.png ( L! z4 g; R) q7 Y( }1 R

1 h' ~) E# C2 r# ?3 `
S$E~F8WBE]O_U4M`UFMEH67.png $ {; F  B" I& y/ v1 [# C* ?

+ U3 B; E, s. }+ w
然后登录自己的邮箱,查阅邮件,点击链接进行激活。进入步骤 3,信息登记,按照网页要求,依次输入信息,身份信息,管理员微信信息,即可激活成功。# ^0 K  z% ?# P; N7 d+ Y

/ O  Y& Z% A% d3 v
返回微信公众平台,输入刚刚注册的账户密码,会需要用管理员微信扫码登录,登录后,下载普通小程序开发者工具。8 x; h6 g3 O3 w) _7 s7 R# Q
3 g1 Z+ ?! e  Q
{$Z2}M}]%WQ(`I@{@1%K8HI.png
8 m2 j; [& p% l; a% l
2 A, B3 e5 }7 r: e  q6 H/ e点击开发,选择开发设置,获取小程序 ID,以备后续开发需求。' W  k3 `. A6 E) w

1 M1 g( Z7 c' G8 ^. Q+ f/ i# j# {" w
IV(94]C]6Z~P{J0ZU)PL7V0.png
4 u# O2 D  V1 b" D& t  p+ h& |
. }1 @! h/ z, F/ t, ]5 i+ J
微信小程序开发工具下载完成后,进行默认安装即可3 C6 Q* a8 U! p' l( ^
6 j7 x# Y5 T  n* E) v) K3 h4 ?
创建新项目工程: E/ B6 d' L' W: P6 l6 C8 v
打开微信小程序开发者工具,点击创建新工程,填写自己的 APPID,选择默认模板,语言选择 JavaScript,点击新建。
9 K1 D3 a; f* s* E  u7 w( B) G0 v" A4 q+ v- ?& L5 `( P" r
9P$~CS~A2JMO{@EISZV80TK.png 9 U8 R! d' }  L# }, d  O: ~
% {% G& s8 m6 G  S, P: Y8 u. f
新建工程完成为如下界面:' r+ f% {7 p% E+ ?% b. ~# x% f

9 z) s. J& D7 O  E0 T
V%K~3U3EN3WB96K4948I1GJ.png
7 @' F' a3 q) y: z! v# x; ^# ?/ z8 h  t  h% S. f0 b6 ~. n
基本环境配置0 Y% g$ m  r4 h* h
1 Y1 Y) V" D5 `, T! c
P[(7LZJYYLB)]P8]09]SGZF.png 9 J) M& @, v' m
$ j% Z+ s7 g$ P, F9 _: Y' ?7 _
打开主界面的右上角的详情按钮,找到本地设置,将“增强编译”和“不校验合法域名”这两个选项进行勾选,因为在小程序的开发阶段,尽量把这两勾选上。
9 D3 Z& o' W$ P( f! a. R, j
7 Y1 x0 f, p3 g' f' \3 m5 t0 ?
编译、调试
( s2 ]/ ^4 ]4 Z3 o打开 app.json 文件,可以更改微信小程序的标题,改为“工程 demo”。然后按下 Ctrl + S 快捷键进行保存,即可完成编译,调试输出。查看现象。
6 _1 ]# J, q/ Q% O4 N8 p8 Z$ v# [% R1 r. a$ I- I+ D3 I
VH%$PZ6_4NJMVCF(2N[X.png ) ]. m1 }9 k, z: J: P
6 k! J# [& L$ k6 i$ e
项目总体设计介绍
# o+ C. ^6 S& z5 s) q, @总体框架
& w; T; z% R( ?9 A" C6 S智慧家庭系统的设计基于物联网的思想,物联网是新一代信息技术的重要组成部分,其英文名称是“The Internet of things”。其基本思想是以互联网为媒介,实现远程监督、控制。它在各个领域有着非常广泛的应用。7 A) F' z+ n* i8 d& T
0 O* A2 @% {7 }2 I
总体框架如下:
* k; \# _5 y1 W4 [% [
2 }+ A0 E* l/ N2 E# p7 |
4@{DJ5ZYAQ_HCBQA726SA{3.png
5 }$ j  ^% W2 ?2 Q4 a& d0 r& l2 e
$ B* ]9 O( R, y) U7 w( P2 J8 ^该项目分为 WIFI 连接模块、智能门禁模块、数据采集模块、智能检测模块、设备控制模块、天气预报模块、与百度云交互模块:下面具体介绍几个模块的功能。5 o  ?9 ^: b& m; n4 U- y4 w
8 ]; x% c& w3 s) E" _  w7 O/ z6 L
WIFI 连接模块4 X9 q8 Y8 x! t) d
该模块实现的原理是使用 wpa_supplicant 工具对无线网络进行管理和控制的功能。wpa_supplicant 是一个开源项目,已经被移植到 Linux,Windows 以及很多嵌入式系统上。它是 WPA 的应用层认证客户端,负责完成认证相关的登录、加密等工作。0 w1 T3 c* B4 Q! K8 G. }: l4 A& z

0 y- v  t' [6 c5 E% ~( K! t
wpa_supplicant 工具包含 wpa_supplicant 和 wpa_cli 这 2 个程序,其中wpa_supplicant 程序作为服务端在后台运行,服务 wpa_cli 客户端的请求,从而实现 WiFi 的配置连接。下面是通过 shell 命令去进行 WIFI 的配置及连接。, ]( l& Y0 a% l+ v
8 q9 L1 U9 u7 _- r* d& N  r9 ]( {
1.打开 wlan0 接口:
- h; K$ y* P/ \6 Aroot@fsmp1c:~# ifconfig wlan0 up
' Y0 J; j2 d6 f0 C' R) V# o+ P' q8 c7 I: y" J/ e
2.启动 wpa_supplicant 进程并在后台运行5 n9 J& x1 h8 |( I
root@fsmp1c:~# wpa_supplicant -D nl80211 -i wlan0 -c /etc/wpa_supplicant.conf-B
" e+ Q+ W- y. w, v; n/ x2 E8 Y
% n8 a- [  C0 u1 @9 r
3.扫描周边 WiFi 热点:& K$ e' M5 u$ v2 S
wpa_cli -i wlan0 scan$ o1 t$ e0 `' L: m; a6 Y
3 n4 b, Q1 p' m/ u* l
4.查看扫描结果:
( S  x% ?& f$ ~( |root@fsmp1c:~# wpa_cli -i wlan0 scan_results/ \% d1 z; C6 I$ l+ V. e4 u: ~* X

: r3 D# N( d: W  V' ]% H& Z; i' a
5.添加一个网络连接
" H0 D( a+ Q6 v- i9 Rroot@fsmp1c:~# wpa_cli -i wlan0 add_network
1 q6 S( e- `  H* B& z8 O! C; d& `! P1 b
6.配置 WiFi 热点的名称 ssid:. n% ?4 y! A; I: g& _
root@fsmp1c:~# wpa_cli -i wlan0 set_network 1 ssid '"FARSIGHT"'
- e9 D1 y7 ^, `) ]
" L& q* Q/ d( }5 H& f7.配置 WiFi 热点的密码 psk:
# p4 B! n; D' b. p, H0 B: {root@fsmp1c:~# wpa_cli -i wlan0 set_network 1 psk '"fs123456"'
  t! |. k* _' [6 }; P+ r  [" J
, K& o0 F; @( D. l5 @8.列举所有保存的连接: a! n2 A! y( }; T' o
root@fsmp1c:~# wpa_cli -i wlan0 list_network
1 v6 X+ S( y6 w  A- j6 V* }! x- u: d3 X% x
9.连接第 1 个保存的连接  B, s: ~; T! G) k
root@fsmp1c:~# wpa_cli -i wlan0 select_network 1
- j( |  o! Z' V! Y* L- y. O2 W3 G: V/ A) |/ B9 m" U* L. C
10.启动 wpa_supplicant 应用
4 b3 s1 f* q4 p( I) qroot@fsmp1c:~#wpa_supplicant -B -c wifi.conf -i wlan02 b  {$ a% f  @% g

8 Z5 j. ?- F; k3 t: G0 W9 y11.使用 udhcpc 命令动态获取 IP
1 {6 O& }% w. J8 \root@fsmp1c:~#udhcpc -i wlan0
& E0 P0 |2 q2 S" L: v8 R8 {8 \+ k6 [$ z! o9 ]. M% r% A: Z
, G9 v8 i4 {, S8 b3 L
智能门禁模块
4 P# C( E4 q& M( q1 @' Y该模块是根据关电开关智能识别有没有人来,当有人触发光电开关,会自动弹出登陆界面,输入用户名和密码,程序会自动匹配数据库,如果用户名密码错误超过三次,会自动报警;如果输入正确,则开门。
. b/ Z, s0 E, f  h7 D% U" Q
8 i! k( D5 ~7 _" L数据采集模块% T  A8 r; l5 S! P9 l; y
另开一个线程,实时去读取温湿度驱动设备文件的数据,进行计算得出温湿度的数值同样的方式得到光照的数值,通过信号传参的方式传给主线程,将数据设置到 ui 界面上。& l% _1 x. X' G
& L7 u. n: t- ]1 f# [% ?
智能检测模块3 g' _) s7 r) @( G& a% ~
开启智能检测后,程序会根据你设定的阈值进行检测,假如温度超过你设定的温度阈值,会自动开启风扇;或者当光照低于你设定的阈值,会开灯提高照明的亮度。
$ [# f' l- w- e; T9 F* H# P& D
$ j3 C3 O- v) h; t8 d; P! t% t, r/ |
设备控制模块
- O. _8 K- Q0 B5 S$ j5 @: m通过 ui 界面的按键去开关灯或者风扇,以及蜂鸣器。: r' O, L- G4 K' i1 c, D
! Y$ B6 I0 B8 U. w' A0 E
天气预报模块& m4 y$ p: {3 U4 o2 F2 f
连接 WIFI 之后,通过 get 方法从网上获取信息,得到 Json 类型的数据,对这个数据进行解析,将解析到的数据设置到 ui 界面上面。
6 V) u! l! ]6 D" Q( d3 V. e3 r
& G! L- O" c' V+ E# ^6 p
百度云交互模块( |. C! S6 S2 C$ [
在 ui 界面输入在百度云创建设备时的 IoTCoreld、DeviceKey、DeviceSecret(三元组)通过组合生成 addr 和用户名,使用 MD5 加密算法计算得到密码,用于连接,连接成功后开启定时器,自动向指定好的 topic 发布采集到的温度湿度和光照,并且订阅云端控制设备的 topic,用户向云端发布json 数据,开发板接收到云端转发的 json 数据会做出响应。如{“led1”,1},开发板收到数据后 led1 会亮) [" Z" p0 Y7 Y3 s7 M

1 N) _+ ]7 @. J! i1 D" w8 J5 |
源码分析
% g& [1 L: p" Y0 w2 j! ^WIFI 连接模块! T  L5 P8 I. f
在 Qt 程序里使用 system 函数来执行 5.2 的命令来实现 WIFI 的配置
' n* E  m; D8 y# y+ Y  }
2 Y1 _/ M: i# e. o3 b) G# e
GMN2XFQ21XQZ2_8SU2`_LAC.png
$ _+ \0 Y* A0 o/ [1 Z+ q3 S6 z& c# Z, {& J
建立刷新按钮信号槽连接,实现点击刷新按钮界面显示附近 wifi。实现原理是启动 wpa_supplicant 进程并在后台运行,扫描周边 WiFi 热点;
+ H4 s. X1 K1 J( e
$ m' n$ E: ?8 P% B# j- L& k
使用wpa_cli -i wlan0 scan_results 命令查看扫描结果,并将扫描结果重定向到wifilist 文件中,对 wifilist 文件进行读操作,将读到的数据直接显示到 ui界面上面。核心代码如下5 E  V& M  U+ \5 x* T
) }: q8 G  K# G+ k9 N1 e
……! |# r' g1 q% S2 ~

; V+ w/ ^: e7 h  T
system("wpa_supplicant -D nl80211 -i wlan0 -c /etc/wpa_supplicant.conf -B");5 X5 s/ Q6 h0 `% v  ?& `- g( h1 T
system("wpa_cli -i wlan0 scan");
) B5 }3 V2 s3 @6 ~5 R: Z3 ~system("wpa_cli -i wlan0 scan_results > ./wifilist");
* ~0 g( ^9 z2 h! w; `( ?8 nusleep(50000);; P; T5 V/ a) K
QString fileName = "./wifilist";7 m6 z4 P  ^- ?
QFile file(fileName);: i* W/ a. p8 E/ N3 g
int f = 0;
' Y. ?& n3 z8 p! f: v" d j = 0;. N$ K& |3 E! N. M6 C
if(!file.open(QIODevice::ReadOnly | QIODevice::Text))  _2 Y, c# J) [- A) c, P
{
; B; A8 B% o/ C& N QMessageBox::warning(this,"Warnning","can't
2 u( N5 _$ Z7 s$ R% d" kopen",QMessageBox::Yes)/ e3 K4 i& w" y* s8 i: @* M
}
1 K1 h; w: S) T- p: B& Q7 n: g' S QTextStream in(&file);
$ S+ p$ U7 ~. a7 U& q+ z QString str;
9 E! n; }+ C! Q/ y8 [/ H& I5 A2 r/ t while (!((str = in.readLine()).isEmpty ()))' X8 L* |, {1 J8 h/ D
……3 g. v- Q. h0 V* k7 N1 w+ h' l

2 @0 C$ A. w: g/ T

8 q4 c0 l1 y$ C. F/ q$ m2 r8 ~0 M" Z连中刷新后显示的 wifi 名后,点击连接会进入二级界面。二级界面输入密码正确后点击连接,等待几 s 后即可完成连接。这里输入框使用自定义类MylineEdit,继承自 QlineEdit,增加了鼠标点击事件,当触摸屏点击输入框的时候,会弹出软键盘,用来输入密码
0 e. J5 n+ C# Z2 q

% x9 g# G1 ?; ~) H( B( [9 M EL{X(8C[6Z[B5K%RN`U9[]8.png 9 @4 Q* n5 J* x) m( w5 D5 x

5 N6 c2 \! Y  M$ o
4 |% m! ^% y" G6 e  x6 C, X
这里连接 wifi 的核心代码如下:
% X1 W8 }" D3 V3 N% k
  y$ f( h( ?! o# p( F8 p

1 |3 }! {# X/ C
  1. sprintf(set_ssid,"wpa_cli -i wlan0 set_network %d ssid
    ) w3 [4 ]4 u' h  E! T
  2. 0 v( U9 K8 o- P! z1 {  Z
  3. '"%s"'",i,wifiName.toLatin1().data());: C  \6 X3 a9 T
  4. / {4 B+ {; R/ \* M
  5. sprintf(set_password, "wpa_cli -i wlan0 set_network %d psk '"%s"' >2 H, k3 Q. M$ s( B" m

  6. & f# Z# r- ~; K. a: i
  7. TorF.ini",i,password_edit->text().toLatin1().data());
    , p" J! m2 d7 }

  8. 8 M5 w; O$ R$ E5 _2 q
  9. sprintf(select_wlan, "wpa_cli -i wlan0 select_network %d ",i);
    / W  L+ {7 V% A8 x  a  [0 x
  10. 4 V3 o: s0 g0 q: e& u5 {
  11. system(set_ssid);
    6 Z2 P, ^. X8 b) g) }
  12. & ^* O$ v7 w1 c  L' ?
  13. system(set_password);
    . p" a* x( s# ^: F( H2 A% t9 ]8 u7 p

  14. ) K1 [# R- [! `) D5 ?
  15. system("wpa_cli -i wlan0 list_network");
    6 N7 n1 t* W! F% f) m

  16. 3 q) g+ L8 ]' D% Q
  17. system(select_wlan);
    ) m& p! Q( k- P- c5 W- T$ Z6 w8 @% F

  18. ( F; j/ I4 Y8 k# m( [$ T. ~9 Q
  19. system("wpa_supplicant -B -c wifi.conf -i wlan0");" m5 t( i5 @% S6 Q

  20. ' g& e! y* P. u, v" n- X) N
  21. qDebug()<< get_TorF().data()->toUpper();# q0 Y$ E0 U- H( K+ w5 Q* p' V
  22. 8 `+ m& g0 g: [1 Y/ v
  23. if(get_TorF().data()->toUpper()=="F"): q, P1 T8 k5 F6 J8 A
  24. ) R( C! u1 I  ]$ o, F1 s2 z
  25. {) `% l2 F' z+ i5 Y% O7 y

  26. 3 L( L- l3 [2 y6 V4 p8 H4 N
  27. QMessageBox::warning(this,tr("Connect information"), tr("密码% B) t5 J6 B$ C/ E3 @' ~
  28. ' ~+ e2 k1 [6 F0 p$ R; z1 \
  29. 错误"));
    * J( P2 D( X7 w7 @; I! c9 X- \
  30. 9 B9 V! {5 q2 T/ [0 W9 W
  31. return ;( e/ p- `0 F# x* D
  32. 0 [( _6 g! u: X$ y* D
  33. }" R! q! u! q1 K  E7 a

  34. 6 U4 L# b+ x+ s& {+ q4 U2 U
  35. system("udhcpc -i wlan0 -B");
    5 H4 K4 f- |8 n. A+ [$ {
  36. 4 K5 ~/ n! I) F7 x0 P2 B
  37. char echo_1[64];
    . v; C% l$ a$ L$ P
  38. 1 A1 f' p6 N, H
  39. char echo_2[64];
    9 w: ?" Q' |" o8 p

  40. + I, x# L# Y5 _) x4 T1 T, n- C
  41. sprintf(echo_1,"echo "nameserver 114.114.114.114" >! I# Y4 J0 \& Y2 o: Z4 C

  42. 2 b- G- V4 o. |5 V- X
  43. /etc/resolv.conf");
    ! Z6 \% u+ L* \2 L
  44. . D. n3 N. N; r& B
  45. system(echo_1);2 u) O8 `# ^" n
  46. . }3 Z+ i! ]9 {# H
  47. sprintf(echo_2,"echo "nameserver 8.8.8.8" > /etc/resolv.conf");1 D% M- x% i) b6 r

  48. ! s* p9 d# Z* q! `
  49. system(echo_2);
    ) M$ g. u& P4 r* k* A4 [* B
  50. 0 X. ?; s' a- ~7 u/ D0 r0 J
  51. close();2 Q) l* \* r9 P) m( O
  52. ( ^3 H3 Q9 v* ^
  53. QMessageBox::information(this,tr("Connect information"), tr("连接成8 E/ v/ u2 \' d" u+ N! C
  54. 5 r* y2 |0 v7 [) p
  55. 功"));; i1 y. i( Y/ i# y+ b$ h% a
  56. : g& s: s! K( h$ x* \
  57. }
复制代码

" _/ K3 i. l8 Q' U$ U0 I  ?6 P& e/ N4 ^' b
智能门禁模块
( L' A3 h3 Y, R- F) b) A5 p; [3 `) k- ~3 f$ d! @5 w+ }8 _
]5RF`O{20C45JT5@87([)XM.png   H8 N5 e7 [. [

6 x# i7 B3 @) O1 ^5 g) e5 K' O+ gPanGu 开发板有多个 GPIO 组,查看 GPIO 组信息,可以使用 gpiodetect 命令。3 \; h* @7 V& q/ ^' N+ Z% _% G
  1. # gpiodetect' b& t3 ^+ t* f5 o
  2. ; l8 P3 a3 v9 s, |
  3. gpiochip0 [GPIOA] (16 lines)
    ! j3 p; L; i" R5 L  F
  4. ( N) k1 X9 {5 m2 s4 _' F4 c: r  H) l
  5. gpiochip1 [GPIOB] (16 lines), w4 s+ o5 x6 [+ k/ ^

  6. 3 k* O3 `: [5 ?2 C% n6 f' E; R3 r
  7. gpiochip10 [GPIOK] (16 lines)
    6 w2 f4 }" D. _* L
  8. * i/ @, W* o6 b1 K
  9. gpiochip11 [GPIOZ] (16 lines)
    . d' @+ A( W: T: W% z- t
  10. 2 c2 ^1 {' M! {
  11. gpiochip2 [GPIOC] (16 lines)+ T: k$ [4 J- U9 c' g& H1 e
  12. , b, [/ W# P- I  ?
  13. gpiochip3 [GPIOD] (16 lines)
    # [+ W* a3 j6 K5 h

  14. - t# i8 n" h3 r  b# b) s  m+ L5 n2 L
  15. gpiochip4 [GPIOE] (16 lines)
    ! q- [$ ], b4 E8 g' [" E

  16. 1 r2 p  f- P3 O3 q9 x; K! z; v
  17. gpiochip5 [GPIOF] (16 lines)) `0 Z0 P5 g: b0 e6 _! Q- B

  18.   {+ C7 Y( a2 b
  19. gpiochip6 [GPIOG] (16 lines)
    / h$ C7 v' s, }9 x2 X# n
  20. $ ~* g' S  T; T2 d; p  _
  21. gpiochip7 [GPIOH] (16 lines)
    1 K/ F9 s) a( n* X: \; M% e3 X
  22. ! }  K+ T4 I! a- N# N
  23. gpiochip8 [GPIOI] (16 lines)
    # p7 Q  c6 z7 B

  24. 3 E6 M3 E( H6 A* j! ^% j$ M
  25. gpiochip9 [GPIOJ] (16 lines)
复制代码

* q  }0 j" D8 E/ `5 J6 @9 ]通过查扩展板的原理图可以看到 :光电开关的 GPIO 管脚是 PE157 y9 z3 m& M3 e8 d
. _, a/ u# \; R7 ~1 ]0 t$ x* f7 ^
读取 PE15 的状态4 m9 T$ k8 B1 u

% G! V8 s0 P, r" }8 ]# gpioget gpiochip4 15) ]/ ]; v( ]- G5 A- @

/ b6 F+ W7 ^( @% U4 S当有东西遮挡光电开关时,执行以上命令得到的是 0;没有东西遮挡。得到的是 1.# T# p7 }# p  v
7 E+ o, A! D7 Y/ t( U% {0 y, d
所以我们开一个线程让它一直去读取光 PE15 的状态,当读到为 0 时,说明有人,发送信号给主线程,使主线程开启登陆界面。8 r  G9 d, s+ s5 f, b
  1. void ReadPE15Thread::run()
    0 x( T2 ]; J: R' D/ L
  2. 8 v- d' M1 |5 `8 j4 H+ N
  3. {4 W' ]6 K( l" R- f# Y
  4. * k# d. z9 t; b- m/ ^
  5. system("touch pe15.txt");
    4 P1 `/ f. Z4 B0 G0 S( F5 K
  6. 7 H. s- M. u. d4 o# h" {
  7. system("gpioget gpiochip4 15 > pe15.txt");
    * M$ r; [9 W% B/ x2 ?' e
  8. : t  K* h# @, \
  9. int fd;
      l5 u5 c6 W- N$ ?5 J' x) m9 G

  10. ( l6 N7 d7 h: f0 S1 _
  11. char buf[32];) J6 o2 P8 i- @  T8 U, Z* ^
  12. ( n" X  N0 P" n6 o2 B( f
  13. while (1) {
    # r* o% L5 E  N! Z7 _# K# j
  14. * \  Z4 Q1 e, b
  15. fd = open("./pe15.txt",O_RDONLY);' t" D+ h, A; G% Y; C) }9 o. a8 c' J
  16. 2 o% \6 i+ {; l6 a5 S1 J6 i+ o/ ]
  17. system("gpioget gpiochip4 15 > pe15.txt");
    # f* K2 V: O, Z, f  i2 B
  18.   U6 i' j* J2 t% d4 h' R
  19. read(fd,buf,sizeof(buf));
    5 L1 \( U& v- ~) o& N& X7 R
  20. 7 g  {  W9 X. H* E
  21. if(strcmp(buf,"1\n")==0)9 l5 U6 R) t$ T9 |9 U

  22. & P- C! }! y7 A! n3 t: g9 c
  23. {5 ]$ y* `, q. J. j& z& _# E

  24. 6 Q7 I& @% Z: z, K
  25. qDebug()<<tr("login !!");! Z3 z7 d( r' F1 d6 H
  26. ' T- H# A0 N5 S: R8 ~- ^5 Z
  27. emit pesig();
    # t! z, x: n" M

  28. 8 ?7 F, ^# M% {2 h" ?, n" ?
  29. }- ]# W! I6 w# e' Y
  30. : A% n& N! N  X9 ~& P
  31. sleep(1);
    6 h* d4 b2 B2 n3 V, `9 }& A# @1 ]1 W

  32. 8 G, ^# b- U/ S, x0 @7 D
  33. close(fd);
    ( ^8 \+ i  |. ?$ e$ c' I$ k$ f
  34. , x, v  s! \8 z  ~; P8 F
  35. }  R: Q! ]4 o, w% a
  36. 7 A/ |2 ^/ M; Y+ E; U$ j5 P
  37. }
复制代码

2 c: V0 g2 a! S6 s& |建立信号槽连接  _* g: Q$ {( r( ~6 p
  1. void MainWindow::loginSlot()
    5 I! q5 {4 o" Z: {

  2. ; s% |, z, M. G4 k* z+ z/ I
  3. {
    $ V% }6 `" d8 u4 A( x) x: ?: n6 H' {
  4. / W5 I6 l1 v' f' z, v2 G& ?
  5. disconnect(&pe15thread,SIGNAL(pesig()),this,SLOT(loginSlot()));4 K' U4 j  N% ^0 |1 C# b* @' V- V: R
  6. ! m# X3 S- X' }1 r5 Z, q0 B: ?
  7. login->show();
    1 o1 A& T  ~6 a: X7 e

  8. - p9 Q& ?4 i( c1 I4 X
  9. connect(login,SIGNAL(loginsuccess()),this,SLOT(loginsuccessSlot()));" m3 [7 [5 I6 _6 b

  10. " a( g; W, D, j* o+ i# `5 s
  11. connect(login,SIGNAL(loginfailed()),this,SLOT(loginfailedSlot()));
    1 O+ U" P6 M1 {! \2 G% o
  12. : J+ P3 I6 {1 |: @
  13. connect(login,SIGNAL(loginclose()),this,SLOT(logincloseSlot()));9 D- u. n+ @' e+ y9 z0 X- U

  14. ' \" U/ Y# t% O
  15. }
复制代码
$ f" j( F% K- M$ S; r: n
登陆界面的编写* \* U, K' u2 c% J
9 ~9 t, F6 p1 y8 [/ @+ ?: d: X" U
编译 UI 界面。3 v3 A) o! q$ b* E; P  S
0 @5 L2 t/ U" V1 E1 q0 E/ R+ G# l
创建 usr.db 数据库文件/ y- z% U$ c, |2 G$ [1 m
( E( ]% Y) G' M* ~" `) A: A: D* b. P7 a
# sqlit3 usr.db
7 A+ F4 L( f! z6 T4 a
0 R  v; G) v; R6 N/ C6 c创建表; M5 ^& K4 p& Z- y

; w6 L$ h8 W. n& V9 psqlite> CREATE TABLE usr(4 a" g* C: r' w. ]. ^8 @2 Y

" C7 t6 j# f1 _+ T# s3 f usrname TEXT PRIMARY KEY ,
/ p5 s6 u" B7 g. q
. E5 N6 e3 g2 q0 G password NOT NULL
/ Q, |1 a+ [; g
5 l1 D* o' Z& {- X# w);
) J: {; L5 p6 ^2 [' Y& b
' v2 g5 F8 |# \: t9 v向数据库中添加用户名和密码% H- p0 e6 R# x* O. Q
4 c* t' |# S: L2 R, j9 _
sqlite> INSERT INTO usr values(“usr”,“123”);
& ~! ?0 |7 W4 K) P% K. w; i
) Z2 ]0 @2 X0 qlogin.cpp
& ~* V: o2 w% R+ b* q, z& Z7 B: K; r$ N, @- b, J
打开数据库 验证密码( g& w) ?- X9 F6 m& e9 _9 [8 B. z
  1. bool Login::openDb()$ T( t/ R1 `$ f, i  r4 f8 D! o' v

  2. 5 `( f% B- w' M( l
  3. {
    & r8 t+ k' }5 U

  4. 7 _8 U$ q# L  @" k
  5. QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
    . `, H, O. X' x3 K3 _
  6. " B) O7 Z$ }) p- y
  7. db.setDatabaseName("usr.db");- `$ ]4 e& |1 M

  8. 7 T  U8 Z% V3 u, u- p8 H1 w  j  U' t
  9. if(!db.open())
    % k, h) K& q( p8 h" I% A( [
  10. 4 Q% T$ \+ M* v2 r( w
  11. {
    ; j  I& S! H4 Z  c, R7 J7 v$ m
  12. 4 o  V# X9 I" O2 u
  13. QMessageBox::warning(0, tr("Warning"), db.lastError().text());
    * K1 B4 y0 F, V4 B& ~- C

  14. 8 C9 v# ]5 i- k7 r; y
  15. return false;$ t0 {4 ~) N* M1 }
  16. ! Z& x; e2 w, P  H
  17. }1 }% S5 L! ~# i2 a1 U4 r. U  |. Z3 m
  18. 5 y! W  m5 m' E# ]4 ~$ p$ o
  19. QSqlQuery query(db);7 H# C& i3 l# W- n8 |% M
  20. 3 F# a5 j5 t( c# y+ _; Z1 s# y
  21. if(!query.exec("select usrname,password from usr"))- }7 W. G: L8 J0 l: M, M

  22. 4 _( q: w/ b) }
  23. {) Q# d! C! r+ Q
  24. ) W% U- K. O% y" f0 ^
  25. db.close();+ b+ t& `( p* r" n
  26. 3 D; {# @  g! c4 J! I+ n
  27. return false;$ c" |3 Q/ t0 t: y+ `1 D: z

  28. 0 Q- j% Y5 s9 V% k* L* a2 P; i7 U
  29. }
    0 p# |3 N- w" o

  30. 6 \4 g) Y( K* v$ `
  31. while(query.next())1 v. l4 f4 T" i
  32. ' [4 H. T( Y2 O: ^5 w: P4 ]
  33. {
    2 k' _( K. x7 h0 A* E
  34. : j* f6 c5 m3 O: \1 D* E% k( @. z
  35. QString UserName = query.value(0).toString();
    5 `2 [5 x/ N2 t& u

  36. $ _1 _8 O! h# B7 v7 r3 z& D
  37. QString Password = query.value(1).toString();
    : I  a: ^+ r2 l

  38. 6 n  P, E0 h6 G1 h
  39. // qDebug()<< UserName;2 m" M/ F7 m& i

  40. ) u8 ^) \# Q9 t! T" S- L- O
  41. // qDebug()<< Password;
    ) q3 N- i6 n- Y1 M$ h$ r
  42. " L& m+ P. y4 d6 ]
  43. if(UserName == usr_edit->text() &&Password ==password_edit->text())
      b3 M! }& H$ m. X* S

  44. " r" X9 M9 @* m; Q8 w
  45. return true;: H; G$ S, P/ d* W- ^

  46. , e4 P; i' _) O: X4 C: |* F9 _2 L
  47. }
    - O6 u% |% [) n3 U% w( u* g' r
  48. / l9 p  b, B/ g! X3 }9 Y9 D
  49. db.close();
    - d$ N% A" Y# a! t* j
  50. ' j" v( ^; O0 b6 U' p
  51. return false;# J. T6 R" e4 }! [2 M+ B2 s: d+ f0 y
  52. / z0 Z4 u7 N8 W  Z
  53. }
复制代码

+ I2 X4 C! T* d, C1 W2 g. h. {' t
) A% H8 Q+ g" r7 T  p登陆成功发送成功信号,登陆失败发送失败信号
' Q# `9 t% O/ `3 w% x* j% D
  1. void MainWindow::loginSlot()
    ) ]7 U8 p# F9 M3 Y
  2. $ Y# R" O6 ]4 A& _
  3. {3 {9 _; Z0 l. p" t2 q" A
  4. 9 s  U' C3 r: R7 h
  5. disconnect(&pe15thread,SIGNAL(pesig()),this,SLOT(loginSlot()));2 i: H7 U8 w  d) [/ w+ g$ l2 h

  6. : ]0 E, `+ a3 X
  7. login->show();
    . ]7 B8 s1 d; ^' ^. n# p" T

  8. ( R/ u; b) _" h; [1 ]
  9. connect(login,SIGNAL(loginsuccess()),this,SLOT(loginsuccessSlot()));- M* G" j# T7 R4 e! t1 H# h

  10. ; q/ N6 A# w$ e% E* l& w. |
  11. connect(login,SIGNAL(loginfailed()),this,SLOT(loginfailedSlot()));
    ! G9 d/ ]' b- i

  12. 4 q" u2 ]2 P% g
  13. connect(login,SIGNAL(loginclose()),this,SLOT(logincloseSlot()));
    . h2 [" w% a1 R

  14. . n( T1 A; h" @; w
  15. }% M# x0 T6 ]7 n
  16. 6 t" o8 V+ G! r
  17. void MainWindow::loginsuccessSlot()  v- H/ M  f' a; S  [: y

  18. ' @: |; \9 ?1 m, Q! N$ w! ~
  19. {
    7 U* v; Q, e6 ^  C4 A8 A$ T( q

  20. * s6 T* t$ i; i4 u
  21. QMessageBox::information(this, tr("information"),"密码正确,门锁已打开");
    & }; Q) q- W1 y& Z' T5 X
  22. ) o9 J7 v! R% A4 }- f. T& N! Y
  23. // 重置错误次数
    . ^7 @4 A' V) L( m( I

  24. 5 \8 c7 L% @# u) Q/ A3 A3 T
  25. Numberoferrors =3;
    8 y  O+ `, S- Y, G& a

  26. * X' m9 N7 i  [
  27. login->close();
    ! N$ v! H  I. v! _3 C9 o6 C7 i

  28. * `) @* E& k3 z/ g4 D, f5 y1 y
  29. beepunring();2 n& ]3 _& \+ x  V
  30. 4 N5 I5 O4 w6 i, p
  31. connect(&pe15thread,SIGNAL(pesig()),this,SLOT(loginSlot()));$ _$ z* o3 W+ P  r. j6 Q: u
  32. / O  P8 y% E: {% h) p
  33. }0 @0 Z+ Y, u9 a/ c: w. r
  34. $ v2 R7 N. u) B3 P) W
  35. void MainWindow::loginfailedSlot()
    8 k7 C8 p' l% w4 S; l$ s# e
  36. 0 d* `2 C' ?- G8 w
  37. {
    2 g( M* U1 e0 s; h

  38. ' j# Y* a. U! E3 G  z
  39. QString info;
    ( Y- P; F( }. v, b

  40. 3 i8 G+ v- k7 Q2 o
  41. Numberoferrors--;5 @3 j) {3 x3 t3 q

  42. 7 O, o$ g% q% _! P( r1 @, [( E3 T
  43. switch(Numberoferrors)
    4 o! {0 b4 n* M' P/ B5 }

  44. 9 S- o0 c. C( Q5 \3 p/ I! x
  45. {
    8 Z& U* W; ]: X
  46. . B. {- e3 v; R6 X
  47. case 2:, i: j9 b, B: f

  48. ! X7 j( O# i0 S
  49. info ="密码错误,还有 3 次机会";9 i! V4 u  s4 @0 w

  50. 0 i* A  W; T: Y
  51. break;
    ! T3 c+ |1 h* W
  52. & T0 u6 L% d* `4 g5 q7 H9 K6 U
  53. case 1:' D; o2 n% {0 S3 k1 M

  54. / H( S. |% S( }
  55. info ="密码错误,还有 2 次机会";2 s2 \: e' ~! \" f

  56. 7 M/ M! I6 e" q3 f. d
  57. break;: C( G7 u6 o& g# i: J  b

  58. . p0 `% Y) |8 x( y, |: d9 M5 d
  59. case 0:
    0 c4 {2 X; u/ O! D/ {; }! ^
  60. % N' N' G& g% N2 L% g# @  }
  61. info ="密码错误,还有 1 次机会";9 X$ w3 y: F' H9 F- ?+ G* O

  62. & S9 @6 c  c/ k, t
  63. break;
    : F1 K, h4 j2 H- {0 ^" ~

  64. 9 N, H2 j- @$ F1 d2 \* F# G
  65. default:' u' I% S5 S, @2 _% }
  66. / f* }% L( S: D- p; X9 q% b; O
  67. info ="即将报警";2 ?2 v2 j; Y( g
  68. $ M* |; x! s# _
  69. break;# r# H/ Q' c  d* j7 e( S( s
  70. & n8 u& L, u$ J6 z
  71. }
    , X) t4 i  ]8 E0 n0 n

  72.   f, j+ _( Y& h1 g& k
  73. QMessageBox::warning(this, tr("warning"),info);
    ( W  C) D- Z: ?# O, A

  74. 3 h, f  S' Y6 p7 J8 J" M
  75. if(Numberoferrors <0)
    4 p' V5 E4 A9 p. g# |+ R

  76. - k( r# T# A3 r( @$ D) c6 `0 N0 M* X, f
  77. {
    0 W& Q3 a8 L0 N4 g

  78. 1 v& b9 a: a8 k/ _
  79. qDebug() << Numberoferrors;. M. [" c8 q% d) J

  80. " j' i+ j' q( b  \
  81. beepring();
    ! {6 q) K& j" [* Z

  82. 2 e1 t, G! ?+ M" o  e$ k) f# T; F
  83. }
    # m$ ]2 T) m4 I6 J5 ~+ l* U

  84. 6 V- K0 s/ d  Y
  85. }
复制代码
3 L) m8 M0 g  U% h
验证密码错误三次后蜂鸣器报警
8 A: i& W( f5 T5 Z- G" A5 s% h  K' z) l! |& i6 V/ b% p
数据采集和智能检测模块
6 X6 [7 y, D1 `# u2 f) W8 t5 f  J
系统启动后可以查看目录/sys/bus/iio/devices/# W5 j, m$ t! |: R
8 H% `5 _4 k5 E! C! L! k$ e
root@fsmp1c:~# ls /sys/bus/iio/devices/ iio:device0
# d2 f: k# @# X7 K- q
6 ~9 x: n  j4 H+ S# R9 e; Y& x! o如果系统中有多个 iio 设备,这里可能会有很多个 iio 目录,确定哪个
$ b1 Y8 H% \; m4 l" [" C

7 F  O9 k" o% E) K' B目录是我们的设备对应目录,可以通过查看: W: v# b$ Y, X. Z

( Q6 u3 [- ^& ?1 k. K+ h2 Z; Q$ {! S/sys/bus/iio/devices/iio\:device0/name 信息确认:
6 t6 P& a  e, u8 }+ x3 [! ^5 l& B4 }* ~( v5 x" g8 d3 f
root@fsmp1c:~# cat /sys/bus/iio/devices/iio\:device0/name
1 \; _+ J) b" h. m# v. f2 U" A' q! U
$ X1 k, @+ ^6 J; ^! ]0-0040
& J8 w. j# N% x
' R6 e4 m$ u; T/ \$ R
由显示信息每个驱动对应设备可能有所不同,当前显示内容为设备的物理
* G5 ~  I+ `+ Z; b8 c
" Y2 R/ ^9 \% _% v4 g: |& U/ X
地址,与设备树中地址一致,可以确认 iio:device0 是当前设备对应目录查看8 f. s3 O# W$ X% x+ T
9 _5 x+ _; @" \" D1 e, ^. d
当目录下内容:$ H- D5 I! ?, T
  1. root@fsmp1c:~# ls -l /sys/bus/iio/devices/iio\:device0/* a/ ~4 u6 t+ m- L$ A$ E
  2. ; M3 }/ F; P9 j0 H) E& n% H9 f
  3. total 04 F6 T) {% B$ x7 _6 @% H
  4. - J9 e4 S" ^# P8 Q4 D- n
  5. -r--r--r-- 1 root root 4096 Feb 7 15:51 dev
    # w  J! e$ j3 P" G( T

  6. $ v3 C- e8 I! h- r
  7. -rw-r--r-- 1 root root 4096 Feb 7 15:51 in_humidityrelative_offset0 y: v! h% I8 I: N- W7 e7 f
  8. 2 y1 Z9 t. k$ r1 E2 \/ A( c
  9. -rw-r--r-- 1 root root 4096 Feb 7 15:51 in_humidityrelative_raw9 C% }+ M5 S1 m2 ^" G  e( D
  10. $ {# N# W5 w+ ^2 q% h$ n  x6 e
  11. -rw-r--r-- 1 root root 4096 Feb 7 15:51 in_humidityrelative_scale
    2 b) P. g( l6 n7 q, p
  12. ; A' {! F0 u/ j6 q* ]' Y+ P5 o/ L
  13. -rw-r--r-- 1 root root 4096 Feb 7 15:51 in_temp_offset, T& {% N) v7 s$ f% E' m' g" l: }

  14. 6 f  c0 O, B2 G' U
  15. -rw-r--r-- 1 root root 4096 Feb 7 15:51 in_temp_raw
    / x0 R9 _/ u. x7 k5 B9 q0 Z! \: Q

  16. ) F+ f9 l2 ]" H( f; T( O9 E: {$ }
  17. -rw-r--r-- 1 root root 4096 Feb 7 15:51 in_temp_scale9 P- o$ b. c. R8 F* \

  18. . y! }; F; B: p  i$ E+ s' `$ {
  19. -r--r--r-- 1 root root 4096 Feb 7 15:51 name
    8 w8 r' K& w# y# D# t
  20. , Q- w) w, o7 u) A1 r
  21. drwxr-xr-x 2 root root 0 Feb 7 15:51 power
    7 L( C/ G6 N& H( K( ]
  22. % k9 f* c$ C# @& o2 M
  23. lrwxrwxrwx 1 root root 0 Feb 7 15:50 subsystem -> ../../../../../../../bus/iio
    : s9 J/ m  D; s# J/ f3 g
  24. : ]) Z" `7 m& A% q: ~3 o
  25. -rw-r--r-- 1 root root 4096 Feb 7 15:50 uevent
复制代码
- ]/ R' E! Y% P; }1 t

- O; @# c/ c, t0 A& z" y0 B9 t转载自:华清远见研发中心
# p. S; ^7 |' \
- g/ ]2 P) @, H  r8 V. G9 \/ H/ c3 [+ z  `- d  }$ z
收藏 评论0 发布时间:2023-2-10 15:21

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版