stm32连接服务器端
* v$ i$ O0 x8 E5 t" u# ]8 c$ ~本章所用到的器件如下:
# ~3 ?4 U, {5 M# R4 @% _. `STM32F103ZET6最小系统板" p. f8 F) d5 v
ESP8266-01S模块
3 s. X- M' g2 T, H5 QUSB转microUSB数据线
* t" h, ~/ s! k6 w U) A6 r& j+ }四根杜邦线; `1 S- A4 v6 `2 y& U
连接如下:- }9 F5 L+ [3 q1 t
32板3.3v----------->ESP8266的3.3v
! a+ d! W4 M3 A. l5 f6 h% I/ a32板GND---------->ESP8266的GND
2 K; h! G9 W5 O2 j+ R) G32板的PC10-------->ESP8266的RX
2 `$ Y5 |, T0 h9 k0 a6 f! ^! l32板的PC11-------->ESP8266的TX
0 c- E: X2 m4 t- p1 Q# q; q
, z( \0 i5 s# @: ~4 Z) y 在这里说明一下,由于本项目是用在其他项目上的,所以在编写此项目时,是基于另一个项目还未被使用到的串口资源进行设计的,所以我这里用了串口4。各位需根据自己硬件已有的串口资源,自行手动修改串口4初始化的函数。5 v/ `8 d" z3 o t
, G. ?6 t& E* K1 D" v 本项目程序是参考onenet平台上的源码进行二次开发的,onenet平台上源码的位置如下:进入onenet官网后,登录账号,在上方有一个社区->论坛,里面就有源码,点进去后就有一个链接是百度网盘的,这里我用的是OneNET标准板中的裸机基础教程->EDP例程。
, G8 ~7 k6 ^ X2 P5 ^4 V# X
+ @* ?0 p+ a' ~, ?' Z& Q8 s* k7 J( l
1 |9 Y, F" H9 ^! _, T. T
5 x& I% |+ L6 s, o1 Y4 j" J& v* D
8 ]( F* D( t9 |$ J
1 m2 J. G* I$ f1 [- C H1 |& B8 J/ P
4 i% H9 n! q7 |% |# }6 O 既然用到了MQTT协议,少不了要用到cJSON格式的一个文件,将cJSON.c和cJSON.h文件导入到stm32程序所在的文件夹下,接着在程序中onenet.c文件里面包含头文件cJSON.h,方便我们下面对接收到的cJSON格式的数据进行解析。 c' o# S% C/ w3 ^. D: }1 T$ r$ Y6 G
1 W" }. g' S5 _, T2 @# \
) Z9 E+ W! I9 n+ Z
9 _3 s) u- J* E
接下来,我们需要修改的是esp8266.c文件中的ESP8266_WIFI_INFO及ESP8266_ONENET_INFO,他们分别表示的是ESP8266需要连接的WIFI及服务器地址(修改成自己的WIFI名称、密码和服务器地址、端口号),本项目中给出了五个MQTT服务器地址,其中EMQX服务器是公有服务器,可以直接连接,至于其他三个服务器是自己在其他平台创建的私有服务器,需要用到onenet.c文件中的设备ID和密码。EMQX服务器连接的时候不需要用到设备ID和密码,所以设备ID和密码可以随便写。
/ J' S4 f% n) |, D
; g7 d; \3 g8 h( ~' l* V) A% s1 f3 S2 L$ f' S$ a. ?! r
& |7 @) ]% n; j# q9 t1 Q2 i) a, j$ v n4 }$ ~
( h" ]7 @! {" v2 D* e9 c
最后,需要设置一下主题的发布和订阅,对于公有服务器来说,是没有主题前缀的,而对于私有服务器来说,他有平台自带的主题前缀。 此项目中连接的是EMQX的服务器,是不需要主题前缀的,所以这里我随便写了一个发布主题和订阅主题(同时这两个主题也可用于我创建的私有服务器的设备相对应的主题)。: m+ U6 P# R7 ~) P
" |0 A" Y( {: `% k! [$ A" M
' w. j$ X. u* ]( V
+ { ?2 p# M0 _7 d9 S; F) o O5 O
至此,stm32部分的程序已经搞好了,接下来进行小程序部分的制作。0 b0 Z- {1 }5 a0 F0 l
1 q0 `/ m. I# h$ r小程序连接服务器
; ~$ x6 j; M- i" {8 G7 Z 先上小程序的效果展示图
& S. H0 q8 l5 i) x
8 }' [& ~8 n- ?, N7 V7 r
1 j' a/ c t4 ~/ F& v- T) r7 K0 X. ^8 \& v1 ~1 Z+ s
此项目的小程序我没有用过任何框架,都是使用微信原生框架进行开发,其中首页涉及到天气数据的获取,这里请求的天气数据API接口采用的是和风天气开发平台上的Web API接口,其链接如下:和风天气开发平台 A; z; U6 } t: C+ v8 z2 y
要请求该平台上面的API接口,需要在该平台上登录账号,然后进入控制台,在上面创建一个应用(目的是获取到一个KEY),如下所示:
8 J2 F* I7 p6 M. ^& \% j# ^* c: ^8 D4 V* }7 Z7 g
3 _0 Y, X6 j$ Q+ C+ M
2 T& k8 m5 T7 c+ x& J) _) d 接着到该平台的开发文档->天气数据Web API开发文档中去找对应的请求地址,上面清楚的写了该地址的格式及请求的参数等信息,下面是小程序端的获取天气数据的自定义函数:
. q3 H. S% G7 l# M) J/ s3 l' e) A) `% {: M9 S4 ~ v
- weahterdata:function(){
2 B$ W4 \6 L/ q5 V+ | - var that=this& E4 t; A$ l! t
- wx.getLocation({//获取位置(经纬度)API
- Q( `3 p+ k9 ^/ ]8 {# X7 a - type: 'wgs84',
8 @2 W4 F& Y& i - success (res) {
' j# E! H, t6 F. e) O. t( I - const latitude = res.latitude
/ O+ |; m8 d. y! N0 s/ h0 C) w3 H - const longitude = res.longitude
+ v, v+ y' N0 P7 _/ Z) ]" N - const key="432a8840589546338cae4c5a825f47db"//和风天气开发平台上控制台创建的应用得到的KEY,只有得到这个,才能获取各种数据
. V( T9 z# \; T3 ?, J - wx.request({//网络请求API
6 t0 |) l8 d; F4 v/ K: f. _8 Q# y, k - //下面使用模板字符串
/ F+ x: m( a" r1 e& I5 q - //获取天气数据的API接口地址
7 b; o4 \* j9 n7 u! [8 ~7 T - 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}`, ( b/ ]9 H1 x+ O+ R1 A3 k( t
- success (res) {
; f7 f' [# V/ `* w& T. l' {( A - const weather_data=res.data.now ( \1 T# F% Y5 @
- const weather=weather_data.text //解构赋值
$ @5 B9 Z! C$ @4 r - that.setData({5 V' E5 c) j) M; Q
- weather, U) h- s6 V, M, |, X4 N
- })
1 e; W0 i2 V& j H. G9 a$ F' A - }
* Y2 @( J% Q% E" n2 @# f - })
: J4 R9 r2 J: m. S% r! p8 P - wx.request({6 B% p$ b+ |- z( o r
- //获取地点的API接口地址
( [' W2 \* z( R) D, _! b+ T* i2 `! t - url: , 4 j' F; c( C# W' u% T! G
- success (res) {' K! P& J2 E9 V. u/ ]: X4 A1 G
- const location=res.data.location[0] 1 z8 ^+ a5 E0 t3 z
- const {adm2, name}=location //解构赋值
/ R6 R* E) s- q- V& @5 X - that.setData({
1 X R5 M0 n* H - city:adm2,
" D! k9 c1 a7 ]0 T6 L/ `7 k4 k" k - area:name
. l& ~7 r; |" h3 Z: S - })
0 \" Z7 R5 K/ h) t l - }
0 ^3 y! S+ j) I3 [0 i- ?" y - })
5 o7 Y" B* K- J3 ~ - wx.request({
9 M8 s# r. |% B) I- ~2 { - //获取空气质量的API接口地址
* v; a9 ]3 h, [4 |( W% h" p - 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}`,
% d+ f, M! j# y$ \; M - success (res) {/ Y$ \" b+ T2 j$ v. q2 K0 e
- const air=res.data.now
* n! q7 K; \* m d: O" s* Q - const {aqi, category}=air //解构赋值: \2 B: c1 {/ \6 d/ V9 {
- that.setData({
8 u' r* W+ A6 E S# }* W' [0 ` - aqi,. O5 q* ^- l: P' L0 \
- airText:category+ s( j: r+ _6 W; N% y
- })
: d5 W( `# t$ I/ ^/ Y - }/ z5 |" ]: L/ K& Y+ ?
- })
: W. W) i" A: b, L% @ - - x3 o2 j7 }9 j7 L
- wx.request({, A0 |1 A+ L: F8 t% S% p5 e
- //获取生活质量的API接口地址; R9 [2 @8 S5 |6 T7 r
- url:<a href="https://devapi.qweather.com/v7/indices/1d?type=3&location=" target="_blank">type=3&location=</a>${longitude},${latitude}&key=${key}`, 9 d% J$ K# Y" K3 _5 x$ c: g
- success (res) {
( O2 k9 {- i1 ?$ D+ W - const {text}=res.data.daily[0] //解构赋值
" C- W' K2 v0 q: T% n) W. n - that.setData({ c( O9 J& [# _! k5 {6 V# e3 J/ O/ N
- weatherAdvice:text5 C" L' N2 u. Z, L2 h$ x( _. @
- })
7 ]$ R6 }/ n$ Z6 |2 ?0 _: W( l O - }4 s1 n* ]$ o* o7 I) ?% F. ~4 M
- })" }' T$ s" q# y/ r% @
- }' M5 x' g9 ?$ b- V4 B0 V0 e) `6 y
- })
, t$ h2 k/ ?5 f - }
复制代码
, d h7 M/ U9 j! Z 接下来是小程序端的MQTT连接部分,首先需要导入一个连接服务器的库,这个库叫mqtt.min.js。该库的地址如下:mqtt.min.js文件1 @- x @# q0 n/ G% b
下载后,直接在小程序中建一个文件夹存放解压出来的文件,其中有两个文件分别为mqtt.js、mqtt.min.js,在小程序的js文件中只需引用mqtt.min.js文件即可,详细的引用代码及具体的自定义函数如下所示:(如果连接的是私有服务器需要多修改设备ID和密码,否则只需修改连接的服务器地址及端口号):
; B3 b* i- \( o, L; J" m: m1 M
, U5 u1 {2 D1 c; L$ [- var mqtt=require("../../utils/mqtt.min.js")
/ ^) _: Q- m8 o - var client=null
' b5 U' {: P; d1 D - Page({( c8 Y& s& a% d3 L/ v" V+ Q4 Z: r
- /**
! I5 i# c5 L2 u# r% h k - * 页面的初始数据' M! k1 f% q4 l/ Q
- */
( q" b: ~1 i$ y% I0 M - data: {2 r9 D8 j3 K# ?9 ?7 M8 P0 V
, z+ V5 j' o) ^- },1 W, Z5 p5 K9 H' b& x/ q
: n7 N# @6 T1 G- onLoad(){ ^- J, w1 u7 T6 D5 a0 G
- this.connectmqtt()
: |) w R, k" r! }1 ]) K- n0 ` - },
9 \0 U1 { C, i. v3 A- D7 a
" x( K* L: Q9 _+ [+ S' {- connectmqtt:function(){
" {+ t9 c+ _' d2 ?0 n5 j" ~ - var that=this;//this是指外层的对象,如果在这里进行提取,后面进入函数后,他的this就是connectmqtt函数的对象
& t2 t6 f* D/ q% [# D, n - /*杰叔叔、EMQX专用*/
. M Y5 W2 Y% ^- u7 R - const options={6 ]2 m; ]( v7 B8 p
- connectTimeout:4000,4 e+ R1 z% z: U" W9 P9 G
- clientId:"zsd", //此变量随便写# ]2 ?( z6 q$ X' f
- port:8084,
& R: Z& O g1 g& \" c r9 S1 Q) G - //杰叔叔的服务器是私有,所以需要账号和密码,而EMQX的免费服务器不需要账号密码
5 y# A$ x' t7 [$ V - username:"f6d61178afa1003ac5d41dc9ae10f0c6",/ [/ T9 W1 n. j2 b2 } ?
- password:"123123"7 M4 {8 H( l% O
- }
: ]3 [& w7 p" u( s% L7 i( I& o( J - /*腾讯云MQTT服务器专用*/
+ y- ~+ g+ f! x! k4 }0 f( x - /* const options={: [9 i' l; q/ a2 k! m! F F( c
- connectTimeout:4000,
2 I' T/ ?! j0 s$ H - clientId:"zsd", //此变量随便写
' _, o5 d, a! L8 t& |4 H - port:80,- e( ^" h0 _: t! W) j8 l' c i8 }0 j
- username:"S2ME0J3F8Xtest1;12010126;bee9c;1656302400000",
1 g" P4 ]' s3 z! J - password:"d58ce11e6725c4de9549c61d564f8bc0c7211707642ae92c63dd94b27943f85e;hmacsha256"; j7 z. q7 f1 U6 V6 I) ^+ u
- }*/
% K ~9 ]! m, |" I! W - /*百度云MQTT服务器专用*/8 L+ c j1 ~3 Z' S- l, V
- /* const options={
# p* z5 x; \( j: n - connectTimeout:4000,
5 @6 i C( y0 R2 s& ]! U2 O - clientId:"zsd", //此变量随便写
1 N1 i7 P2 l' G9 L8 f. Q - port:443,
, H: Y; k0 v) i3 Y0 S( M0 B - username:"thingidp@acwbepc|test2|0|SHA256",! x* j" b! P) u5 T5 X7 V
- password:"6fac92df9ce9cb5839cf95da0c0d8f60e3d5d333fff8b7d85bcaf5b5e71d8517"
) l1 V! i/ y- G/ `: V - }*/5 \. f( z! R# e0 g. H# L
- /*小程序连接远程服务器时,用wxs(wss)加密连接出去,其他客户端工具,
" R9 f; u6 C3 M9 D - 例如emqx在线测试工具可以使用wss协议连接服务器一;mqttbox软件也可以使用mqtt/tcp协议连接服务器一( o& R% ]! F8 Y' q
- 原因是因为服务器支持这些协议,本质上wss、mqtt都是基于tcp进行封装的5 g$ K" }, r7 d8 G) ]: A
- 实际上下面借助wxs协议连接服务器一,而其他工具也是借助服务器支持的协议进行连接,然后就可以进行数据的传输8 c4 V, e9 s( A- d' T. d& V/ t
- 如果连接的协议是ws或wss,需要在服务器地址后面加上/mqtt,如果不是前面这两个协议的地址,则直接连接服务器地址即可*/
3 C; q% l& |9 G( x7 H - //client=mqtt.connect("wxs://t.yoyolife.fun/mqtt", options)杰叔叔的服务器地址(wss协议需加上mqtt路径)
5 d4 M5 p6 K4 T' |+ S7 U/ ? - client=mqtt.connect("wxs://broker-cn.emqx.io/mqtt", options)//EMQX的服务器地址(wss协议需加上mqtt路径)
2 k" u# m: E) R8 d: c - //client=mqtt.connect("wxs://broker.emqx.io/mqtt", options)//EMQX的服务器地址(wss协议需加上mqtt路径)
. Q7 @# E* c+ Q7 o5 Q - //client=mqtt.connect("wxs://S2ME0J3F8X.ap-guangzhou.iothub.tencentdevices.com/mqtt", options)//腾讯云服务器地址(wss协议需加上mqtt路径)
( Y% n) r& U, s4 ]8 W - //client=mqtt.connect("wxs://acwbepc.iot.gz.baidubce.com/mqtt", options)//百度云服务器地址(wss协议需加上mqtt路径)
( \/ s1 Y) U+ n1 x - client.on("connect",(e)=>{4 d( X/ D' c5 g0 z1 v7 h; L
- console.log("服务器连接成功");
7 \2 T0 n, H2 b! q- K) g- V - client.subscribe("/iot/1009/zsd2", {qos:0}, function(err){//杰叔叔的服务器需要主题前缀、EMQX服务器不需要主题前缀
! D; B; U: c& ]( c - if(!err){! g9 X$ U/ O3 I( L* K# s
- console.log("订阅成功");
5 z$ U' s. a4 Q: w. o: S - }/ \8 O1 m* i# ]
- })
1 F# o2 `' @! h: F% G - /* client.subscribe("S2ME0J3F8X/test1/data", {qos:0}, function(err){//腾讯云服务器需要主题前缀
" T1 S3 C ?! z' i2 g - if(!err){$ }5 o' Y z' H. \% d3 w
- console.log("订阅成功"); s# C( t6 s/ {$ _- ]0 g
- }
8 S# v' m. ], l; g - })*/
0 \+ ^! s n/ F* L: Y' v - /* client.subscribe("$iot/test2/user/test2", {qos:0}, function(err){//百度云服务器需要主题前缀7 J. W6 m% }. z6 l/ f* _
- if(!err){# J5 H1 @8 m! J, R" b% Z
- console.log("订阅成功");
& t$ j: H; K; j - }5 r$ ~6 J9 t1 c* |0 {' @
- })*/
" C* I2 q! K% A( ?/ B5 f5 U% R# @5 U - }), M- d) K8 |- |- x" H i9 M
- //信息监听事件
( F8 p8 r, M5 E- ~ - client.on("message", function(topic, message){
, n5 f. | ~5 S. t1 W1 `/ L - let tem=JSON.parse(message)
* C, U# v+ X0 L# ^* u - console.log(tem);
% i$ G/ j- Y9 N& V! C' J) B/ w+ Q/ s2 } - that.setData({
) A6 T& k$ a9 U+ L/ o - temp:tem.a,( |) y" ? A9 G0 a& W' E4 E
- humi:tem.b
9 s2 F" o! @5 ?" Q2 e. w - })& X3 j0 m7 I7 p l d$ s
- console.log("收到"+message.toString());
6 ~% l+ ]# `( Y g; o - })
9 W- l) W) u% H: U, C - //发送reconnect类型给服务器,一旦连接中断,就会触发重新连接, v7 P, o! v0 ?$ {
- client.on("reconnect", (err)=>{
9 {* @) Z/ s* Q, a - console.log("正在重新连接",err); l$ N4 ?# z( Y E# i
- })
3 t- [, K- v; c" n( j+ t - client.on("error", (err)=>{. l8 t, E) a2 L, n6 @. v) z( {& H( \
- console.log("连接失败",err);
& o/ e9 d# c! I! v% J) k - })$ R% ?3 n9 s, L5 O
- }
L- B, F/ I% n( \
, `- B4 G) y( A7 `2 ]! M9 H& e- })
( M- f1 d$ O" [! T/ r. b7 ~7 K' e
复制代码 ( E8 `: z4 y5 l" M
至此,小程序部分的天气数据获取和MQTT连接已经基本完成,至于界面的优化,那就需要各位去学习小程序的界面优化啦。, Y& Y; @( w5 }4 a
————————————————! Y- ]+ ^/ e: R; c3 \4 F2 X
版权声明:i土豆! c* P* ?7 g0 K. {2 z
% s' u+ g* e3 J; ?* ]
! w& i0 F" V( g! y9 u1 h |