stm32连接服务器端0 P9 r9 b8 O7 F: [. q8 e+ }& E5 @
本章所用到的器件如下:
. R3 g4 h- b/ Z ^) u, y; rSTM32F103ZET6最小系统板. n: l5 n, C1 c* K# u r6 U; f9 K$ q" t
ESP8266-01S模块
- Q Q4 P! q% o/ PUSB转microUSB数据线" ^; p3 X0 q0 U t. u. U
四根杜邦线
* s* Q& ]. u) S' J9 {9 Y- e7 }8 A连接如下:4 H* ^$ G9 G+ E" w' y* G7 }
32板3.3v----------->ESP8266的3.3v! D% b- `! d5 {+ X$ X1 g
32板GND---------->ESP8266的GND
" P# k v2 S6 f- p4 g32板的PC10-------->ESP8266的RX) f9 l2 a, F6 ]6 h. e
32板的PC11-------->ESP8266的TX" m4 R3 I, x+ U; u# v
& M/ K& L8 Q2 D, x; i8 D2 L, l0 M 在这里说明一下,由于本项目是用在其他项目上的,所以在编写此项目时,是基于另一个项目还未被使用到的串口资源进行设计的,所以我这里用了串口4。各位需根据自己硬件已有的串口资源,自行手动修改串口4初始化的函数。
! {) v7 M" i0 y2 ~ B) q; i2 R" J" u% Z# Y( j
本项目程序是参考onenet平台上的源码进行二次开发的,onenet平台上源码的位置如下:进入onenet官网后,登录账号,在上方有一个社区->论坛,里面就有源码,点进去后就有一个链接是百度网盘的,这里我用的是OneNET标准板中的裸机基础教程->EDP例程。, x' t, W1 |3 v, s% a7 E
7 v8 q$ D# B ?" C
9 K8 p7 H: \, ~' B4 ]2 O" ~1 R( c$ [8 \4 D2 j# X, b# v5 y3 b! c8 g% o
6 N- {0 ]9 D' e4 K* G
( s5 \- L, h. @: {5 w, l
$ g4 P/ U6 `7 S/ b; X2 k8 M0 a: v2 d1 N6 [' u/ L( P q3 Z8 `
既然用到了MQTT协议,少不了要用到cJSON格式的一个文件,将cJSON.c和cJSON.h文件导入到stm32程序所在的文件夹下,接着在程序中onenet.c文件里面包含头文件cJSON.h,方便我们下面对接收到的cJSON格式的数据进行解析。- ^% y4 ~$ l5 Z9 @1 {( w
6 I* r) |1 H( n9 g9 b) A, V( d
6 A% p) l @0 e# [ l
: t3 ^! |( |* K8 R8 d% W# D 接下来,我们需要修改的是esp8266.c文件中的ESP8266_WIFI_INFO及ESP8266_ONENET_INFO,他们分别表示的是ESP8266需要连接的WIFI及服务器地址(修改成自己的WIFI名称、密码和服务器地址、端口号),本项目中给出了五个MQTT服务器地址,其中EMQX服务器是公有服务器,可以直接连接,至于其他三个服务器是自己在其他平台创建的私有服务器,需要用到onenet.c文件中的设备ID和密码。EMQX服务器连接的时候不需要用到设备ID和密码,所以设备ID和密码可以随便写。 9 f7 B* B" `- ~# L8 k
/ m- W% ]: h( I$ q9 w/ x
8 m. O$ E- j. m C$ ~3 V
* G( b4 b( J) V k D9 t, f4 h
+ Q* O z& x& r% O% p# T1 D/ x X3 B6 `" }6 ~" L+ C1 x
最后,需要设置一下主题的发布和订阅,对于公有服务器来说,是没有主题前缀的,而对于私有服务器来说,他有平台自带的主题前缀。 此项目中连接的是EMQX的服务器,是不需要主题前缀的,所以这里我随便写了一个发布主题和订阅主题(同时这两个主题也可用于我创建的私有服务器的设备相对应的主题)。
+ F. c( Q. p% m& G. H9 |2 J6 }5 \7 ~ D& O$ u2 M
) n6 u# M9 `3 r- H. p2 b
' W) I+ e" h+ K3 o! v1 c0 } 至此,stm32部分的程序已经搞好了,接下来进行小程序部分的制作。
, v2 t0 F7 X4 V: O( ^5 o* m; O( D6 N/ V H: X( J. Z0 I
小程序连接服务器
5 w; e8 p/ [, u" M 先上小程序的效果展示图( E# |) a4 {+ `5 v9 E: j
! G4 D4 p' f6 b5 { |3 t
6 q9 p7 ]( n; |; |
7 y& v1 T! t2 d6 [" b0 ` 此项目的小程序我没有用过任何框架,都是使用微信原生框架进行开发,其中首页涉及到天气数据的获取,这里请求的天气数据API接口采用的是和风天气开发平台上的Web API接口,其链接如下:和风天气开发平台
! |' C% \! [$ @0 k+ a! [6 ] 要请求该平台上面的API接口,需要在该平台上登录账号,然后进入控制台,在上面创建一个应用(目的是获取到一个KEY),如下所示:
6 E# o) o& A* |6 {, x2 H- [4 d: A% f$ E. f# ~. l
* T' P9 P u7 }! x& l. y0 a+ o6 B; ~1 R0 ?3 q2 R" }
接着到该平台的开发文档->天气数据Web API开发文档中去找对应的请求地址,上面清楚的写了该地址的格式及请求的参数等信息,下面是小程序端的获取天气数据的自定义函数:
/ n4 O% z. r. j* j- @2 O! w' Z! T! |& i: z# W& v1 c2 W
- weahterdata:function(){
7 @; Z5 x; q9 Z' u+ R - var that=this
8 A. [2 Z" E, | - wx.getLocation({//获取位置(经纬度)API( L+ x: Y$ P" p7 V) M2 `3 b
- type: 'wgs84',
6 ^8 M! a" p L - success (res) {# n- \' e- M w
- const latitude = res.latitude7 ]& _1 S0 H6 U3 l6 ^) n
- const longitude = res.longitude0 u" W2 S2 i$ \4 K+ N0 C) J
- const key="432a8840589546338cae4c5a825f47db"//和风天气开发平台上控制台创建的应用得到的KEY,只有得到这个,才能获取各种数据7 E) D! `5 [2 Q
- wx.request({//网络请求API
( v5 L+ N5 _' J y" z S9 U - //下面使用模板字符串! `/ s% b4 ~6 e v L' X
- //获取天气数据的API接口地址+ V' `% u* M9 ?- V6 T0 }7 d3 y
- url: `<a href="https://devapi.qweather.com/v7/weather/now?location=" target="_blank">https://devapi.qweather.com/v7/weather/now?location=</a>${longitude},${latitude}&key=${key}`, : c: c1 [! u1 m
- success (res) {* {" M. p' {* I/ I4 D" Q
- const weather_data=res.data.now
O& i( C$ f4 P) H) a# { - const weather=weather_data.text //解构赋值$ ^% Y# c' B- I7 H7 }( n$ f$ f
- that.setData({
) F, K1 t, q" W6 n& s( N/ q - weather
; P1 t6 E. a1 d+ c4 F# r - })3 f7 q. g/ N8 ? G- z6 z# U
- }9 d7 Z5 v/ e$ z% J& } S5 t
- })
) D- k9 y( d& G1 y o - wx.request({
' K4 V9 s* r2 L6 j - //获取地点的API接口地址: J' D' d9 i- M7 U; t- p9 e
- url: ,
$ V. ~; k- t4 {* {0 a: P* b6 [ - success (res) {9 \3 O1 s; W! T/ _' {
- const location=res.data.location[0]
4 Q8 Q* l3 [9 h# O1 i - const {adm2, name}=location //解构赋值
5 N$ M" O, L+ [) O# W - that.setData({
3 X1 ~6 E/ ` }: q8 j - city:adm2,7 C E) C7 w+ n' V4 A( v
- area:name
8 c: e/ c( c. z7 b% k/ t$ f; M - })
0 u/ P0 O9 _) j0 m& J/ D - }
+ U" M: q0 N& L d- Y) s' N' ^ - })
9 R8 Q. i }8 v& G" g! f8 T - wx.request({1 n( y8 x* {0 F1 u
- //获取空气质量的API接口地址, l$ Y) h& M9 w0 U( ?
- url: `<a href="https://devapi.qweather.com/v7/air/now?location=" target="_blank">https://devapi.qweather.com/v7/air/now?location=</a>${longitude},${latitude}&key=${key}`, / i# p/ s8 c- _
- success (res) {( o+ |) j, t, s1 f& Q/ o
- const air=res.data.now
( l8 x9 u" s- o: a! Q8 m( ^ - const {aqi, category}=air //解构赋值
( ?+ e' F, v* w( g4 U6 c/ }( H6 ~ - that.setData({
$ C( _5 {; T# _1 o, } - aqi,
0 X% L1 s! s- i8 l - airText:category
9 T# b$ N/ B: p* h. Y - })' j* N3 u9 ~. e5 t* ~. u# M3 y
- }
- x' Z% x. @ f) W c( W% b0 ~- i - }), a7 |+ C/ f+ _# f
r7 d9 m' o& e2 p2 x! n- wx.request({
, D" ~7 g+ P1 W! W' N# k - //获取生活质量的API接口地址/ ?5 f# q- w+ R% x
- url:<a href="https://devapi.qweather.com/v7/indices/1d?type=3&location=" target="_blank">type=3&location=</a>${longitude},${latitude}&key=${key}`,
. I6 z4 \8 S9 } L9 Y0 y6 V - success (res) {( w2 p# k! e( j! E/ d' k/ v
- const {text}=res.data.daily[0] //解构赋值
/ V& a0 Z+ ?. Q. b - that.setData({
1 g5 @. g# e7 s+ n1 s* j: S Q. {( O- w) R - weatherAdvice:text
t& ^9 ~6 q+ F% j& G6 F2 c$ C9 r - })3 \' T- Y6 @# A; r ]
- }5 @ S2 R6 p8 Y# ]$ ?% w0 Z
- })
- [! P5 D, S4 n" x - }
" D% b! j! ~4 f4 i' f5 a - })2 i4 r( Z) {$ J" P% E, K
- }
复制代码 9 i- e9 W; f6 x9 L
接下来是小程序端的MQTT连接部分,首先需要导入一个连接服务器的库,这个库叫mqtt.min.js。该库的地址如下:mqtt.min.js文件0 o2 w) J F6 m' p7 q- X$ G1 u
下载后,直接在小程序中建一个文件夹存放解压出来的文件,其中有两个文件分别为mqtt.js、mqtt.min.js,在小程序的js文件中只需引用mqtt.min.js文件即可,详细的引用代码及具体的自定义函数如下所示:(如果连接的是私有服务器需要多修改设备ID和密码,否则只需修改连接的服务器地址及端口号):1 K+ S% `# A* l* i' q* d* u
3 q3 G4 h+ k( o$ |7 S& ?- s/ C! Q: k
- var mqtt=require("../../utils/mqtt.min.js")
" A9 [) i: D3 [3 H2 L3 J - var client=null1 q" x) \* z. c
- Page({5 F6 a6 M' e; x. y* M- G
- /**1 y" L" x1 v4 F, {1 u% @4 p
- * 页面的初始数据
5 ?1 Z$ R9 @1 T- C4 g - */* x5 o( y6 a) ~2 V$ [/ ?
- data: {$ X. s% x, [$ P9 t" u
- " T5 q4 @3 `% t- ]# u# S) V5 `( ~
- },
' B, s# n* K3 n4 H& _& O - / X( e/ T! Z% [: G( ]- v/ W7 J
- onLoad(){
7 }% I* b' [ d4 b# _4 r6 W5 f' q - this.connectmqtt()8 A/ m2 s/ O$ v: C
- },& |# I! R7 q1 {4 y9 i
1 \7 z. `. B! J- connectmqtt:function(){% Q' v4 s5 S* ^' E) j* N" N% B1 r
- var that=this;//this是指外层的对象,如果在这里进行提取,后面进入函数后,他的this就是connectmqtt函数的对象+ _: r% s) [( E. F+ I$ s
- /*杰叔叔、EMQX专用*/! Z$ @, Q1 V) N' o) o, h
- const options={
" g: Q6 m4 S, E8 T/ a( }4 Q - connectTimeout:4000,$ Q# c: f7 ~6 V* n
- clientId:"zsd", //此变量随便写" c( `- q5 G5 i& X
- port:8084,1 @; ?: S( r) C2 T9 U6 x& g; I6 n8 C. L
- //杰叔叔的服务器是私有,所以需要账号和密码,而EMQX的免费服务器不需要账号密码3 x. G6 c n. e6 t, Y
- username:"f6d61178afa1003ac5d41dc9ae10f0c6",
* e9 @% _' T- n* b* Q& ` - password:"123123"' Z' X: A& v0 K2 m! ?3 n/ c
- }
0 E6 v) o: \) k6 b B - /*腾讯云MQTT服务器专用*/- F* q w& k9 S3 u6 k' @
- /* const options={' y2 h- l5 ]0 U* F
- connectTimeout:4000,+ U$ v. \4 _ P% t% s3 c( D+ }
- clientId:"zsd", //此变量随便写% P* h' V9 v0 {
- port:80,
$ M# W$ \, s+ g" B4 U7 O% U - username:"S2ME0J3F8Xtest1;12010126;bee9c;1656302400000",( t D+ Z0 Z7 K* e7 T; x0 e5 y! v' R
- password:"d58ce11e6725c4de9549c61d564f8bc0c7211707642ae92c63dd94b27943f85e;hmacsha256"# k5 p6 @* z6 q3 p2 v9 F! _
- }*/
( l( t, _% `% J. O& G4 ? - /*百度云MQTT服务器专用*/, e% v8 S s! g. w
- /* const options={
2 |: w6 A; Q( J% G# U2 U) o0 z - connectTimeout:4000,/ c$ X9 r' w0 I
- clientId:"zsd", //此变量随便写* C! x9 X. Y' U. ^; y* U
- port:443,8 [7 w7 \6 _# ~0 n) F x' a
- username:"thingidp@acwbepc|test2|0|SHA256",
. n2 r8 t" n# a) O$ l1 S U; E - password:"6fac92df9ce9cb5839cf95da0c0d8f60e3d5d333fff8b7d85bcaf5b5e71d8517"
1 i9 B8 H9 P7 t" @& q5 L - }*/
' T+ ~/ u! u$ I" e - /*小程序连接远程服务器时,用wxs(wss)加密连接出去,其他客户端工具,$ s7 Z2 }4 P% L I4 e
- 例如emqx在线测试工具可以使用wss协议连接服务器一;mqttbox软件也可以使用mqtt/tcp协议连接服务器一, r" f9 a% y- M8 n9 W1 v/ ]+ W k+ h
- 原因是因为服务器支持这些协议,本质上wss、mqtt都是基于tcp进行封装的
- O0 `. C6 G3 M* _, e - 实际上下面借助wxs协议连接服务器一,而其他工具也是借助服务器支持的协议进行连接,然后就可以进行数据的传输& [3 q; n2 V4 X) a0 S8 ]
- 如果连接的协议是ws或wss,需要在服务器地址后面加上/mqtt,如果不是前面这两个协议的地址,则直接连接服务器地址即可*/
+ F0 u/ D4 O) M - //client=mqtt.connect("wxs://t.yoyolife.fun/mqtt", options)杰叔叔的服务器地址(wss协议需加上mqtt路径)& N- Z q) k) e8 E+ n( f
- client=mqtt.connect("wxs://broker-cn.emqx.io/mqtt", options)//EMQX的服务器地址(wss协议需加上mqtt路径)
" e) U0 }6 o2 C4 p, g' b# } - //client=mqtt.connect("wxs://broker.emqx.io/mqtt", options)//EMQX的服务器地址(wss协议需加上mqtt路径) r8 V; J/ A/ b' o" y
- //client=mqtt.connect("wxs://S2ME0J3F8X.ap-guangzhou.iothub.tencentdevices.com/mqtt", options)//腾讯云服务器地址(wss协议需加上mqtt路径)/ z2 i, r( n7 ~" h
- //client=mqtt.connect("wxs://acwbepc.iot.gz.baidubce.com/mqtt", options)//百度云服务器地址(wss协议需加上mqtt路径)
4 g% O. r5 E4 z - client.on("connect",(e)=>{; R2 d6 O$ ?& F7 t2 J2 ^% p* G
- console.log("服务器连接成功");
* e) P3 q' S- \5 T8 a - client.subscribe("/iot/1009/zsd2", {qos:0}, function(err){//杰叔叔的服务器需要主题前缀、EMQX服务器不需要主题前缀' {, Y" d& [; x" E& X
- if(!err){
2 f) d# u0 s4 _: Q- n - console.log("订阅成功");# _. L6 n" }* M& d
- }
7 V, s/ C( p% K3 H, p - })
/ u3 r6 U) d2 K% k O, ^1 B* \ - /* client.subscribe("S2ME0J3F8X/test1/data", {qos:0}, function(err){//腾讯云服务器需要主题前缀( I2 b: T& P- L' ~ K
- if(!err){
3 }# f s3 p2 C' l. T7 _0 l - console.log("订阅成功");
' ~# m; v$ _* ]! Z$ m' N* C, L - }
& D0 E/ z8 C* s) q - })*/0 d l( o( I" z' v: x0 M! D) Z
- /* client.subscribe("$iot/test2/user/test2", {qos:0}, function(err){//百度云服务器需要主题前缀: W5 n+ {* r1 b" }
- if(!err){
, |3 w _1 q. u- @) i3 u8 J. n" q: ^ - console.log("订阅成功");
' t T C! x, d+ K/ O% m: ~ - }+ J. Z. J8 R; h; M$ g; B2 v2 r
- })*/
) U, i' b- L+ J- z- { - })) o% M F5 n; C9 M. k
- //信息监听事件. e- J; h$ a/ H3 E; `, j% ~3 ~6 g! X6 D
- client.on("message", function(topic, message){
. i& U9 o) I( l- h/ V) p- ~ I - let tem=JSON.parse(message)
! n8 c/ z O+ D3 H0 f! T - console.log(tem);" P- L( B; m6 R. w1 W) _
- that.setData({% @% s! [; g7 \. g" ]7 q% u
- temp:tem.a,# k6 s9 q2 A3 I( j' ~6 M3 e
- humi:tem.b
* m5 Q* C6 G5 p; d% F/ l( Q - })! e# B3 `( L$ x' w$ a; ^
- console.log("收到"+message.toString());, X3 A- p# k2 I% k6 A) `1 f
- })
% g. U9 O% s" B - //发送reconnect类型给服务器,一旦连接中断,就会触发重新连接8 t# s9 w+ m' h+ I: H+ Y/ J2 e
- client.on("reconnect", (err)=>{$ G: h- N# B8 m- q; d
- console.log("正在重新连接",err);" j% P- s( |% I2 a; o
- })
: V1 u# G! d6 [0 w5 A - client.on("error", (err)=>{* e* k( G2 ^6 V' x
- console.log("连接失败",err);* k" }6 F# u7 S
- })% K! w7 \" g. V' `* l. |$ |
- }% O% e; B* L5 I
& e. J& L% f# @. K. j* k- })& Y. |) _3 \' A$ O
复制代码
5 E9 o6 v5 Q- H' Q& C. m+ |: ? 至此,小程序部分的天气数据获取和MQTT连接已经基本完成,至于界面的优化,那就需要各位去学习小程序的界面优化啦。) e2 o$ ^( U: {4 G R" z( W1 X1 p
————————————————" k+ @/ }! Z* U% U
版权声明:i土豆
( y: p, a1 t" F' [4 J: o6 e# e2 U1 a. J4 r2 y
3 d0 x: Z( r: v: o# D+ ~- L$ i% j |