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

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

[复制链接]
STMCU小助手 发布时间:2023-2-10 15:21
QUYJ`TB]SDY048IU{DTGNPI.png ; x0 A8 {# p" |: [7 o
: N1 ]- {% A" w% Q0 K* v
stm32mp157开发板FS-MP1A是华清远见自主研发的一款高品质、高性价比的Linux+单片机二合一的嵌入式教学级开发板。开发板搭载ST的STM32MP157高性能微处理器,集成2个Cortex-A7核和1个Cortex-M4 核,A7核上可以跑Linux操作系统,M4核上可以跑FreeRTOS、RT-Thread等实时操作系统。开发板搭配仿真器、显示屏、摄像头、资源扩展板等丰富的扩展模块,可拓展物联网、人工智能等相关技术学习,还可以拓展丰富的项目实战,非常贴合企业当下开发需求,是一款嵌入式Linux入门进阶必备开发板!
( H( g; k$ C! h% T0 X6 d7 c
4 y" m4 I# Q( P5 [) o( V2 P7 U可学习技术:嵌入式Linux应用/系统/驱动开发、ARM裸机开发、Qt界面编程、STM32单片机、FreeRTOS、人工智能机器视觉等。. Z) N9 ]# \! E
9 [% W. B1 i7 B
QWI[0A~{`_9QWBZAXQ[Q@@P.png
/ B0 O: e7 q2 O& I4 |! n
/ |3 [, d6 Q7 V) ~6 c* j可实战项目:14个Linux+Qt综合项目案例,8个MP1A物联网拓展项目0 C. E2 q6 u3 z8 c
7 l, l5 z& D! e
1、Linux+Qt综合项目案例:华清远见stm32mp157开发板优势特色部分,包括音乐播放器、智慧家庭、智能工业电表、智能出行助手、智能猫眼、环境监测、智能安防、智能语音识别等10余个项目案例,涉及家居、医疗、农业多种应用方向,在案例中使用了多种物联网和嵌入式技术,包括OT开发、linux应用开发、linux驱动开发、物联网云端接入、MQTT协议、json字符串等知识点。  f, v8 A+ |: |
6 ?2 Z( ^' q1 a+ V& x+ I
基于Linux+Qt的智慧家庭项目
: V1 P; f$ c0 G' ]( A9 I) L. O9 O
项目简介:
# C. m- }4 X) R: f& C智慧家庭又可称为智慧家庭服务平台,是智慧城市的最小单元,是以家庭为载体,以家庭成员之间的亲情为纽带。智慧家庭综合利用物联网、云计算、移动互联网和大数据等新一代信息技术,结合自动控制技术,将家庭设备智能控制、家庭环境感知、家人健康感知、家居安全感知以及信息交流、消费服务等家居生活有效地结合起来,创造出健康、安全、舒适、低碳、便捷、个性化和充满关爱的家庭生活方式。* W. b, P9 |6 \" l( W; W

( o+ N' z3 o% E" j  b

/ Y% N8 f$ W5 [0 ?& y$ b! R开发平台:/ k0 x. X  Y( H# W$ b0 n. b
华清远见stm32mp157开发板豪华套餐(开发板+仿真器+五寸屏+摄像头+资源扩展板+tf卡+读卡器)" B6 r  f& @5 D+ I' f2 l
/ F- f% q4 g. U# V- ^. G' R2 T
项目功能展示:
* ^7 [# k2 E4 _, Z+ S! GWifi 模块
) O* f) c, _5 Z. T9 W$ [) s点击刷新按钮,可以实时更新附近的 wifi,选择要连接的 wifi,会弹出输入密码的页面,输入密码,点击连接即可连接成功。
) T0 U  I4 G- ^
3 H1 P! L9 w7 G# J- M3 Z
SVCIYPP{%K$@1`6~12X]]1P.png
; ^9 b3 }8 r. {6 ~1 K- i% e: {: R9 I/ ]; C# J
{5BP8C5(JF(]MIQO$@UM}UP.png : t6 K4 Y7 r4 f
6 B* {7 s: C& \+ @* G7 I
选择要查看天气的城市,点击获取按钮8 E, b& F1 _; G8 Q1 t9 V8 A

  q" _) D5 x  I2 N& v) l" q
_@89SPX3E4B4@QA{AZOGZ]3.png
7 B1 f$ p+ s" t
; G3 c) O6 S+ e! S' ^7 W! J
环境监测模块
- J6 w5 u1 x  e( n" a/ y$ Y) \3 J) g7 A$ E
YC)~A94I08EQ`YH~KL4IL{2.png
/ m, R2 V# Q- }
4 Y* M. U9 t, r3 y* x5 F
设备控制模块4 B/ ~( [2 P( c. w) J9 I/ M; J1 r1 ~
选择按钮即可完成设备的控制
0 {+ d& Y( j) q' ^- P0 ^+ R, t6 l4 F
%~KKPI%Y@F**BCOP($M2W6.png / n3 G* ~" }1 _% F
9 G+ R8 X, _4 M+ }2 F% Q9 p. |. F
开启和关闭按钮控制智能监测的开启和关闭,提交按钮上的输入框输入的是智能监测触发的阈值。/ q, U, N. p; f2 N
7 K. y/ |9 q6 ^+ ?  L9 L
URPIE04H]F}THLY2KYHAKI8.png
' D) {4 n0 a8 F

1 [. n$ `" d" j! k连接百度云模块
7 l. a; s* M5 f8 t7 z5 c  M输入百度云连接三元组,点击获取时间戳,点击计算、连接,即可实现向云端发送环境进而转发到微信小程序,并且通过微信小程序控制设备。
* D- J5 v, f1 [2 m/ S0 K. `7 {
% E3 d3 q6 ^$ F
TK48WOBRWP_6KDF~_6TQ{7H.png " S" |" ~  i: Q3 }/ E9 z" l
: s. a  T/ T* i. i4 K6 P. [
在微信小程序显示温湿度。并且控制开发板 led 灯
8 l! q. v4 K; V: Q+ K4 Z* E! R! b, y1 k
KD_XW~VN`6_F[EMWXHC@3VL.png : M( ~0 M# @$ w/ M$ L
( i6 W8 k8 |- y4 R
遮挡光电开关,会自动弹出门禁系统。
% f+ |4 [3 u1 ^2 ~( t$ S! r* d9 w& N7 k* h
$W0}X6H@4MJE]2C5(E9JHSY.png 7 |$ O) X0 o/ q- y8 j

: a5 D. K- N" G
Qt开发环境搭建
9 H, \" c" w/ U& W" i2 c" s4 t6 |$ l主机开发环境说明
& S- S- O( s& ]8 @( x+ Q+ U
1) 本文档主要介绍 linux 环境下的 Qt 程序开发;5 y; Z8 `; i1 Y3 r
2) 主机 Qt 版本为 5.14.1;
" H6 D/ C  ^/ }: t3 b9 t0 Y- e9 ^* i& y& z, U, ?6 w
主机 Qt 环境搭建及使用
2 Y  W6 Z  t+ k3 Q% S3 o" I/ B+ VQt Creator 安装
& F5 z% z6 @6 S. y将 qt-creator-opensource-linux-x86_64-4.10.1.run(Qt 实验源码\工具软件) 复制到 ubuntu 主机中,可以采用共享文件夹的方式也可以使用 tfp方式将文 件存入家目录下的 Downloads 目录。我们需要在终端中赋予安装程序可执行的权限
; F9 w* I0 t* \2 `  I, K$ W, z" X, B: e. p: h
YXM}@[HAVEZBR9%5NX[_)6H.png 4 L" \! N2 |* G

% ^3 |: T4 t' j; q8 W: D( D: v
我们可以使用图形化的文件管理器来查看
, j; c$ J* a7 N9 j/ N+ @
/ I: I( W! p' ?; `
P2FS$@N$$EAOMI@MNC[MV7U.png
9 n3 _# U! ?8 T0 j* r

# }' U- V7 E" x5 k2 p/ y8 g双击“qt-creator-opensource-linux-x86_64-4.10.1.run”图标运行安装程序。
1 b' {2 J* |  H" c* f  l9 t+ B  J  K5 I4 c& j/ b" _
出现如下界面:
/ N+ B; y/ [6 r6 i* {  j
  i. ]$ U6 _6 k; f
4ID8XA`Z(`ODSHHTIKPBCNQ.png
6 F3 f- l6 X( J8 x
; M/ g' G% k! ]/ w% S: r
等待程序验证完成后点击“Next”0 }; r4 _8 F+ N$ o

- L5 r# F/ d0 C5 I# P
0]VQY9LZ[`6SKA9RTFNRE23.png
: f7 p7 [" R+ B" y- V# c  `; N; j& ]9 f9 U, p" C9 s9 t/ T+ k
这里我们需要登录或者注册一个账号,如果我们之前已经注册过直接登录就可以。如果没有注册过则需要新注册有一个账号后登录。这里笔者已经注册过账号,所以直接登录。
2 O, }& S5 G! a9 z* v0 p' `+ ]' t2 P+ O
$ m0 p- Y: q& e; j1 K: i
登录成功后出现如下界面,点击 Next5 e; l' r7 i( b

% X- W6 k2 X- X7 M: f! B, l4 V
[~}4K%%{O06AWV40[8HYKAJ.png
  Q! j# s2 l" B3 k# f6 T% w( D" {* z1 [- S# s, z
这里选择安装路径. Z: q2 T3 j% E3 s, O
! m2 `4 {. |# V
02@}`7QZ}W)QEA`PA5LA4TU.png
/ J# G3 R, \$ U+ ]4 M0 T/ m. k/ {可以直接默认,Next
4 I5 a: m8 D2 ^( ]- r5 W. H* J# b, g- D8 r/ B6 I
}VRQS6H_]G@Y](SHYD$J24J.png 9 ~# E, d6 j7 W4 ~7 Y( p" I
! ~9 v% ~( m' V5 t0 r& N. L4 L# t
这路选择安装的组件,直接默认即可+ n& @1 [" a: ?) P% `7 M9 B5 |5 H
7 R7 X1 X/ `7 _" w# k
LGFW1HZB5M9AJH@TH%$C4.png / I, |" \8 Z( m4 }: x

- \( d" o$ ]; g1 G
这里我们需要同意用户协议
3 z& o. q/ \0 a9 E- ~1 l. V, ~* z% f0 k3 m# B, ^  h$ r9 V! S
HBUXY`$%YNWN7Y3M1~__R(A.png . M! ~$ Q' O. o& F9 E  w: j" Z6 J
4 \" s1 W- W& |1 c( J% ]% W, A! R
这个界面告诉我们安装完成后需要占用的空间。点击”Install”按钮后开始安装。1 R  U3 O  G3 m% g- N' @

% [8 A$ z: Y: ~& e+ D: D0 }  K

" [, k. y' ~* v" \+ {

/ n" z5 Q. ?; f0 e' o/ M' ]1 W安装完成后出现如下界面) }' Q3 y2 f7 W# q- `
6 _; M- t% d# D6 M/ P

5 W" l' N2 D6 f
& ?- J( W  B4 v& N
点击“Finish”按钮后将弹出 Qt Creator 主界面
2 ?$ U$ ]1 O& F
& \6 m; L/ O) S! B9 ?2 o5 c& S: p
7S(9~_~$~L)90NE1B)8XZD9.png ' j: K4 }7 D- d" K- _, ^# M

2 v) o; M: Z3 M3 Q, K6 N
点击“Cancel”按钮后即可正常使用
0 X) b3 u4 N3 t* \; H2 m4 I$ U: f0 _$ I( S

5 Q0 b! ^" ?  S1 @4 UQt5.14.1 安装
% I) X" a. h) G. G$ {复制到 qt-opensource-linux-x64-5.14.1.run(Qt 实验源码\工具软件)到 ubuntu 主机中,可以采用共享文件夹的方式也可以使用 tfp 方式将文件存入家目录下的 Downloads 目录。进入所在文件夹,先给执行权限输入命令
* |% g  g  b6 U! [: a" E/ ~3 |# h: u% o; e8 m
chmod +x ./qt-opensource-linux-x64-5.14.1.run+ _! O" Q. j- B; u( \
0 a/ q2 L* B  X7 J
安装在命令行输入
8 N+ Z& n+ k: Z: X! d
- b+ A7 h, p$ M1 U
./qt-opensource-linux-x64-5.14.1.run# b5 D7 K( t  P* t$ X

0 F0 `; Z3 A3 @
会有可视化引导安装,一直 next 就行了
* q6 _2 G- v- t1 i+ O1 o  @3 B7 G  g- o5 Y5 @- Q8 T1 b
在选择安装组件的时候要是不知道选择那些就全选了 大概有 4 个 G 左右0 V' j4 I9 N3 p3 Z7 r, o5 H8 f
$ {" `" q" x3 Q/ Y2 a, r
下载 gcc 和 g++% I3 _& U" E2 j" Y

: |0 t. i$ ]- }4 m# a
sudo apt-get install gcc g++0 w  q  }5 ~7 @+ U  _

) S/ I4 m1 ]6 G! g6 H
下载 cmake4 ^# [1 _$ _- w; M, x- |, r3 m' {+ |
  f- ~% T. K. o7 t0 o2 U
sudo apt-get install cmake
2 Z+ ]& p* N! D0 }+ a/ f8 U& j7 U. Q) z: o: I3 B3 |  ~
下载链接库5 N: d, ?+ u+ X6 Y% ^

