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

stm32利用mqtt与小程序通信

[复制链接]
STMCU小助手 发布时间:2022-10-16 22:09
stm32连接服务器端
' L. y' s, t) J本章所用到的器件如下:5 C* }) u( f# V
STM32F103ZET6最小系统板
2 p: c4 B; u6 n, S7 Q, Z: vESP8266-01S模块; s; W. s6 C* d- I' I
USB转microUSB数据线
9 Z% c7 z0 w0 {: u- G四根杜邦线* I" D0 \/ Z6 y1 f
连接如下:
0 M$ M8 _$ @' ~' Y32板3.3v----------->ESP8266的3.3v
: W" \8 E8 z7 Q3 A' w% F8 ^32板GND---------->ESP8266的GND
% K* E1 v. X) D" T2 f7 C, A32板的PC10-------->ESP8266的RX
5 K- o4 g2 l/ K* J  u( f2 l32板的PC11-------->ESP8266的TX6 V) f# V& h% g" E# w1 U
# \( L. P6 _! A. a- q
  在这里说明一下,由于本项目是用在其他项目上的,所以在编写此项目时,是基于另一个项目还未被使用到的串口资源进行设计的,所以我这里用了串口4。各位需根据自己硬件已有的串口资源,自行手动修改串口4初始化的函数。$ o$ c" e  F7 l* m& m9 H! a8 O
0 E" @. b! Z8 l* ~( N4 w! i) B2 A7 e
  ​本项目程序是参考onenet平台上的源码进行二次开发的,onenet平台上源码的位置如下:进入onenet官网后,登录账号,在上方有一个社区->论坛,里面就有源码,点进去后就有一个链接是百度网盘的,这里我用的是OneNET标准板中的裸机基础教程->EDP例程。
$ \9 s. g- N" C( _( G  Y; ]2 ~
: P$ n3 _- n0 ^" I$ c
3eaa322c7ba340d098d5e65c9a79ef86.png
/ J: c( }4 m+ j9 x
: V! O, \/ ?- r, N/ j; }  t4 |2 B
6cde9575277f4238b6a7eae9d6c5019d.png
+ |* I6 v9 d* F( C! O: I! \

$ d+ `; c8 n, }
453801fdbcc24fb58c01654c6d1759d3.png
8 Q  b& I  L9 I* p
5 D5 j2 E3 Q6 V$ F4 g* ~7 g
​  既然用到了MQTT协议,少不了要用到cJSON格式的一个文件,将cJSON.c和cJSON.h文件导入到stm32程序所在的文件夹下,接着在程序中onenet.c文件里面包含头文件cJSON.h,方便我们下面对接收到的cJSON格式的数据进行解析。
5 c* N: |# J$ p* x# E  ~1 T( c$ _% I5 x2 y' U! \
60a454561882413c9e135d241e0b90da.png

' f# D" V1 w1 l( U7 G& o% V  m$ U; V8 R+ W! P, G, Z+ D  F
​  接下来,我们需要修改的是esp8266.c文件中的ESP8266_WIFI_INFO及ESP8266_ONENET_INFO,他们分别表示的是ESP8266需要连接的WIFI及服务器地址(修改成自己的WIFI名称、密码和服务器地址、端口号),本项目中给出了五个MQTT服务器地址,其中EMQX服务器是公有服务器,可以直接连接,至于其他三个服务器是自己在其他平台创建的私有服务器,需要用到onenet.c文件中的设备ID和密码。EMQX服务器连接的时候不需要用到设备ID和密码,所以设备ID和密码可以随便写。 1 K! d( W4 J" f1 ^4 a/ Z8 Z
4 j" J7 C# y2 a& f5 E: [9 y3 f
2ea29e4152434a6d9ac4e7a2acae9341.png
1 t. C2 S( D( P  `4 W. I
& j# n9 P, y1 f2 ~3 e5 q+ s- @2 {
959f20157eb240dc8a77746f1df9108d.png

7 d9 f. u: Z7 ~: m* r# N: \! m: {& h
​  最后,需要设置一下主题的发布和订阅,对于公有服务器来说,是没有主题前缀的,而对于私有服务器来说,他有平台自带的主题前缀。 此项目中连接的是EMQX的服务器,是不需要主题前缀的,所以这里我随便写了一个发布主题和订阅主题(同时这两个主题也可用于我创建的私有服务器的设备相对应的主题)。& k8 d: J; A( T3 [& y

" _  D4 C$ R4 M: s" Q
31c485dd56364a24b3ee2e80c96f1222.png

# V' Y( k* b) Z& y% G1 T
6 H) f" x' m9 c3 v% g$ ~​  至此,stm32部分的程序已经搞好了,接下来进行小程序部分的制作。
* M+ c2 e6 i! P* P3 M  `
( g% _4 ~; d( i0 n2 W' p% s小程序连接服务器
: b: M( m- ?/ i. T​  先上小程序的效果展示图9 g4 G7 E1 x4 O7 z. a* z; E4 D4 ]( N
ef03ad84687344d0bef3551db07d271a.png

+ _2 q$ s) _  f$ y' P. S9 h4 @  q
4 A/ [& P9 l% }+ f! i
​  此项目的小程序我没有用过任何框架,都是使用微信原生框架进行开发,其中首页涉及到天气数据的获取,这里请求的天气数据API接口采用的是和风天气开发平台上的Web API接口,其链接如下:和风天气开发平台
4 @. a% u# H1 O​​  要请求该平台上面的API接口,需要在该平台上登录账号,然后进入控制台,在上面创建一个应用(目的是获取到一个KEY),如下所示:; }) L( T0 {+ L8 ^' Q7 M+ S8 b+ {
$ ^; S6 g& G  x  c( ^- T
fcd7d662c2014fd3ac4489f303b2ca14.png

2 b$ n9 j# D: L8 e! u  b; f2 [: U) C; N- B
​  接着到该平台的开发文档->天气数据Web API开发文档中去找对应的请求地址,上面清楚的写了该地址的格式及请求的参数等信息,下面是小程序端的获取天气数据的自定义函数:
. |% x5 T1 n+ X, s3 }6 D* U% ~+ N! b% v+ v
  1. weahterdata:function(){  k6 g/ O! j) t
  2.     var that=this
    - k# ~0 `4 B% `3 Q* ]
  3.     wx.getLocation({//获取位置(经纬度)API
    6 @) {3 d5 W7 F2 W8 c) I
  4.       type: 'wgs84',! [- c, A  d7 ]; o" r
  5.       success (res) {
    5 {. Z/ w0 ^9 _3 Z8 h
  6.         const latitude = res.latitude
    ! H7 l' `& J9 r: Q% A
  7.         const longitude = res.longitude
      D; k0 ]4 e+ t$ A% L# u
  8.         const key="432a8840589546338cae4c5a825f47db"//和风天气开发平台上控制台创建的应用得到的KEY,只有得到这个,才能获取各种数据9 D5 I" f6 R+ Y
  9.         wx.request({//网络请求API' |" @9 x- A: Q8 o# E& y4 ?* k, ~6 Z6 s
  10.           //下面使用模板字符串
    ; r6 |  T( |5 z
  11.           //获取天气数据的API接口地址
    , [# h, Q/ D" s
  12.           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}`,
    ; I1 Q; \$ q, M! ?5 D! E
  13.           success (res) {9 l( H# u; L8 J9 k8 I2 r
  14.             const weather_data=res.data.now 1 E' V' Q1 B% o% }2 d
  15.             const weather=weather_data.text //解构赋值* E* p8 [. G1 O8 R" @$ w
  16.             that.setData({  q0 b& m* R& J7 U& S
  17.               weather' o" M! X* q4 W& z
  18.             })
    + R* D) Z* @; e5 k! u" G
  19.           }
    / K# {& M) F& ~3 U
  20.         }): E4 I/ `# z. l2 \
  21.         wx.request({
    # H4 ]* H, U4 w9 ~0 v+ F
  22.           //获取地点的API接口地址
    + A8 N5 f: r( H4 Q9 n; W
  23.           url: , 8 t& E6 m, ~! M3 H9 r- w: y& e7 B
  24.           success (res) {
    & {% _0 R* f  d9 n
  25.             const location=res.data.location[0]  
    / B! m" v: j, j
  26.             const {adm2, name}=location     //解构赋值% @1 b3 |! y, [7 h6 k% I
  27.             that.setData({, ?: {( j" g* I4 d6 C/ x
  28.               city:adm2,
    / |0 D0 D* q4 M
  29.               area:name
    0 l; j7 j; _! l" k* A( M1 z
  30.             })
    - U8 s- P# Y* i
  31.           }! M( Z& ^& W; u$ }% T
  32.         })
    6 w& T! b4 L/ A' ]+ ^: h, m5 t
  33.         wx.request({! T3 i$ K0 y* u
  34.           //获取空气质量的API接口地址; ^1 I5 t! U& z6 V6 Y
  35.           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}`,
    ; ^6 x3 K$ [" y7 Q
  36.           success (res) {
    3 X! h* `) g$ S7 H+ e  ?
  37.             const air=res.data.now    O/ B5 ^, [; e2 Z2 o0 |
  38.             const {aqi, category}=air       //解构赋值- ?6 F% {: J0 Y
  39.             that.setData({4 U/ `' J! v" }3 W4 Z
  40.               aqi,
    % |7 S+ X" _0 F, x' g/ v
  41.               airText:category
    * d( @" z0 w( E/ z+ K) W
  42.             })* x, ]5 S! r+ e( Y
  43.           }" V% y0 p( `) B: X, C; h) k" ]' x0 d
  44.         })
    5 A( g# b3 O2 W6 W# H  F  o

  45. 5 b. z7 Z6 n  }$ f, T
  46.         wx.request({* h6 S. s. q  R3 l7 W
  47.           //获取生活质量的API接口地址
    , B2 G, t* ]2 E6 q8 R' L0 R
  48.           url:<a href="https://devapi.qweather.com/v7/indices/1d?type=3&location=" target="_blank">type=3&location=</a>${longitude},${latitude}&key=${key}`, # W* u5 r$ U) q4 A/ x/ g
  49.           success (res) {
    ; E- ]& U8 e3 ^8 U% |* S; Z; R0 V
  50.             const {text}=res.data.daily[0]  //解构赋值: P9 m3 h- x3 w8 y9 e: Z) S
  51.             that.setData({
    - k0 n2 |6 Q6 Y& p* d
  52.               weatherAdvice:text
    - h. Q! R0 c9 t+ K  h5 ]; Z! n
  53.             })
    $ ^+ d4 a) U5 R' M  m
  54.           }; |" }  n$ K3 w* G: {9 C( A
  55.         })6 g. w; q% B; A
  56.       }
    ( ^' K# x7 y% Y$ U& m/ R5 V6 ~$ ~
  57.      })
    0 ^; m2 N) b% F6 W1 v
  58.   }
复制代码
* D! a2 a$ \& T6 s# U
​  接下来是小程序端的MQTT连接部分,首先需要导入一个连接服务器的库,这个库叫mqtt.min.js。该库的地址如下:mqtt.min.js文件
, r, o* K3 g) U+ z8 c" X5 H( Y​  下载后,直接在小程序中建一个文件夹存放解压出来的文件,其中有两个文件分别为mqtt.js、mqtt.min.js,在小程序的js文件中只需引用mqtt.min.js文件即可,详细的引用代码及具体的自定义函数如下所示:(如果连接的是私有服务器需要多修改设备ID和密码,否则只需修改连接的服务器地址及端口号):
9 y: \6 z& h9 J3 y- B' P9 ~6 Y) Q9 h; l1 E$ m) E
  1. var mqtt=require("../../utils/mqtt.min.js")
    * t* B, E) x5 N8 ^$ g) @
  2. var client=null. K, N  C- H, Z2 w
  3. Page({' |+ _0 I2 r* N( \
  4.   /**: b, N" j0 K0 z3 \) L6 X
  5.    * 页面的初始数据
    ; i0 c7 `$ k0 i3 \6 j, m. Y4 M
  6.    */$ e, N: N8 k4 T6 z* I+ d
  7.   data: {, i4 w8 T  l/ v5 k, W

  8. ! p4 v/ z8 I+ z4 m6 |: \9 k
  9.   },% @3 V. n( ~% u: N5 W! C

  10. : W8 E8 `2 t7 _5 W2 s+ T- ]
  11.   onLoad(){* p& s7 r1 T+ W
  12.     this.connectmqtt()
    5 K+ y. k3 |# W
  13.   },. Y- a. U5 e$ k; |" C! Y$ t/ u7 T# X
  14. $ Y( l- T) y( E. l! `! O" W
  15.   connectmqtt:function(){+ S/ F/ k' z; B( s, f2 `) P7 x
  16.     var that=this;//this是指外层的对象,如果在这里进行提取,后面进入函数后,他的this就是connectmqtt函数的对象
    % h8 P* H% D+ h
  17.     /*杰叔叔、EMQX专用*/% ^3 H; p& p% G( ~, ~" h
  18.     const options={
    # z2 f& X( P1 V; p& Z
  19.       connectTimeout:4000,
    ) U7 P0 n5 P8 x1 N7 g
  20.       clientId:"zsd", //此变量随便写
    $ V2 Y" N& z, M* W
  21.       port:8084,
      m) r; `. _" u3 W% h4 k
  22.       //杰叔叔的服务器是私有,所以需要账号和密码,而EMQX的免费服务器不需要账号密码
    : p8 X6 i1 }! L! |
  23.       username:"f6d61178afa1003ac5d41dc9ae10f0c6",
    + _7 z1 E" U4 y. B1 F5 S
  24.       password:"123123"
    0 {. T  c# x" _
  25.     }' ]- z, z/ y1 ~. ~. D# y6 V
  26.     /*腾讯云MQTT服务器专用*/
    ( t- t+ d$ j* e7 h3 A" g
  27.     /*  const options={0 q. P# {" T6 z1 s0 s2 v$ I' G
  28.       connectTimeout:4000,8 F6 o5 M3 B3 q' V2 }8 y
  29.       clientId:"zsd", //此变量随便写
    5 _2 v+ w' r0 I  g
  30.       port:80,) ~1 n, R3 |. |, K/ O
  31.       username:"S2ME0J3F8Xtest1;12010126;bee9c;1656302400000",
      n* }) @( U0 `" j# `
  32.       password:"d58ce11e6725c4de9549c61d564f8bc0c7211707642ae92c63dd94b27943f85e;hmacsha256"$ I  O$ U( Q' b* u$ Z3 @' r
  33.     }*/5 P% f# g/ u+ R1 p
  34.     /*百度云MQTT服务器专用*/. b- u8 c; a0 P# ?
  35.     /*  const options={
    8 H* t, t4 ^/ M# a7 M2 k
  36.       connectTimeout:4000,4 ^  z4 O6 n: @2 V# o7 f8 W7 z; {
  37.       clientId:"zsd", //此变量随便写
    - s" @" V2 p1 z, g; A/ t. u- r3 [
  38.       port:443,: P) W8 E9 _& N/ J, g. j; i) c; E# z
  39.       username:"thingidp@acwbepc|test2|0|SHA256",
    9 c6 l! Z1 v. k) D. _
  40.       password:"6fac92df9ce9cb5839cf95da0c0d8f60e3d5d333fff8b7d85bcaf5b5e71d8517"
      A. V( k2 c) M/ L- h+ H: s
  41.     }*/1 l7 B4 F& a4 K
  42.           /*小程序连接远程服务器时,用wxs(wss)加密连接出去,其他客户端工具,
      X( D  V4 J: b3 v9 e5 R
  43.                   例如emqx在线测试工具可以使用wss协议连接服务器一;mqttbox软件也可以使用mqtt/tcp协议连接服务器一1 T0 o5 ?$ s8 |( K- v/ \( a
  44.                   原因是因为服务器支持这些协议,本质上wss、mqtt都是基于tcp进行封装的
    ; v. R/ d& Y4 K; r- _8 Y. \1 {
  45.                   实际上下面借助wxs协议连接服务器一,而其他工具也是借助服务器支持的协议进行连接,然后就可以进行数据的传输
    ! z" h' C, V) T5 c/ W
  46.             如果连接的协议是ws或wss,需要在服务器地址后面加上/mqtt,如果不是前面这两个协议的地址,则直接连接服务器地址即可*/
    - |: r( V8 l$ W. ]4 X6 e
  47.     //client=mqtt.connect("wxs://t.yoyolife.fun/mqtt", options)杰叔叔的服务器地址(wss协议需加上mqtt路径)
    8 {" O. u+ H" C, _' Q- I2 T
  48.     client=mqtt.connect("wxs://broker-cn.emqx.io/mqtt", options)//EMQX的服务器地址(wss协议需加上mqtt路径)
    6 D6 d, Z; \1 L& E
  49.     //client=mqtt.connect("wxs://broker.emqx.io/mqtt", options)//EMQX的服务器地址(wss协议需加上mqtt路径)- I8 N4 l9 x& r4 F3 q/ N" K- W
  50.     //client=mqtt.connect("wxs://S2ME0J3F8X.ap-guangzhou.iothub.tencentdevices.com/mqtt", options)//腾讯云服务器地址(wss协议需加上mqtt路径)/ ]$ S3 i: h: {. q* n
  51.     //client=mqtt.connect("wxs://acwbepc.iot.gz.baidubce.com/mqtt", options)//百度云服务器地址(wss协议需加上mqtt路径)0 k9 j" f9 t; V# u5 P1 o
  52.     client.on("connect",(e)=>{$ X% l* s% `$ }4 p3 u+ c% F* F
  53.       console.log("服务器连接成功");/ {6 `( t. m: }0 [
  54.       client.subscribe("/iot/1009/zsd2", {qos:0}, function(err){//杰叔叔的服务器需要主题前缀、EMQX服务器不需要主题前缀
    - b: |, [2 f2 T" K0 m6 _
  55.         if(!err){8 O# i* p0 y' g. u
  56.           console.log("订阅成功");
    1 G+ ]  V" b" i7 o3 F) v' i# I
  57.         }
    6 w: b& g7 e/ D' r& U9 |& f
  58.       })" N9 l. |/ ?' m- b- \
  59.     /*  client.subscribe("S2ME0J3F8X/test1/data", {qos:0}, function(err){//腾讯云服务器需要主题前缀3 x: a9 N, ~2 ^" V! x! e
  60.         if(!err){
    # J7 t' E7 d0 Y3 R3 ^
  61.           console.log("订阅成功");
    2 N+ j; K9 _3 J( g' z4 U, M) B
  62.         }: k2 C+ ?9 P7 [/ X# \. L
  63.       })*/
    2 ~0 b# V  q% B: J, F
  64.     /*  client.subscribe("$iot/test2/user/test2", {qos:0}, function(err){//百度云服务器需要主题前缀
    + O2 F# O& c, x' F  W4 a' V- N
  65.         if(!err){
    4 \* O* O8 o# y1 j9 G. C0 w1 P
  66.           console.log("订阅成功");) o& K) V' J5 u
  67.         }% S4 ?! ]& A: i) @8 t6 W& H: h
  68.       })*// N% u5 c% N7 G0 ]
  69.     })
    ; V" ^. w7 i7 K) R0 Y' c4 q
  70.     //信息监听事件
    2 P! K" M( H) u
  71.     client.on("message", function(topic, message){7 |( c3 {1 t# k, |. Y1 \8 T
  72.       let tem=JSON.parse(message)
    6 O2 Y) v9 E* b6 r
  73.       console.log(tem);2 L( {/ j+ N# X" j1 Y
  74.       that.setData({- l9 v* x7 r1 z8 {' H9 A- E1 G
  75.         temp:tem.a,
    9 x# e3 l: q9 w* A5 ~2 p! ^4 y. x
  76.         humi:tem.b
    . \9 b! G. T+ h
  77.       })5 r8 L, y2 K# s
  78.       console.log("收到"+message.toString());
    3 x3 k+ {: W% {+ M, i2 y1 z
  79.     })+ K; J# M, l, ~5 w/ {5 B! `
  80.     //发送reconnect类型给服务器,一旦连接中断,就会触发重新连接+ |2 M+ h: Z/ q4 O  t
  81.     client.on("reconnect", (err)=>{
    0 S6 y1 g6 X. F$ E
  82.       console.log("正在重新连接",err);
    1 ]% V7 c9 G+ D  |5 T; x- Z
  83.     })7 `" |( j: y) Z% w! h8 T
  84.     client.on("error", (err)=>{
    5 L% P! O$ ], L7 U, Z
  85.       console.log("连接失败",err);8 O; w" b: B# Y5 h
  86.     })
    ) f0 [7 t/ B( z  w4 J' `
  87.   }
    : l0 |) e% l4 a# x3 s6 b

  88. : Y$ P0 ~9 Z. ~1 m  h' {4 C; y. R
  89. })
    ( C' V" `  I) W' x: [5 b; K" ]
复制代码

, g& o+ E5 K) A​  至此,小程序部分的天气数据获取和MQTT连接已经基本完成,至于界面的优化,那就需要各位去学习小程序的界面优化啦。5 ~/ Z; o) [0 }" v+ q
————————————————
  Z5 V; k; s1 U, r, P版权声明:i土豆
  D/ Q  c$ h) d, \7 c% b( m3 G; z+ ~: m# j+ a
, j* d! G2 e2 X7 b2 W) C
收藏 评论0 发布时间:2022-10-16 22:09

举报

0个回答

所属标签

相似分享

官网相关资源

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