# N7 W$ `" l) e. N$ D  Esudo apt-get install libgl1-mesa-dev libglu1-mesa-dev# B: w# R  W0 y0 a8 J' T) F

2 U7 X. q( m- a1 s# P2 BQt Creator 配置# }8 J4 }2 G4 f, R! Q, [
1)配置 GCC
/ S& w* X* `7 C# O7 B4 s运行 QtCreator 后,依次点击"Tool"->"Options",出现选项对话框,在左侧点击"Kits",右 边选择"Compilers"标签。 检查有没有下图标注的 C++和 C ,一般按上面步骤执行后都会有
- c* A; T( P5 Z3 h# `( t& v) {1 T+ D2 a
`TM6{[`YAQ@]B`FV1%EGNER.png ' D1 t7 X  E3 u

+ `. a( F$ C2 _# Z) u7 K点击右侧"Add"按钮,弹出下拉列表后,选择"GCC"的"C") E7 Y0 t: R' l& s) x

  v0 \! v" K- o
1EROYSYWYNFAKNG){AQAI_3.png
9 u8 Z9 ]8 e6 ^& Z# c" D0 S
* ~$ V7 K% u% J' u' R5 O! ^填写信息如下,"Name"为"Auto-GCC","Compiler path"点击旁边的"Browse.."按钮选择编译器的路径,例子中的路径是 “/usr/bin/gcc”
# O" @* {8 d3 b& s0 a6 e7 a. m, \7 F2 n# [- Z* `0 X/ y5 ]% u
U~6B}]8(%(L0$CWOE6CT.png # e8 w" y; A5 r8 f6 K3 f. V9 a; D
" n! j7 p: s6 Q0 m+ m/ B0 b
2)配置 G++* J( d" l8 ?9 Q
点击右侧"Add"按钮,弹出下拉列表后,选择"GCC"的"C++",下面的文本框填写"Name" 为"Auto-G++","Compiler path"点击旁边的"Browse.."按钮选择编译器的路径,例子中的路径是" /usr/bin/g++"。
' j5 Q. l3 z5 G  J2 r% l
4 T4 s/ b& `+ R1 P/ ~

! e/ `+ r8 W/ f1 }1 U" u% E* D( o! C3 ~. P& _

' R2 T0 c6 d4 M0 Q) x5 I2 F; t5 r2 _7 ^6 C) X" R2 [- |' e; u3 r9 Y  U
填写完成后,点击"Apply"。
0 b4 l- n9 l' G9 n; H0 R2 A2 o1 k4 e' h; T
3)配置 qmake
" }, t$ a: T) }$ ]; i) C3 l% J, l选择"Qt Versions"标签,如果有下面红框中的文本,可以跳过下面步骤8 G$ Y- F. a6 X4 \
# q. \- _& Q7 s9 J
(_WYIV~I3(WLN)UZL}L24A0.png
5 r/ O- v6 v" @' ]" ^" H! l/ v5 e

2 f& j$ g4 Z2 }, @如果没有,在右侧点击"Add..."
* I( Y4 f( {* ?% B
9 T: Z0 f# p5 y8 g3 x  v5 k7 V
8A9O1FTB_`48Y]IQI@X){HM.png . \9 W* _3 a6 C3 Y9 b- R% k& j% ~

0 ~: |1 d, }) V$ h2 A会弹出 qmake 路径选择对话框,这里以"/home/linux/Qt5.14.1/5.14.1/gcc_64/bin/qmake"为例子。 选择”qmake”文件后,击"Open"按钮
% b, k5 N( e; l- c1 U* K9 z' n7 G" K
VWR%~DF7DT9O`@N}X{5V(MO.png / Y8 j' l7 i$ y, \5 }

5 v/ y8 I; a5 x"Version name"改为" Qt %{Qt:Version} GCC"。然后点击"Apply"按钮。' c/ x$ c$ v$ A6 g; h. y
+ }: s1 t8 M; @( D% e( w0 t  m
4)配置 Kits0 R! l. W% \: A3 ^) }  b' t& J
点击左侧"Kits",右侧选择"Kits"标签。检查有没有下图红框选中的文本,如果有可以跳过下面步骤
9 L6 {9 M, ^) b) e6 E% k6 T, o2 ^* W
2}FWK{5CA{K0)S4(3OH8G8C.png : O1 K# K+ N' C+ p* H3 v; o& V# b- B

+ R2 F2 f6 ~4 I/ [' v( T/ E4 R% v然后没有,点击 Add:( }. ], ?4 @# Y6 S0 K1 f0 ^

, g& P; v7 }  i  Y) a在弹出的对话框中"Name"为"Desktop","Device Type"选择"Desktop"选项, "Sysroot"选择目标设备的系统目录,"Compiler"选择之前配置的名称0 y3 Z0 B: C' ~, g

& g! E8 k$ X9 O"Auto-GCC"和"Auto-G++","Qt version"选择之前配 置的名称"Qt 5.14.12 c2 {$ x4 A7 [- i9 Z

. X5 p* F4 ~! |6 KGCC",其它默认即可,最后点击"Apply"和"OK"按钮
* k( i! s( G% t& x2 j* K6 v: F9 t

) p0 z- I# x3 q2 t7 R/ Y% q9 V4 J( C; F1 D+ Y! {
Qt Creator 新建工程, M8 R1 f' A. w! L8 X4 r: l# S  }0 [6 ~7 \
注意:工程路径最好不要包含中文、特殊字符、空格等: |+ X% F; f. A: c' O

3 g& H6 x! Q  U我们可以新建一个“qt”文件夹,该文件夹用作我们以后存放源代码。
: o+ J$ o; f5 a/ y. N; ?; o2 \+ e, u( \: M# K
P(YSDLLU7HPN]O[$(E9J~YC.png / x1 u9 T! t6 I8 L
% \' r, ?9 B% L/ G
打开 Qt Creator,在欢迎页面点击 “New”按钮,来新建一个工程。
) q& n8 i* r( u/ y" P0 ?' m0 D- k( J+ M  z
W0`CL}D(SP}G1_M9MVSHEC9.png 4 @) K6 V% u) q* H: ]: z. e

! I, a& \# |; N6 A# v5 j# ]8 c; q在出现的新建项目窗口中,我们选则“Application”->“Qt Widgets
5 K' n$ W" b1 D4 I! I; k
/ B8 C, w  m, ?1 z/ JApplication”,然后点击右下方“Choose…”按钮,来创建一个桌面 Qt 应用。
8 s" |1 s9 f! g( b0 F) \' c5 q& ~( M2 j% O% f4 l
$_YRN3RR@G(1EDQ`GD78[3L.png ! ~8 L8 j& O9 ]' v  L

- r4 ~/ R3 L" G3 V, ]% U我们在这里设置项目介绍和源码位置,我们这里创建一个名为5 C! E' |' V' R  ^9 [, ~' G- T+ P  b
“HelloWorld”的示例项目,设置完成之后点击 next
' }$ g6 o7 h4 B+ `  Y$ d3 z; t9 _. n( X$ a( V2 i
ZB}(]4PU0$C07V}NU8_Z4OK.png 1 D0 X7 d. X; v2 F# B% J

. y" c0 J+ w& T( k7 J直接点击 next
) s# q) ?, d9 D1 O2 _$ z) L5 |  u  h/ I
Q(K%H9VD4}Y`J_C)PT~D{N6.png
1 |9 I0 n- d" r0 ~7 o, q- }
2 X- |" d' G3 M: n2 J0 O. @随后进行细节设置,主要设置要创建的源码文件的基本类信息,包括类名等。这里我们可以根据自己的项目特点进行设置。需要说明的一点就是基类的选择,这里基类有 QMainWindow、QWidget、QDialog 三种,它们的不同之处如下:' `; _5 s' j$ `/ `* L. X* H
⚫ QMainWindow 类提供一个带有菜单条,工具条和一个状态条的主应用程序窗口。主窗口通常提供一个大的中央窗口部件,以及周围菜单,工具条,和一个状态栏。QMainWindow 窗口经常被继承,使得封装中央部件,菜单,工具条,状态栏等都变得很容易,当用户点击它的时候,相应的槽就会被调用;4 M( q  Z/ l7 f- T# K
⚫ QWidget 类是所有用户界面对象的基类,窗口部件是用户界面的一个基本单元,它从窗口系统接收鼠标,键盘和其他消息,并在屏幕上绘制自己。一个窗口部件可以被他的父窗口或者是其他窗口挡住一部分;
1 ^& s0 G+ F8 U1 X* M5 V⚫ QDialog 类是对话框窗口的基类,对话框窗口主要用于短期任务和用户进行短期通讯的顶级窗口,QDialog 可以是模态对话框或者是非模态对话框。QDialog 支持扩展并带有返回值,他们可以带有默认值;我们在这里选择 QDialog 类即可,点击 next 完成类信息设置$ V/ m7 z8 J( E" ^& z# v

/ q. _" m* c& c) z0 K- J( N% i
X$%UAH}$)FO(J3BIU])@3_T.png
: ]$ L: o5 q4 t6 e: o
5 j1 o# O- l0 L- a6 ~* G直接点击 next 按钮即可。( L0 `" s- I& P" E- X; D
4 U2 r: O+ i' {
6TH61]SII0LQ691FQVLPOBB.png
/ V0 E. r9 ?, r. V) e; |# {! |
/ Z! m! _9 A! g* F5 x: p然后进行工具选择,该页面可以选择我们创建的工程可以使用的工具,选择想要使用的编译器模块,例如下图 。点击 next
7 C. Y' I8 ?+ W7 }1 A7 S
3 u8 x& u9 n* E; r2 R7 `% r
_JKKWR6U67_L@75WZVPMKFU.png
; [! @' k+ z- m. |/ Y! T" j) Y: r+ k
最后我们设置汇总信息,如果不需要版本控制等功能,直接点击完成finish 即可
2 c# ^" M$ {4 Q8 Y  t, B) U, H
& u  W5 N% ~# H% R! j( g
XZ_C0WTB7XYG[9{94G4~~RJ.png
( k- ^5 k3 j0 ~% _6 g& N2 }0 w
/ S0 C4 x: [  ?
随后我们就进入到了主界面,这时候 Qt 已经帮我们做好了一些准备工作,包括创建了一些文件,写好了一些前置代码等等。
' j$ `7 ]: F6 r2 B' S
- S8 ]. e7 i3 l$ L
我们可以点击左边 protect 栏,来查看我们的编译选项
6 n% Y; b2 l* b# s
; X9 ^$ b1 A) e+ Q# M5 c) c, M3 k
)CP44_~VJY0J)I1LUVE)1NL.png
2 K3 r" F2 x7 I  f4 d' V' n- B4 }
我们可以在左下角选择编译 Debug 版或者 Release 版,即调试版或发行版。3 H* s+ P0 c% i* s9 p& E

1 m# `% C8 t+ t1 O! a* \# B( R8 D
3ULZA9%8G{[14G%{VQH7.png 2 f* ]# ^! x3 G- q7 L/ ]/ m

( P: v- o. w; o2 W7 a) e左下角绿色剪头是编译并运行,锤子是仅编译,我们可以直接点击绿色小箭头将我们导入的工程编译并运行起来。  P! B, p; v9 R6 p- i
: J8 {0 {# n1 R, F7 g; X  `0 M( |
1NBIR0`F@3ZSU2REX5ZK4$K.png
3 d( d, a: ~: R' V! Z9 r. T$ F6 v$ P: {. U
点击运行按钮后,我们可以看到 HelloWorld 窗口运行起来了。
- E+ ^* M5 a! C7 F  D4 x) Q+ I# ^4 Y/ K4 c% z! s; y
(15RO4%(RD}A_@I2Z72R[]R.png
* j/ h: O8 |: }1 y8 M% @# b. u
7 g+ B/ q7 B  y3 n7 Y# u导入工程' p6 w0 |/ w8 c( d$ D
我们可以将已存在的 Qt 程序项目直接打开,这里以上一章节的HelloWorld 程序为例。首先我们确定源码存在的位置,如 HelloWorld 程序源码在 /home/linux/qt/helloworld 路径下。0 c3 k6 v7 _9 e, c$ k% |0 f8 \

0 v1 S& d) Z, A+ ~: r点击欢迎页面的“Open” 按钮可以打开已有的工程。
+ e7 P( x5 {) n- ?$ \7 }# I2 C7 k  r8 p+ l" d; ]
YO_SU(4O5X8B$UJ_M2F.png
& S9 M7 I6 g& X6 E$ ~% Q, |- ]/ ^2 i, o" n7 F* x0 Y2 _6 F( V+ [7 ]
找到我们刚才解压好的源码,选择“helloworld.pro”文件并点击打开( D5 Z* X: Q4 U9 n% r( _4 a; r' z' c, K
6 H! g. x/ a4 k7 A# Q

! c) u" l8 i  G4 r* H& Q" x6 L% g
8 l  D! ]1 d# K2 A8 c$ A9 ]8 ?接下来我们就可以进入到代码编辑界面了。9 `5 R4 B+ C2 f9 R
% u) h- R9 s3 F9 a7 ^
BZEPY[_6ZZK~V59`XL7%XV2.png
- g; Z( {) v" z* n0 F1 P- t( s& y. _
左上角是项目栏,点击项目名称左边的小箭头可以展开项目目录。
7 c7 {6 K4 i( E8 o1 R2 z# ]
8 e" ~3 E" J$ M6 m% }# K* L
_~OX6IL7)EGWXZCWSKQU6.png 5 z7 r  y: |' L" S/ X0 F8 L
: f; E4 |+ k. f8 L7 e- A, Z- B
我们可以点击左边项目栏,来查看我们的编译选项。需注意的是构建设置中的路径应与工程路径处于同级目录下。
3 ~/ t; w0 Z4 I$ V* M* ~/ g; v% S$ a1 f$ z  A) e! o# z. s
[%~`0NJ~]M(GDU(R_IQ)R}X.png 1 A! ~# B5 X& I/ L0 R: C! ~

, s. o" y: Y, e我们可以在左下角选择编译 Debug 版或者 Release 版,即调试版或发行版。
! v( y( @! Q( a# o, {5 y! {$ F4 J' \5 Z- S5 p, T3 x$ t  m7 z  b- `$ v  [, f
72BZ`U_6]LTC)W5L2PR0J%J.png 0 L) E# t5 J/ C. l) C$ p2 j

( }3 Y2 I, Q9 ]9 v" l  r5 k左下角绿色剪头是编译并运行,锤子是仅编译,我们可以直接点击绿色小箭头将我们导入的工程编译并运行起来。/ V# ~4 @) t" X1 a5 d2 Q
* L9 P9 J# o- w5 G
: A8 Y& H  I, ]7 t* a

7 P' L: E& R* u4 b5 I
点击运行按钮后,我们可以看到 HelloWorld 窗口运行起来了。6 d3 ^* l' r8 a/ r( c" e

5 c( a* Y  \9 [& B( |
+ ^6 v1 k0 G% Z5 |4 B; z0 L

3 h1 c( {9 M- ]
文件说明
0 D% Y' o5 u; |4 T" G/ G  B) e通过上面两个章节,我们学习到了 Qt 程序的新建与导入的方法,也知道了Qt 会帮我们做一些基础工作,比如帮我们建立了一些文件,那么这些文件都是干什么用的呢?我们以HelloWorld 程序来说明一下。; G) O/ a8 Y5 s+ ~  }
. w' F" d( |/ U  L/ e
5 S2 R. a1 m3 |% l: G

6 v6 z- l( A. o+ [" R2 S
以“.pro”为后缀名的文件,为 Qt 的项目管理文件,存储项目设置的文件;
  C: ?1 _! ?) q! j, O  o+ Q/ R2 a& _: I
NIL}HI4FU0OAUV1]VKODRZ3.png . d7 \; ~) q  Q, ^; k/ ]( K
8 n) c/ T8 v( K& w4 C  B; E
“Qt += core gui”表示项目中加入 core gui 模块。core gui 是 Qt 用于GUI 设计的类库模块,如果创建的是控制台(console)应用程序,就不需要添加 core gui。
* j+ U1 s; h' k# b7 {5 t; `, d9 s# W6 d7 W8 p
Qt 类库以模块的形式组织各种功能的类,根据项目涉及的功能需求,在项目中添加适当的类库模块支持。例如,如果项目中使用到了涉及数据库操作的类就需要用到 sql(数据库)模块,在 pro 文件中需要在后面加上 sql:
2 o. ^* b. G- K# }7 v/ h7 }: Q- I6 z
( f4 ~: b: d$ c0 i4 A! i
1 Qt += core gui sql
2 |3 q! D' O. C8 z0 `6 t3 f4 u% W/ X
“greaterThan(QT_MAJOR_VERSION, 4): QT += widgets”,这是个条件执行语句,表示当 Qt 主版本大于 4 时,才加入 widgets 模块。
# a2 e+ _' a0 Z' h" }8 h7 V  \* f) `6 t/ l- H- h' i  R3 v
“TARGET = HelloWorld”表示生成的目标可执行文件的名称,即编译后生成的可执行文件是 HelloWorld.exe。- r# `' s1 |6 y% G9 {: ?( d) W1 Z$ [

8 z: |: @+ z) U& d
“TEMPLATE = app”表示项目使用的模板是 app,是一般的应用程序。
! }+ E" o. |( G# R' k
* Y% `, a: q! o
后面的 SOURCES、HEADERS、FORMS 记录了项目中包含的源程序文件、头文件和窗体文件(.ui 文件)的名称。这些文件列表是 Qt Creator 自动添加到项目管理文件里面的,用户不需要手动修改。当添加一个文件到项目,或从项目里删除一个文件时,项目管理文件里的条目会自动修改。
6 Q( }* f* L( B0 p9 s7 ]2 Q
" |/ x9 {1 a. s" ?9 k) Z1 Z- i  Y
文件夹“Header”中,存放的是所设计的窗体类的头文件;
! _' P4 Y. g9 ?  Z8 r
) Q8 w) e- V; R: O, P. @& A
文件夹“Sources”中,存放着源码文件。main.cpp 是实现 main()函数的程序文件,HelloWorld.cpp 是 widget.h 里定义类的实现文件。C++中,任何窗体或界面组件都是用类封装的,一个类一般有一个头文件(.h 文件)和一个源程序文件(.cpp 文件);5 q7 S$ w2 P1 H( h! b- C- H1 W
  g2 @2 [9 z! b, y2 ?* B
文件夹“Forms”中,存放着界面设计文件,“.ui”文件是一个 XML 格式存储的窗体上的元件及其布局的文件,双击项目文件目录树中的文件 ui,会打开一个集成在 Qt Creator 中的 Qt Designer 对窗体进行可视化设计;1 I. L; E! _! }8 G  f( y8 i0 Q# s

4 G5 e/ m' F$ q' Y9 H3 S- N/ Y
~0O849UB9NT(C(C6S2$Z7R9.png
* S+ C  V, {+ G' X

$ y% I& J0 a1 x# P0 q7 WUI 设计器有以下一些功能区域:( D- V6 W, b0 l+ l: c6 g' K

& F  O  H: B& N4 C% R7 V
组件面板:窗口左侧是界面设计组件面板,分为多个组,如 Layouts、Buttons、Display Widgets 等,界面设计的常见组件都可以在组件面板里找到。
& N+ O- X0 Z  B
3 N7 }$ y9 Z7 V& q: j% |, {1 g7 c
中间主要区域是待设计的窗体。如果要将某个组件放置到窗体上时,从组件面板上拖放一个组件到窗体上即可。6 `( y) {% g0 P  _1 X
4 T1 B. j- S& v8 v1 I
Signals 和 Slots 编辑器与 Action 编辑器是位于待设计窗体下方的两个编辑器。Signals 和 Slots 编辑器用于可视化地进行信号与槽的关联,Action 编辑器用于可视化设计 Action。* r5 m9 H  [1 ], k2 r

; ^% u/ Y& N" w) ^9 [
布局和界面设计工具栏:窗口上方的一个工具栏,工具栏上的按钮主要实现布局和界面设计。9 x1 I8 U% P* Z0 h  [3 t: \2 `
9 h% W2 _* V$ E! e  z- i
对象浏览器(Object Inspector):窗口右上方是 Object Inspector,用树状视图显示窗体上各组件之间的布局包含关系,视图有两列,显示每个组件的对象名称(ObjectName)和类名称。
2 a1 S% l. H7 W
0 m1 t, J+ e( t. k8 ~0 g1 m
属性编辑器(Property Editor):窗口右下方是属性编辑器,是界面设计时最常用到的编辑器。属性编辑器显示某个选中的组件或窗体的各种属性及其取值,可以在属性编辑器里修改这些属性的值。属性编辑器的内容分为两列,左侧为属性的名称,右侧为属性的值。属性又分为多个组,实际上表示了类的继承关系,位于下方的类属性组继承自位于上方的类属性组;如果我们需要新建资源文件、源码文件等,可以在项目文件夹出点击鼠标右键,选择 Add New;如果我们有新的文件需要添加,可以在项目文件夹出点击鼠标右键,选择 Add Existing Files。
/ m% b* P- H" s) Q9 @7 j. L% P3 U4 b' d' _
E5LXC5(Q61T$$LY8RXFN2_L.png 0 A. y" v7 H8 Q3 ~* E) R/ w

6 F9 g: a/ a( ]4 c3 S
帮助文档
( K, D& H  |$ o: ?$ bQt 的帮助文档是伴随我们学习 Qt 开发的好伙伴。在 Qt 开发过程中,我们会面临图形接口使用的问题,它不像 C 语言那样就那么几个函数接口,图形接口的接口数量可以用海量来形容,常用的我们可能能记住,其它的就没有必要去记了,用到什么就去帮助文档查看用法是比较方便的。我们可以按 F1 按键,或通过上方导航栏的“help->contects”来进入帮助文档。
# i, l+ f; u. L2 ~# i, H8 \1 h( v1 B. E; z4 U
LNUOL]PXQ$_U192L}P_YWR7.png
3 Z/ F+ M/ M6 x; t
, B/ A$ G; w' e$ s! e; Q6 M0 [
上方的前进后退按钮方便我们查看文档,如返回到上一步,返回到下一步。9 R1 a  U1 ^- X+ W
0 ]% a5 A9 N" D6 O# y
$~}K$@TWUD8XGKFOZ5WMLF7.png 3 [6 O& H$ [4 S, O+ f3 q

( P6 ^5 Z1 {. B
我们可以通过帮助文档来查看以下几个部分:; H- Q4 T4 W, ^6 ^& G% `
类使用的相关介绍;  a! R1 m1 v5 A6 u: u
查看相关类的使用介绍,我们可以先进入到帮助文档,然后在左上角选择“Search”。笔者这里以 QWidget 类为例,输入我们想要查找的类的名字,然后双击查找结果来查看说明
7 ]! j' U/ S0 y% b* c6 ^) g5 h# Y% J" x: B3 W
PP2)_IDX51I7ZA)[@R(YYB6.png + w0 W* w# Q3 E; z5 P3 i. h
2 c, E% q. U" u
也可以先将鼠标移动到想要查询的类的位置,如图所示,将鼠标移动至“QWidget”处,然后按“F1”键,即可跳转到相应的帮助文档) ~8 W: R8 L5 h5 N

- S1 j! b% ?8 K
ZHZC%A(RJ_L{DLXA{KCH]6P.png
. E0 S0 ]% l' g
6 j$ K4 O# a8 S$ p
我们可以通过再按一次“F1”键来全窗口查看帮助文档,按“Esc”键可以退出。" U7 V/ C% R: `) K$ F/ O
+ K7 P: ?9 o, s" k8 _0 K
3C33W5PFOAWO$_[8%NJ~Z5O.png / ^( S; x) V; ~1 B

0 @. `  _3 j# O
部分常用的成员元素包括以下几项:8 ^# J8 w* \" ^* _0 |
⚫ 公有成员函数:操作部件属性的相关函数;
6 T, u( s+ `0 _/ m3 X⚫ 公有槽函数:Qt 类中已经定义好的槽函数,直接可与信号相连接;* n* J  {2 u  c7 |6 q8 d% c1 b7 F0 A
⚫ 信号:软中断,如按下按钮触发 pressed() 信号等;. ], W0 w* u) Q
⚫ 保护成员函数:通常事件所对应的虚函数放在此处;# }) f0 ]3 w8 e
⚫ 事件:常用事件,如操作鼠标触发的鼠标事件;" N. N* A' o8 V. E9 I( c
, @* n6 M- A% R' i
滚动鼠标滚轮,向下即可看到“Qwdget Class”类的相关说明了。  j- Z/ Y6 w9 ^+ B- {7 {' g
3 o% @& y( @1 k/ n! L/ l8 v, j& `
O{GSH6}@YO_Q_78])68O}8I.png % ?- @+ O! x  o( W
, r, J  R1 a2 j2 F( A3 c
1) 查看所用的部件的相应成员函数。: i  `. h# V4 [, S: k1 z; E
我们可以查找到该类所用部件的相应成员函数的使用方法、功能、参数、! l! z, @0 C$ m3 l
返回值等等,我们以“按钮”控件,即“QPushButton Class”类为例,我们通2 S6 L3 Y7 r" H/ a
过索引搜索的方式,来找到这个类% r2 y5 d1 R$ i* |9 T- B

/ Z, V& N8 n8 D  G2 N
1U%_{~7$WAI~)NLNJLYTQ(I.png * ]$ {, Q$ H1 F: f, [
3 p/ s7 a/ Q6 z* H% u' A! V
我们可以通过点击“Public Functions” 来查看“QPushButton”这个类中的成员函数。
/ m0 U' f) a2 H
6 T$ ]: H  T: O1 }6 D1 Z; P" N* \: [
F2HWVYXAL7P}5]A@)~D(DFP.png ; m* s+ j: T% Y! ~, N. U
) S  F. I! H* K% P- ]# c! U; _: L
这里以“QPushButton(const QString &text, QWidget *parent =Q_NULLPTR)”为例,我们点击函数名字可以进入到函数详情中。我们可以看到相应的描述为:以“text”为显示内容,以“parent”为父对象,构造一个push 按钮。“text”“parent”为函数参数,由于是构造函数,所以此函数没有返回值。1 i" L6 p9 F+ d4 ]! [8 T
) r  @% k& M3 ^- ~( K
QAS29X5%LXF`@YPFW}FH0JH.png
6 B8 ~6 L" e+ m9 {) z

' o8 S9 R1 d" N6 ^- t9 ?还有一些函数是继承自其它类的,例如“Public Functions”中有 21 个继承自“QAbstractButton”类的函数,我们点击“QAbstractButton”即可查看。# e3 ]# A8 v2 W! n, `# S8 n

% Y! \( }9 ?7 H, _
点击“QAbstractButton”即可查看。: z2 [3 }/ p  k0 C% ~; ]9 ?
. @) G+ W: t: h* e7 o1 ^3 V/ u
NUUS]2Z5YS4SE53GVKL5EB6.png " p: k) i, s& s% p8 g

( \$ Y" x, v0 T1 K6 S. {8 E
@]Y`O$(`[D9NGB~15`~E8)G.png # T3 y) \, h. L1 `
6 J( L7 d# m' V  x0 k* c3 ?
同样我们可以点击相应的函数进入查看详情。如查看“void setText(const QString &text)”。3 M7 b# H7 {3 h, H- Z9 ~
, M7 T) O, ?3 v4 d, R- p3 s
CYEU7TXQ]_[)LH9`_Z6_GYA.png
2 i- ]" k: z) N8 k/ Y: l7 a7 B
7 L6 _' q& i8 |& b- C' O
4 C) _* \: b- K2 k
2) 查看所用的部件的信号。
% H, E' {5 l! N  S, l, Z$ Q我们这里还是以“PushButton”为例,我们点击“Public Slots”。
0 m& z. l' S. q8 I7 R/ d- H: F/ c  b. G1 k4 y; Y
GM[Z[8OJW)I1Q7HF[9Z2]G6.png & h  h' ]; ^/ ?, Q! h! K2 P
可以看到“PushButton”本身有一个“void showMenu()”的信号,并且有很多继承自其他类的信号。1 M8 T8 s) p. N
" q) f; }9 g' Z% \8 g, |8 C
{1CRC40MNF539L{UHLA48JX.png
) X/ P9 J  \0 y- |* Y" }- n0 e
$ [- y9 Y7 p5 i0 _# N0 ~5 e
2 h# ^  J& X  l! `! b7 \6 G) |! n" k
一般来说我们用的“PushButton”的信号,最多的是用到其继承自基类“. f/ i0 d; ~, M% ~) |) p9 t
) U7 D2 J4 _+ Y0 Z) y% x
QAbstractButton”中的几个信号,分别是点击(按下后抬起)、按压(单按下)、释放(单抬起)等。
3 h: b; m  l" Q0 N7 Q2 V7 T6 ]
0 n, U8 S+ H, f! w1 T& k
~B1FTK{5$GSFKI)O9TN9.png
8 C8 A. R( |3 ~' }
% r; c8 j6 F" ]) Z4 h
我们可以点击相应信号查看详情
1 h* V4 L0 E( s/ x0 w; H, ^' {+ s* G( t3 ]2 }+ j
]PTTEU3FAWQNKQ5GAP82OWT.png - S% W  u$ A% B2 l! n! c

) E( x3 y+ Q; A

: K+ ?; g( h8 |" M/ h$ c* G0 N! @3) 查看所用的部件的事件(所对应的虚函数如何编写)。部件常用事件主要在 “QWidget”中声明,选择“Events”即可查看相关说明。
- W4 y( Q, A  ~5 \; o0 {3 f每个事件都对应着事件函数。
) {. w8 s4 k: D- z. J& L$ A0 }  u% J" j
97P10BOBQ%B)W9R{0207OFO.png # g4 v! o8 w& d, G4 `  e! F

7 j1 J: Y( ^, I4 }3 k
点击事件函数可查看详情2 J$ K) T; l+ n6 U
" y) _9 b6 u) n( L( {
W(PX5{9X[32V@J5XL41(~1Q.png
. o0 d8 J' N7 W7 I8 Q0 e5 ]) U, d' p: `/ E/ {
微信小程序开发环境搭建
0 g$ w. W. j0 T& p, t8 ]微信小程序开发工具简介

" c7 `  M% Z& Q0 Z: e" c3 f微信小程序是小程序中的一种,英文名 Wechat Mini Program,是一种不需要下载安装即可使用的应用,它实现了应用“触手可及”的梦想,用户扫一扫或搜一下即可打开应用。全面开放申请后,主体类型为企业、政府、媒体、其他组织或个人的开发者,均可申请注册小程序。微信小程序、微信订阅号、微信服务号、微信企业号是并行的体系。以下是小程序所涉及的技术概括:
/ b0 F6 L$ Q2 s" C6 {0 b* s  S6 e% c$ S: a" `! i+ T9 g
2 J0 y# L; d1 @7 A# K
⚫ JSON
7 O" Z$ X) g8 O9 g& N# SJSON(JavaScript Object Notation)是一种轻量级的数据交换格式。它是基于 ECMAScript(w3c 制定的 js 规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。易于人的阅读和编写,同时也易于机器解析和生成,并有效提升网络传输效率。0 s  ]: F) ]7 t3 T" H: |/ C) U
' V9 Q  e! U) M9 S
⚫ XML7 C  z5 [) y5 P3 }9 N; V$ h6 f
XML(Extensible Markup Language),中文名为可扩展标记语言,标准通用标记语言的子集,是一种用于标记电子文件使其具有结构性的标记语言。
% o; p# H$ V0 S( D1 f
, g9 x7 P' u2 _( q
⚫ CSS
% E" z0 W5 l/ r2 r: Q层叠样式表(Cascading Style Sheets)是一种用来表现 HTML(标准通用标记语言的一个应用)或 XML(标准通用标记语言的一个子集)等文件样式的计算机语言。CSS 不仅可以静态的修饰网页,还可以配合各种脚本语言动态的对网页各元素进行格式化。
, K# u$ `* _( f6 L5 Y8 j+ G* z& U) D0 E
⚫ JavaScript7 r9 L5 G) M6 L9 ~  ~% B. w
JavaScript,是一种直译式脚本语言,是一种动态类型、弱类型、基于原型的语言,内置支持类型。它的解释器被称为 JavaScript 引擎,是浏览器的一部分,广泛用于客户端的脚本语言。$ r7 X+ `+ ~3 V$ Q2 S8 T1 q
, L+ E; J) e# m8 L
申请微信小程序
; m4 o$ S6 D6 b; z登录微信公众平台,注册账号
- T9 V& P+ ^# T# l% {
, G% T7 X% `% L" _/ P
GUQ$V671RLHKCGUL13@71_T.png & x4 ~* |/ Q5 T* d3 ?" q

3 y9 t* t3 Y4 W& \0 C按照步骤依次注册,输入邮箱,密码,验证码等,同意协议进行注册。7 T7 r$ f: g3 q

; z# v7 X) `9 i. m) B$ V/ |+ r
50K]YY7QJXWBPHQ_K(5}G20.png
* n" _7 ]4 b+ _6 g9 H+ i
) S6 r' X8 h" o" r  D
S$E~F8WBE]O_U4M`UFMEH67.png
0 T- G2 A! e" `: \' s
. B; J7 i. O' b: ]6 T- V8 ^4 j
然后登录自己的邮箱,查阅邮件,点击链接进行激活。进入步骤 3,信息登记,按照网页要求,依次输入信息,身份信息,管理员微信信息,即可激活成功。
' E+ [; E" v8 \  \. a
9 k4 ^7 A* O. d1 Z% s/ U+ d" P
返回微信公众平台,输入刚刚注册的账户密码,会需要用管理员微信扫码登录,登录后,下载普通小程序开发者工具。& [9 r' w) G' r# k* t

0 l' j* c9 O/ q& C) M
{$Z2}M}]%WQ(`I@{@1%K8HI.png
4 V$ T% N' o/ g& ^) V; K. F( p  {% J* T; y9 O! ^
点击开发,选择开发设置,获取小程序 ID,以备后续开发需求。# F- W  @  j9 x
$ Q* B5 s% {& j- e4 J1 R; n
IV(94]C]6Z~P{J0ZU)PL7V0.png
( x- Q0 H& d/ r) _
' _2 ^, k9 N/ H, ~+ ^4 D+ b7 M
微信小程序开发工具下载完成后,进行默认安装即可
. U; v/ g# s3 H* Q3 a& d) ~+ I& Z% k* \; |
创建新项目工程
& c" Y! b: k9 |$ N( c4 i8 u; T. h; \打开微信小程序开发者工具,点击创建新工程,填写自己的 APPID,选择默认模板,语言选择 JavaScript,点击新建。
2 t9 V# i( E! D& n# }% g) \+ N0 V3 L
9P$~CS~A2JMO{@EISZV80TK.png ) R! e9 \5 P( K; G. P) {1 i1 q

8 `" k* I3 f* ^5 f9 X2 I  |: x
新建工程完成为如下界面:, K* F7 c, W+ M6 a
4 Q; q, }; v& W/ K$ F8 S
V%K~3U3EN3WB96K4948I1GJ.png
' M3 m" k. j: ?2 T, U& o& n! p, b7 J; y! E- ^
基本环境配置# G/ I* H, x7 ]
% E- d9 ]+ @8 K/ o% U
P[(7LZJYYLB)]P8]09]SGZF.png 0 q/ v& @  _. Q- R

) {, N2 l* k. [  g  I打开主界面的右上角的详情按钮,找到本地设置,将“增强编译”和“不校验合法域名”这两个选项进行勾选,因为在小程序的开发阶段,尽量把这两勾选上。
3 j% [& C( \/ ~4 h9 h9 |
) G% O) {$ `. e& g1 _' f* U
编译、调试
* s/ L$ p( Y6 N: F打开 app.json 文件,可以更改微信小程序的标题,改为“工程 demo”。然后按下 Ctrl + S 快捷键进行保存,即可完成编译,调试输出。查看现象。5 s2 t5 a  N" x. Q# z
) m8 R; p+ z  f6 Z  Y) F' F
VH%$PZ6_4NJMVCF(2N[X.png
- p1 Q4 p" _/ X* C, e% U
: ]$ }- D2 `, Y3 A6 @! o' n9 A9 K
项目总体设计介绍; K0 Q. }/ w: c" l
总体框架. E; i8 C7 T+ J$ S" G7 C  L
智慧家庭系统的设计基于物联网的思想,物联网是新一代信息技术的重要组成部分,其英文名称是“The Internet of things”。其基本思想是以互联网为媒介,实现远程监督、控制。它在各个领域有着非常广泛的应用。
5 Q0 g1 `  b4 A% U+ @8 y
- J, K+ F9 o' G' g, L
总体框架如下:8 x' _# [& J0 v1 _
2 K. [/ |: u6 x( x* `
4@{DJ5ZYAQ_HCBQA726SA{3.png
& q0 C: N! M( O$ r7 I( t7 G* a4 F  J' c4 Y# h( l) u/ e
该项目分为 WIFI 连接模块、智能门禁模块、数据采集模块、智能检测模块、设备控制模块、天气预报模块、与百度云交互模块:下面具体介绍几个模块的功能。
( b. V2 V0 E$ y, g8 \
) E9 `! [7 s% `* u
WIFI 连接模块
# l4 k, L* r- Y4 c该模块实现的原理是使用 wpa_supplicant 工具对无线网络进行管理和控制的功能。wpa_supplicant 是一个开源项目,已经被移植到 Linux,Windows 以及很多嵌入式系统上。它是 WPA 的应用层认证客户端,负责完成认证相关的登录、加密等工作。) k1 u! w9 K  S
9 O9 \: [" Y% q7 |! }! h( Y$ O9 _
wpa_supplicant 工具包含 wpa_supplicant 和 wpa_cli 这 2 个程序,其中wpa_supplicant 程序作为服务端在后台运行,服务 wpa_cli 客户端的请求,从而实现 WiFi 的配置连接。下面是通过 shell 命令去进行 WIFI 的配置及连接。2 i/ |( b9 v! D

! o3 I9 g9 v, {& {. v
1.打开 wlan0 接口:
: d9 E0 u8 _7 h3 I/ lroot@fsmp1c:~# ifconfig wlan0 up
' z! z8 e6 A$ r0 x
' M  ^: `' b) m' ^) q
2.启动 wpa_supplicant 进程并在后台运行' a6 b, H5 _9 W; H
root@fsmp1c:~# wpa_supplicant -D nl80211 -i wlan0 -c /etc/wpa_supplicant.conf-B' E4 z* n, @# i+ L7 z9 B

" X" A: _4 b& E# r
3.扫描周边 WiFi 热点:) x5 m9 \! Z; N' t! d2 H
wpa_cli -i wlan0 scan( r* B0 J& n3 c0 _4 e
* Z# H" l5 d& B2 U
4.查看扫描结果:
7 U; O  ?, K3 \3 f- kroot@fsmp1c:~# wpa_cli -i wlan0 scan_results; \+ U+ @( \" F8 n7 O5 K$ a* Q
; f# `; f8 x) T* `% b
5.添加一个网络连接
4 B5 C8 f4 v* D8 troot@fsmp1c:~# wpa_cli -i wlan0 add_network9 T* z8 B) Y. b8 G( U4 T4 p! Y
7 T7 ?& Y1 Z: e& n9 k7 @
6.配置 WiFi 热点的名称 ssid:
1 h% ?* ]/ X$ i/ K8 Sroot@fsmp1c:~# wpa_cli -i wlan0 set_network 1 ssid '"FARSIGHT"'
4 b- X) \  h  `, I% N
7 p( H, S/ j" Y! m( _, l) D$ {7.配置 WiFi 热点的密码 psk:
0 j6 G/ _! Q# O( M- h1 A. mroot@fsmp1c:~# wpa_cli -i wlan0 set_network 1 psk '"fs123456"'
; e$ q  @8 r9 n7 C& X3 i1 g
. n7 v4 }) Z: o8 y- _% h5 H8.列举所有保存的连接3 Y$ Q0 ]& I/ o/ [" S. J/ \; J" E( [
root@fsmp1c:~# wpa_cli -i wlan0 list_network
1 H8 ^" g, u* U5 r
4 e% C8 N0 j9 U; f# n9.连接第 1 个保存的连接' l0 {2 i' h9 p6 P: T* m
root@fsmp1c:~# wpa_cli -i wlan0 select_network 14 `* I6 V' b$ e: ]5 N

1 s4 [$ z9 `8 ?
10.启动 wpa_supplicant 应用
' N& A+ n% D% Q; L; f; ~' {, K5 zroot@fsmp1c:~#wpa_supplicant -B -c wifi.conf -i wlan0
  f# E  }$ n+ H% ]* K3 N( s; U- n( [, J+ x7 Y7 N
11.使用 udhcpc 命令动态获取 IP
- t/ X) e: n' c& t5 p( Troot@fsmp1c:~#udhcpc -i wlan04 l3 w* c2 l  b8 U4 R

; m' z2 K- ^% J. K0 R4 u
+ T: J. D. _1 m  B+ O
智能门禁模块
4 k+ N3 k7 s; T! i/ i该模块是根据关电开关智能识别有没有人来,当有人触发光电开关,会自动弹出登陆界面,输入用户名和密码,程序会自动匹配数据库,如果用户名密码错误超过三次,会自动报警;如果输入正确,则开门。! v/ o4 f. y- d: I; ~7 {  |

( m5 ]# A. g- ?7 Z" g- x, X数据采集模块' a2 c! U+ ~& X& Q* r( R
另开一个线程,实时去读取温湿度驱动设备文件的数据,进行计算得出温湿度的数值同样的方式得到光照的数值,通过信号传参的方式传给主线程,将数据设置到 ui 界面上。2 o5 k% }  b1 x' h/ R9 w. O

) t( e/ b: H* d
智能检测模块, M$ a' ~+ H& C4 y" |7 q4 `
开启智能检测后,程序会根据你设定的阈值进行检测,假如温度超过你设定的温度阈值,会自动开启风扇;或者当光照低于你设定的阈值,会开灯提高照明的亮度。# Z, l: t' H( ^" n
$ j* `6 `7 d4 J: N, R9 f8 N0 \  `
设备控制模块
% z4 X" C( ]. u5 _* l; H通过 ui 界面的按键去开关灯或者风扇,以及蜂鸣器。
. f) t+ e# V% ?9 h$ N
! q4 b; B8 k9 L
天气预报模块/ F5 s' K; [+ f" I
连接 WIFI 之后,通过 get 方法从网上获取信息,得到 Json 类型的数据,对这个数据进行解析,将解析到的数据设置到 ui 界面上面。
; r9 A. M* H9 d6 u* _' D1 l. Y: M- p. D3 ?) z  Q- k
百度云交互模块
# C* b' G/ u' s" i. \& L  f8 |8 e* X在 ui 界面输入在百度云创建设备时的 IoTCoreld、DeviceKey、DeviceSecret(三元组)通过组合生成 addr 和用户名,使用 MD5 加密算法计算得到密码,用于连接,连接成功后开启定时器,自动向指定好的 topic 发布采集到的温度湿度和光照,并且订阅云端控制设备的 topic,用户向云端发布json 数据,开发板接收到云端转发的 json 数据会做出响应。如{“led1”,1},开发板收到数据后 led1 会亮7 x( l8 Q: z) v* e- @

7 o0 _4 l  Q# U
源码分析! g# |( B) a: \
WIFI 连接模块
  O9 A- e3 o9 d4 |$ S在 Qt 程序里使用 system 函数来执行 5.2 的命令来实现 WIFI 的配置
; x* U) p' W% p* b. V- I# `; a2 a4 g. Q% O
GMN2XFQ21XQZ2_8SU2`_LAC.png 8 [# c9 J" u' q* B3 @: h, Q

* f: h1 Y- l  B  L
建立刷新按钮信号槽连接,实现点击刷新按钮界面显示附近 wifi。实现原理是启动 wpa_supplicant 进程并在后台运行,扫描周边 WiFi 热点;
9 I1 Q% j( e: k* N
- N2 H/ a. }! Z
使用wpa_cli -i wlan0 scan_results 命令查看扫描结果,并将扫描结果重定向到wifilist 文件中,对 wifilist 文件进行读操作,将读到的数据直接显示到 ui界面上面。核心代码如下
7 q3 l; v, l+ p, x% X, d7 q% T5 `# q, U6 J' z
……
8 ^- W# C! F! N2 W$ d
- \7 \& Q& U* b
system("wpa_supplicant -D nl80211 -i wlan0 -c /etc/wpa_supplicant.conf -B");
/ b0 o" m* U9 h: V8 g/ R9 Fsystem("wpa_cli -i wlan0 scan");( M" f3 C( C+ `
system("wpa_cli -i wlan0 scan_results > ./wifilist");
% o% ~$ h7 F% Z9 B, Wusleep(50000);$ S9 `& r3 z+ T: }& a
QString fileName = "./wifilist";
3 q/ w" @% b2 m% f9 C2 q- c; HQFile file(fileName);
9 d3 F  g% N+ B/ R1 b2 fint f = 0;& ]; _  K3 L: S7 Z2 v
j = 0;
$ F0 X& t! B3 A if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
! X: j/ G0 s  O' k+ s5 J& D {
9 m* c: n1 \- Q0 G. M QMessageBox::warning(this,"Warnning","can't
& B1 f$ k; y0 I0 wopen",QMessageBox::Yes)
4 g5 P2 i3 r$ \; c  [0 { }, \( W. ~! n/ p6 K" Z7 C
QTextStream in(&file);
- v+ D$ {. _) z* ?1 e QString str;# B- X2 Y. B9 u  s5 z
while (!((str = in.readLine()).isEmpty ()))2 D: `- ^3 p# M+ ?. y
……9 K& ^1 l+ `0 W& N

* H6 W$ }+ p' Y3 B) f. R

( W- e; t9 [' i, G3 \6 h连中刷新后显示的 wifi 名后,点击连接会进入二级界面。二级界面输入密码正确后点击连接,等待几 s 后即可完成连接。这里输入框使用自定义类MylineEdit,继承自 QlineEdit,增加了鼠标点击事件,当触摸屏点击输入框的时候,会弹出软键盘,用来输入密码
2 E  _$ [( r; n: R
* H8 L# }# }8 ]6 M' _9 f
EL{X(8C[6Z[B5K%RN`U9[]8.png
% y: u9 R5 O4 m  J) O( l
) u5 ^8 l6 X& b' |1 e: c
' V" t/ R7 Q' i; Y* o0 R$ t
这里连接 wifi 的核心代码如下:% P* x9 A- W6 Q; z3 Z

2 V( F. u5 A# g0 y% O) ^1 S

' o7 a$ I9 N% y" a6 r3 d" h3 x& r; N
  1. sprintf(set_ssid,"wpa_cli -i wlan0 set_network %d ssid
    - F- J, E- }& d! r) z. W9 g

  2. # z0 b! r6 G( P0 u8 o
  3. '"%s"'",i,wifiName.toLatin1().data());
      G- U0 |1 i0 G! L* m  O

  4. 9 Y. ?! p' ~: |5 E: ^
  5. sprintf(set_password, "wpa_cli -i wlan0 set_network %d psk '"%s"' >
    . h# B$ a& k4 _" d

  6. # K: p3 _) R* K3 O& W0 U; z
  7. TorF.ini",i,password_edit->text().toLatin1().data());7 c! `/ h  m/ b% I2 b2 P
  8. 0 E: |$ {) b7 F( t3 N* X& f
  9. sprintf(select_wlan, "wpa_cli -i wlan0 select_network %d ",i);1 d( x, r. L( l3 g: O" ?# b8 B
  10. + z9 ~! c3 ]! n% I  ]' `2 w% i
  11. system(set_ssid);$ s! |; [- f/ Y/ n7 Z
  12. , D  K7 ]# q$ F" X/ V
  13. system(set_password);9 B2 U$ I0 S8 [4 R" B

  14. 0 ^* u/ N9 b* T- r( {
  15. system("wpa_cli -i wlan0 list_network");
    " R3 v5 w" X  ?) U, b
  16. / _7 o% {2 ]3 b7 s0 c. e
  17. system(select_wlan);
    6 T  V9 I0 g  p

  18. 9 m# }+ y  x" H4 W/ ~% ?
  19. system("wpa_supplicant -B -c wifi.conf -i wlan0");" }0 x6 I* ]& z' O# R( _$ \' t" t

  20. 0 d+ B& \. s3 a
  21. qDebug()<< get_TorF().data()->toUpper();5 `3 ]5 ]6 N! p2 B* |/ N6 q

  22. + z* _* y* w: u2 z( c
  23. if(get_TorF().data()->toUpper()=="F"); }7 C. a' j. I* E8 }' @9 V
  24. ! S% P( D* ]" T/ A. z
  25. {
    $ w) Y3 ?$ z5 t+ Q' n* E5 |

  26. 2 U( t. z( g/ Q! T
  27. QMessageBox::warning(this,tr("Connect information"), tr("密码! V1 P9 ?# S3 Z
  28.   H+ Z8 {! h+ e
  29. 错误"));5 Z" e; O! }6 Q4 d; U
  30. 8 _7 F) R2 |0 p/ m
  31. return ;  Z) Z& [7 |6 B

  32. 9 P# V  i: E7 B  B4 B- k
  33. }) ^7 @4 L& |* q) n5 n9 [

  34. , C, z; @1 L9 z$ g& j: \. Q
  35. system("udhcpc -i wlan0 -B");3 `" ~/ E+ r; _2 G  h: ~
  36. + M+ b! g7 v" a9 G9 `. o6 H* L. b1 B
  37. char echo_1[64];! {! {5 k; l4 B8 x7 u6 Y7 k
  38. 6 r* D7 F; a  [: h) Q
  39. char echo_2[64];# w& L9 i3 N+ h" i0 `: G
  40. & F9 O. [* @% W( a
  41. sprintf(echo_1,"echo "nameserver 114.114.114.114" >
    6 J+ G3 Y: H1 b4 m
  42. 8 s* l) l) b' ]5 ?3 X' g
  43. /etc/resolv.conf");+ w! G9 P! n; X& c5 x

  44. 6 ^; i. E& _' F
  45. system(echo_1);; [9 T0 e4 L7 {5 ^9 z7 j' V& M
  46. 8 E9 K5 [, o6 U" K3 @
  47. sprintf(echo_2,"echo "nameserver 8.8.8.8" > /etc/resolv.conf");
    ' W5 B. s5 S) u5 ^

  48. : ^! G' W; E6 d, x
  49. system(echo_2);
      O: T# c/ L$ @) i6 ?- }2 j0 J

  50. ; X; L! i( p# q4 T& D' u4 I+ j
  51. close();
    9 B0 f* @( C  {& I) j% I. Y! P
  52. 4 B, m8 X) ]. [1 A5 M0 o
  53. QMessageBox::information(this,tr("Connect information"), tr("连接成
    6 s  s' V8 B# Q- q! h3 f

  54. 5 L+ H  I! A7 N9 _5 B( v4 ?
  55. 功"));
    ' U8 q  h% @3 {" C1 ~
  56. : s  G  _7 [( C- `5 I
  57. }
复制代码

: K7 {8 c" Q% B
, i: ]" e, K! v; T2 h$ g5 K; g
智能门禁模块
% @0 B6 y6 V$ _* j9 A
$ {5 |6 ~/ h/ h6 x7 a/ u2 t% g+ C, V
]5RF`O{20C45JT5@87([)XM.png
. F+ l) U* k' r7 H2 R$ B, U
% t0 ~/ [8 h' S: L0 pPanGu 开发板有多个 GPIO 组,查看 GPIO 组信息,可以使用 gpiodetect 命令。1 p2 K" ~% I5 V( ~5 q1 [
  1. # gpiodetect
    5 T5 [; o$ x; F6 H

  2. 3 K  ^3 u8 F8 s5 T
  3. gpiochip0 [GPIOA] (16 lines)
    8 _- v, M' b  H% C

  4. 6 N; C0 d  ]: j# l8 F: g
  5. gpiochip1 [GPIOB] (16 lines)
    2 o) r9 d+ ^& T& C2 k
  6. 3 M8 ^( m% S0 ], `
  7. gpiochip10 [GPIOK] (16 lines)
    ( V* m5 t- Y( R! F: O

  8. ; c- z' r9 `% v1 c; |
  9. gpiochip11 [GPIOZ] (16 lines)" [8 ~1 Z$ t* C& b- Q6 x

  10. $ l  k/ k' j( x7 M! R
  11. gpiochip2 [GPIOC] (16 lines)9 p& G, F+ n. B" x( s

  12. ! b; O7 W; V: ?- C7 x$ V. \2 f
  13. gpiochip3 [GPIOD] (16 lines)
    9 U' X  r: V/ _' K5 ~8 W' R6 m' O
  14. 3 i, b3 c. P  F: B
  15. gpiochip4 [GPIOE] (16 lines)
    ( K7 |& U7 L# e+ v$ J; n6 c: ]- G0 ]5 i

  16. , P) B" g. _& i
  17. gpiochip5 [GPIOF] (16 lines)# N& u+ V( z, }, ^& A
  18. " x# n# j& E) Q) }2 E: Q
  19. gpiochip6 [GPIOG] (16 lines), J0 Q. e# m3 {; F

  20. . ?2 w: w1 z1 P* M4 O
  21. gpiochip7 [GPIOH] (16 lines)
    " z1 y2 H4 W! k* S" U; s
  22. 5 }: ~1 y  j; o+ q) m& x! B
  23. gpiochip8 [GPIOI] (16 lines)
    . a4 v0 i+ \+ Q

  24. ( S5 S5 F6 w$ P8 K3 ~, r
  25. gpiochip9 [GPIOJ] (16 lines)
复制代码

2 I% m) k$ S+ m1 w通过查扩展板的原理图可以看到 :光电开关的 GPIO 管脚是 PE15- T& K' ~' E" k1 E4 r2 A
8 R$ y7 C$ x. ~$ X
读取 PE15 的状态( J8 |( l; Y# Q/ D5 r
7 u1 f# H$ R+ Q8 O
# gpioget gpiochip4 15
3 b: \3 X# d; t& }4 S# ?5 z& }1 W# e, |1 Q& K9 f( x% T9 @5 a
当有东西遮挡光电开关时,执行以上命令得到的是 0;没有东西遮挡。得到的是 1.; E5 c  l9 Z  ~' l1 W

- L  P4 W4 k! t& ]& y所以我们开一个线程让它一直去读取光 PE15 的状态,当读到为 0 时,说明有人,发送信号给主线程,使主线程开启登陆界面。
8 S( k- ]! |, k5 E& s+ y: @
  1. void ReadPE15Thread::run(), u* B; @4 |/ q9 W: @" ^$ u

  2. ( o# ]; d' T: l, g9 W9 a
  3. {
    1 D1 V- Y) n' U, k5 `

  4. " N- j  K: Q2 X
  5. system("touch pe15.txt");# l5 k9 }: ?0 K8 B- ?' N! m* c

  6. 0 o' t$ k4 r8 z2 c: }& ^' @% z
  7. system("gpioget gpiochip4 15 > pe15.txt");9 q( O2 ~  J- V; P
  8. : E4 E" d( M3 w' F& k0 o8 ?
  9. int fd;
    ) s( u& `$ s# F% C
  10. ; ~  [$ l4 G, f2 O3 `- @$ @8 U1 ^0 P
  11. char buf[32];8 Y: F& j1 s! P6 ~7 S2 _+ h

  12. " _0 ]% N5 W& b* ]. |0 ^" q
  13. while (1) {( B4 y5 i* y; A% }

  14. . \, E. W( K0 H: G2 ]
  15. fd = open("./pe15.txt",O_RDONLY);
      C; l' }1 X3 J* ?& C" F+ S& s
  16. ' P" G3 L( J$ R
  17. system("gpioget gpiochip4 15 > pe15.txt");) c& U$ a' r1 z+ |4 O

  18. # @3 r6 N( i1 y3 j& {. w0 q) W
  19. read(fd,buf,sizeof(buf));; x5 a$ [, [2 U9 T, B$ u
  20. ) C( p0 Y; W7 P7 e8 `
  21. if(strcmp(buf,"1\n")==0)
    ) ~: G8 l$ @+ s" ?6 @' g, w

  22. ) i4 V+ t0 P7 J- o9 [5 m* I
  23. {6 p9 s/ N/ k+ H4 u8 m

  24. & G( H$ K8 [3 v) J2 Q, b, d2 Z
  25. qDebug()<<tr("login !!");0 }7 M/ \" p, Y$ @% r
  26. 2 V& E5 Z' Q: o: r$ O# n9 v1 P
  27. emit pesig();
    " V0 ~( N0 h% q% s3 E7 ]
  28. 8 X4 A; q+ ~3 f% @/ C  V
  29. }
    ( A; T. T/ v' V. i! s' M# i

  30. ; K$ [0 x4 [  M1 g0 P
  31. sleep(1);2 L4 ?2 ]3 D- U" z. i0 _" T( x8 ?
  32. ; F1 A6 |6 z  x- H
  33. close(fd);
    6 c- @0 B5 w6 v4 u8 _
  34. + S' `; G7 `+ o/ _
  35. }
    $ O7 d5 F- r! k. W6 Y) \3 }
  36.   ]4 i9 }- L1 X0 S9 f
  37. }
复制代码

$ Z  j# u/ v9 ^* e6 w1 ~建立信号槽连接
9 ~* f) q7 @1 `; A' y. U6 @
  1. void MainWindow::loginSlot()
    ! q  O8 g/ m9 j  L0 s2 w9 @

  2. # a0 G9 N. ]4 c9 [
  3. {+ B0 t" n" {1 Y# m

  4. 3 \4 ?+ N4 J$ [+ X! l# B3 {4 v
  5. disconnect(&pe15thread,SIGNAL(pesig()),this,SLOT(loginSlot()));! \' c+ {& E5 `- O
  6. ! T4 F, m8 U+ Y; q
  7. login->show();
    + W  S2 z/ P8 P& _+ {
  8. 0 ]; \* j9 i1 w; W0 `
  9. connect(login,SIGNAL(loginsuccess()),this,SLOT(loginsuccessSlot()));
    5 ^2 h* G& k6 i' H+ X' j* i

  10. 5 Z/ g' d( d0 S
  11. connect(login,SIGNAL(loginfailed()),this,SLOT(loginfailedSlot()));
    3 k0 c. K. p$ u2 m
  12. & _, Q& _# X. ]3 H# I! g
  13. connect(login,SIGNAL(loginclose()),this,SLOT(logincloseSlot()));+ Z4 N" {* P5 o! _
  14. 5 O7 o) g& j4 V3 p1 c0 m
  15. }
复制代码
" [2 C  z8 @! U* s, B
登陆界面的编写2 u/ j* S( m0 t/ z' p, p; L

6 p  D1 X2 t! I7 C% s1 e- w0 d
编译 UI 界面。, u7 U: }& D" m

  a& X' p. Y! M$ C- G
创建 usr.db 数据库文件! P1 U, c; w6 K- T: Z$ K5 f3 L! |2 j

* t) @, ]/ d! d2 Z: O) D+ \: |9 b8 D# sqlit3 usr.db( F" w  a- |! b- ?8 A
$ u0 b. w5 K6 |; ~
创建表/ T& C, g3 S8 o) z9 C* u4 K
3 a+ A4 b! V7 G9 y; A
sqlite> CREATE TABLE usr(( y6 Y6 H0 }. G" |6 B, a2 I) z# U0 o+ {

7 j7 Q9 z% B/ L usrname TEXT PRIMARY KEY ,
$ ]2 h, l6 Z) Q* v1 ?! }* @( ]$ }# X* G$ v! ^7 ]
password NOT NULL+ A" Q# A# {! m
" ~" B  P6 u% K9 ?1 X
);1 M4 w2 S: D3 ~
; ?' f5 e) o; f$ f4 p) E
向数据库中添加用户名和密码
) W2 f4 v. R: ~7 F: S9 j8 m! E" J" F! h
sqlite> INSERT INTO usr values(“usr”,“123”);
8 n: ~- H  }6 W0 y/ Z2 W4 b* h' s  ?* k& z) N
login.cpp  q# L' v1 f4 F+ K
, f2 a" q" x9 C- H( ]* ~
打开数据库 验证密码
0 ]* J, U% a7 B6 ]1 m; V1 X
  1. bool Login::openDb()& P/ I0 [. v$ G$ p( I
  2. 8 Y% {* d( O: t! @3 U
  3. {6 Y- q6 f5 [; _" X' T% l9 M

  4. 7 M) F& l( ^) ^, N8 M
  5. QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
    7 U) d: W/ h2 f# W+ Y
  6. 1 u# P, D# O5 o4 a: `3 |2 y# g
  7. db.setDatabaseName("usr.db");
    " G7 M2 `" {" Q! a. ]$ f! C" \7 x
  8. # ~1 J  T) b' J. `! I
  9. if(!db.open())
    , r# V0 E4 J" K# f# _6 B& |

  10. & A9 G) b5 d0 Z; U# [
  11. {, B1 ~8 E, Y# I; b, X& Q
  12. 3 P* N' R; w& o# l
  13. QMessageBox::warning(0, tr("Warning"), db.lastError().text());
    / P  T9 w: F! U" g9 t
  14. ' R; x; W* V% }8 p. e
  15. return false;; V: ^, ?$ u9 p4 X
  16. 9 X) h2 C/ S% i$ [3 A  s4 F
  17. }
      d# s3 F, G% j* O/ _

  18. . T# a2 ~9 P! n2 g' }8 }  V3 F; U
  19. QSqlQuery query(db);
    9 Z* u; z0 B0 j- X8 K$ b1 j( @
  20. ' u6 p" `( c" m5 \3 w% A) _
  21. if(!query.exec("select usrname,password from usr"))
    ) V% Y8 _" G  S% O5 L
  22. * h6 G* @& u5 [+ j' _
  23. {
    & u* s3 b! u% x$ M7 J8 K
  24. 3 h& w* o2 X8 ~, l3 `3 O
  25. db.close();3 F' z! w3 _5 x
  26. 0 p) Z/ l9 t7 n) P' n+ E5 k1 l% p* m
  27. return false;4 G: f$ y' U% a7 e8 Q/ X% l' g
  28. 7 ?4 e' R6 @- x- X; g8 U6 `
  29. }3 f: k* c4 L- a: h( e  V" h, Q

  30. 9 s  K8 E/ P+ Z1 y! P% X
  31. while(query.next())
    1 K$ T: R  s$ f( S# h
  32. # b$ o- ]9 Q9 u8 g& p/ W3 o
  33. {/ D% {1 ?" O4 f8 V  h6 w" f% U2 n
  34. 0 d% [. k0 f) \: e) l  a
  35. QString UserName = query.value(0).toString();% ^7 w6 v" E$ Q; G! W0 h
  36. ) Q- G- j1 `8 A/ N; i0 h* L% y
  37. QString Password = query.value(1).toString();# f* S& a# B0 U  H

  38. 8 V8 G( {1 C, O) u2 A
  39. // qDebug()<< UserName;
    & C% M1 g' a: U2 H

  40. # o9 D* ?2 h9 s. x
  41. // qDebug()<< Password;$ [' H" @& ?1 w" y
  42. , h5 Z5 F% r; }& F# u$ ?6 H
  43. if(UserName == usr_edit->text() &&Password ==password_edit->text()). b5 h9 v. o8 N. H

  44. - c  g1 ?# }5 ]2 k  m/ T
  45. return true;& M' N+ _) m5 i4 H; k* N
  46. 5 r" l. ]1 k0 A' {& \0 z2 r
  47. }% I6 F7 \. z8 |
  48. 7 ~% \3 E6 p# a: K7 P
  49. db.close();
    * ]' I6 i' P" a/ Z( |
  50. ! P  Z9 u( x. e! B) g$ L: `1 v! Z# D
  51. return false;
    5 m( U8 X% [) E* N3 n( A' ^; t

  52. 7 x; \- q. `9 v, i8 M
  53. }
复制代码
/ }2 N, Y2 k. o

( U+ J  n. q! I) T  L登陆成功发送成功信号,登陆失败发送失败信号
( p* [- }( |0 `/ ?0 T
  1. void MainWindow::loginSlot()7 G0 N& p0 D% ]7 M
  2. 6 Z8 o- {1 S; Z% H# t4 U& q
  3. {) ?  e& d, Q# v, m  J' C" i$ @) C

  4. % t1 E+ }7 v' H9 I5 F! A
  5. disconnect(&pe15thread,SIGNAL(pesig()),this,SLOT(loginSlot()));
    4 M9 C) n# u6 k% L) `

  6. 8 I3 e. u5 D2 z4 }5 ~2 J% d
  7. login->show();, Y) {3 ~7 [! \5 b0 u
  8. * E( F+ b' I$ D
  9. connect(login,SIGNAL(loginsuccess()),this,SLOT(loginsuccessSlot()));1 u9 Z6 B0 s* f- U1 J, p0 f* D
  10. 9 a) u) E6 R% e7 X2 b* M+ x
  11. connect(login,SIGNAL(loginfailed()),this,SLOT(loginfailedSlot()));0 n* z" U8 p) m  S
  12. % O) u0 E1 w+ i4 I
  13. connect(login,SIGNAL(loginclose()),this,SLOT(logincloseSlot()));8 ^5 H4 W) @) s
  14. 4 G8 b0 R, \  y- b' X9 U3 R. e5 t$ b, U
  15. }
    2 \  W, p: `2 Y9 Z% ]
  16. : ?9 `# r5 b5 f
  17. void MainWindow::loginsuccessSlot()
    3 \% b* v& c3 `5 b
  18. & s6 O6 O. f1 g) Q; I' |3 Y
  19. {
    2 d+ Y  v! v- `3 f3 }! k0 V
  20. 7 E) c0 t. i9 v% ?
  21. QMessageBox::information(this, tr("information"),"密码正确,门锁已打开");! r. g6 k% `  {

  22. ' c! Z( K2 V9 b
  23. // 重置错误次数+ b' i2 i; z6 y( W4 x
  24. $ n, {- o- b0 n; \) d7 u+ l' p3 h* g
  25. Numberoferrors =3;& E1 p' i8 y* J

  26. ! F, b( G: O, @0 n
  27. login->close();& v5 C: O( E9 b# f& j

  28. $ G" _$ z. \& T: B
  29. beepunring();4 V$ q' I  V( {3 \$ _6 `: E

  30. 4 s1 R! Z5 H* {( c2 S' @/ q
  31. connect(&pe15thread,SIGNAL(pesig()),this,SLOT(loginSlot()));
    ' k$ @3 F$ R" I' q9 s5 i$ X
  32. . Y. X* j2 D% c$ G( \2 P6 {
  33. }
    ; r4 t  d" T3 m6 n3 {* l% {
  34. / E4 f" ^7 o6 e) J: _
  35. void MainWindow::loginfailedSlot()
    5 Y8 }5 d; o* \- H7 t6 s
  36. 3 p- Y3 R' o  U+ p( F3 J: P
  37. {
    ) H2 R  E" U9 d! C* ?

  38. ) I7 {6 x( S/ u7 Q0 v
  39. QString info;; j: B3 e5 n% D" W! V6 k
  40. * |; m; ^: |- M4 ?6 j! y# H
  41. Numberoferrors--;
    ; Z- \# c3 ^) D$ p# ^
  42. ; t; I) d# P8 v3 s
  43. switch(Numberoferrors)
    $ N' C' R- Q; F& ]
  44. * a; z6 q# L# Y+ [( t2 Z+ ]
  45. {! V' t& I4 E1 D0 z6 {

  46. * q/ @0 n2 g$ m9 ~. W
  47. case 2:
    $ u& S& J8 d$ x6 g% ?
  48. $ R# A2 x8 }, B+ T: p% a5 m
  49. info ="密码错误,还有 3 次机会";
    3 J$ u9 a, Z1 ^7 x, M  z! n% z% k

  50. ) C7 |1 U. b3 w
  51. break;
    6 Z7 k2 k( n* w# j/ B$ v' B* K

  52. , {& X' q% m0 v4 E" w( Q
  53. case 1:
    ; h6 h0 {# N7 A; h

  54. + u+ w2 z, J- c* r. q( ~& |
  55. info ="密码错误,还有 2 次机会";; T9 e- \7 K, p! ?# K% ]+ u
  56. 6 w5 K! O7 \& X" E. ^* j5 S6 q
  57. break;
    ) [; o& X1 n+ V! }

  58. ! J% j: T. w3 n+ m2 M
  59. case 0:
    0 Q- P/ T6 M1 J6 z( T# [( C
  60. 2 w( ]" n+ |* x5 N& S
  61. info ="密码错误,还有 1 次机会";
    1 m! ^& [6 |! K, c, Y4 I

  62. . V1 Y+ I3 R& P/ g/ i
  63. break;+ k8 r! n0 Y4 W; g# ~& o8 e  u- e
  64. ' H4 V3 w8 v8 E( I
  65. default:- A+ w$ g! M! Z6 G' r2 c
  66. . @. Z5 J; i3 z8 x" N. g
  67. info ="即将报警";
    ( ~. A8 I2 c0 W4 O1 Q) l( c

  68. * f" Z6 ^' g  ?0 x- ?* w6 \( D' l
  69. break;
    + ^: k! G' l+ w1 u( s

  70. 0 |4 x! p: O) P
  71. }
    & ^6 k% ?, k5 W2 x
  72. " ?* X5 k3 [$ p2 W, v
  73. QMessageBox::warning(this, tr("warning"),info);; i! u7 B! ?- N/ ^
  74. 4 X( |" g) O" _) g9 E0 g
  75. if(Numberoferrors <0): o: O. k' P6 I, ?

  76. 9 @$ ~) a" B, ]1 y
  77. {
    8 n- V& C* e+ h( K) x6 m$ f) |) P$ v

  78. 3 S6 S( C, p3 V& ^6 g
  79. qDebug() << Numberoferrors;& d: |- E1 B! |  c! U( H
  80. ; v( ]: s; t  `# u4 d3 P
  81. beepring();
    & K' Q/ b' q" u
  82. % D: x4 R/ @  l- S) F$ _' G
  83. }) x% t5 H/ t/ n2 v8 J

  84. 1 c$ j. j1 e2 H" z
  85. }
复制代码

) M. \) C4 t/ W验证密码错误三次后蜂鸣器报警& I% c6 {+ E) B# ^
( b: C7 k: j; s$ `
数据采集和智能检测模块
' g8 `( q! O4 {8 S) L" E1 ?. @- D- g5 @  P6 @1 t- C
系统启动后可以查看目录/sys/bus/iio/devices/$ P+ L+ Q) k9 K+ @+ D( E7 d, l2 U) c
/ X* m' Z& x8 P6 c; m) X! x8 c2 l
root@fsmp1c:~# ls /sys/bus/iio/devices/ iio:device0$ r8 a( {5 [' q
: L. o) ]9 O+ ~9 M  `
如果系统中有多个 iio 设备,这里可能会有很多个 iio 目录,确定哪个
& m# c1 }1 }2 |  J# V) J4 l' y. H8 i6 v

1 j4 Z4 h) z! z( j6 d$ |4 L0 [9 f目录是我们的设备对应目录,可以通过查看
7 a+ F. I# t9 v( e
) o' Z9 x7 M' `7 E9 ]! r/sys/bus/iio/devices/iio\:device0/name 信息确认:
+ b- |$ J  u2 ~# n! w9 R$ u+ ?# g. V3 ^
root@fsmp1c:~# cat /sys/bus/iio/devices/iio\:device0/name
; |# L. ^! Q- _$ P  v( K: `% O+ Q8 ^' K2 [2 Z) [
0-0040
8 d% P) G7 b/ @
5 [5 K2 ^; y0 j4 Z4 q0 n8 H: O8 `
由显示信息每个驱动对应设备可能有所不同,当前显示内容为设备的物理; K8 i, s) f: i' V( V! G8 r
" O! N; p7 i7 |8 V" t
地址,与设备树中地址一致,可以确认 iio:device0 是当前设备对应目录查看
+ }6 n- Y4 w1 X# d/ Q5 h. w+ v4 h/ }  x- k
当目录下内容:  W9 J  G: L* H
  1. root@fsmp1c:~# ls -l /sys/bus/iio/devices/iio\:device0/$ x+ c" y# b' L  _  y6 |; g7 g

  2. 8 R- G* o7 @, ]# {& t- {3 Z
  3. total 0
    ; E3 h: u4 k# K7 r7 \3 f+ _" B

  4. & i" P% J/ a7 U1 e5 N# ^0 ]8 U/ o
  5. -r--r--r-- 1 root root 4096 Feb 7 15:51 dev
      l( d. @4 ]5 \" a' s

  6. - ~( P, V" O& E8 P% ]. F6 R
  7. -rw-r--r-- 1 root root 4096 Feb 7 15:51 in_humidityrelative_offset' Z( }7 o0 |$ ^( K

  8. % C6 R; [$ u" \
  9. -rw-r--r-- 1 root root 4096 Feb 7 15:51 in_humidityrelative_raw
      A! O4 K4 e; p5 }
  10. 2 l0 h( b6 p7 d
  11. -rw-r--r-- 1 root root 4096 Feb 7 15:51 in_humidityrelative_scale
    & v4 Y; L4 d2 G0 c$ w; g

  12.   I7 K( q, j- W' l0 P
  13. -rw-r--r-- 1 root root 4096 Feb 7 15:51 in_temp_offset
    2 ~% f# ]) L' K4 l$ d/ ^! Z; N
  14.   J5 u' ~& r: Q  j, i
  15. -rw-r--r-- 1 root root 4096 Feb 7 15:51 in_temp_raw9 a+ A" R7 S( T7 W7 }
  16. & I' u' k- y# [/ a3 ?$ \% U$ `2 p
  17. -rw-r--r-- 1 root root 4096 Feb 7 15:51 in_temp_scale/ {6 e2 f' h; x3 V4 ?$ w! C
  18. : g7 O- q3 E/ H: g6 k+ m4 c
  19. -r--r--r-- 1 root root 4096 Feb 7 15:51 name- j; _. M2 f% ?2 g
  20. $ I) w. L. R7 ?2 @8 j
  21. drwxr-xr-x 2 root root 0 Feb 7 15:51 power
    % k* A& _( U$ S( W' Y! z' W8 h

  22. " K, l$ }) E5 l
  23. lrwxrwxrwx 1 root root 0 Feb 7 15:50 subsystem -> ../../../../../../../bus/iio, |$ s8 d4 K9 L5 r- M

  24. ( j6 _4 {  Q! b: W4 R
  25. -rw-r--r-- 1 root root 4096 Feb 7 15:50 uevent
复制代码
5 i) k. _: C* U$ k& I) I+ X+ m0 s
2 G, d) ?$ Z0 c! y# ^: b* l/ w9 L7 x
转载自:华清远见研发中心. B* a# S8 ~. w, D5 V1 D* y/ k* w: \9 o
8 d+ E/ f% ~. o% }( d' K
: U/ B3 Z" z. {/ P: y
收藏 评论0 发布时间:2023-2-10 15:21

举报

0个回答

所属标签

相似分享

官网相关资源

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