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

stm32利用mqtt与小程序通信

[复制链接]
STMCU小助手 发布时间:2022-10-16 22:09
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
3eaa322c7ba340d098d5e65c9a79ef86.png

9 K8 p7 H: \, ~' B4 ]2 O" ~1 R( c$ [8 \4 D2 j# X, b# v5 y3 b! c8 g% o
6cde9575277f4238b6a7eae9d6c5019d.png
6 N- {0 ]9 D' e4 K* G

( s5 \- L, h. @: {5 w, l
453801fdbcc24fb58c01654c6d1759d3.png

$ 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
60a454561882413c9e135d241e0b90da.png
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
2ea29e4152434a6d9ac4e7a2acae9341.png
8 m. O$ E- j. m  C$ ~3 V
* G( b4 b( J) V  k  D9 t, f4 h
959f20157eb240dc8a77746f1df9108d.png

+ 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
31c485dd56364a24b3ee2e80c96f1222.png
) 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
ef03ad84687344d0bef3551db07d271a.png

! 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
fcd7d662c2014fd3ac4489f303b2ca14.png

* 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
  1. weahterdata:function(){
    7 @; Z5 x; q9 Z' u+ R
  2.     var that=this
    8 A. [2 Z" E, |
  3.     wx.getLocation({//获取位置(经纬度)API( L+ x: Y$ P" p7 V) M2 `3 b
  4.       type: 'wgs84',
    6 ^8 M! a" p  L
  5.       success (res) {# n- \' e- M  w
  6.         const latitude = res.latitude7 ]& _1 S0 H6 U3 l6 ^) n
  7.         const longitude = res.longitude0 u" W2 S2 i$ \4 K+ N0 C) J
  8.         const key="432a8840589546338cae4c5a825f47db"//和风天气开发平台上控制台创建的应用得到的KEY,只有得到这个,才能获取各种数据7 E) D! `5 [2 Q
  9.         wx.request({//网络请求API
    ( v5 L+ N5 _' J  y" z  S9 U
  10.           //下面使用模板字符串! `/ s% b4 ~6 e  v  L' X
  11.           //获取天气数据的API接口地址+ V' `% u* M9 ?- V6 T0 }7 d3 y
  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}`, : c: c1 [! u1 m
  13.           success (res) {* {" M. p' {* I/ I4 D" Q
  14.             const weather_data=res.data.now
      O& i( C$ f4 P) H) a# {
  15.             const weather=weather_data.text //解构赋值$ ^% Y# c' B- I7 H7 }( n$ f$ f
  16.             that.setData({
    ) F, K1 t, q" W6 n& s( N/ q
  17.               weather
    ; P1 t6 E. a1 d+ c4 F# r
  18.             })3 f7 q. g/ N8 ?  G- z6 z# U
  19.           }9 d7 Z5 v/ e$ z% J& }  S5 t
  20.         })
    ) D- k9 y( d& G1 y  o
  21.         wx.request({
    ' K4 V9 s* r2 L6 j
  22.           //获取地点的API接口地址: J' D' d9 i- M7 U; t- p9 e
  23.           url: ,
    $ V. ~; k- t4 {* {0 a: P* b6 [
  24.           success (res) {9 \3 O1 s; W! T/ _' {
  25.             const location=res.data.location[0]  
    4 Q8 Q* l3 [9 h# O1 i
  26.             const {adm2, name}=location     //解构赋值
    5 N$ M" O, L+ [) O# W
  27.             that.setData({
    3 X1 ~6 E/ `  }: q8 j
  28.               city:adm2,7 C  E) C7 w+ n' V4 A( v
  29.               area:name
    8 c: e/ c( c. z7 b% k/ t$ f; M
  30.             })
    0 u/ P0 O9 _) j0 m& J/ D
  31.           }
    + U" M: q0 N& L  d- Y) s' N' ^
  32.         })
    9 R8 Q. i  }8 v& G" g! f8 T
  33.         wx.request({1 n( y8 x* {0 F1 u
  34.           //获取空气质量的API接口地址, l$ Y) h& M9 w0 U( ?
  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}`, / i# p/ s8 c- _
  36.           success (res) {( o+ |) j, t, s1 f& Q/ o
  37.             const air=res.data.now  
    ( l8 x9 u" s- o: a! Q8 m( ^
  38.             const {aqi, category}=air       //解构赋值
    ( ?+ e' F, v* w( g4 U6 c/ }( H6 ~
  39.             that.setData({
    $ C( _5 {; T# _1 o, }
  40.               aqi,
    0 X% L1 s! s- i8 l
  41.               airText:category
    9 T# b$ N/ B: p* h. Y
  42.             })' j* N3 u9 ~. e5 t* ~. u# M3 y
  43.           }
    - x' Z% x. @  f) W  c( W% b0 ~- i
  44.         }), a7 |+ C/ f+ _# f

  45.   r7 d9 m' o& e2 p2 x! n
  46.         wx.request({
    , D" ~7 g+ P1 W! W' N# k
  47.           //获取生活质量的API接口地址/ ?5 f# q- w+ R% x
  48.           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
  49.           success (res) {( w2 p# k! e( j! E/ d' k/ v
  50.             const {text}=res.data.daily[0]  //解构赋值
    / V& a0 Z+ ?. Q. b
  51.             that.setData({
    1 g5 @. g# e7 s+ n1 s* j: S  Q. {( O- w) R
  52.               weatherAdvice:text
      t& ^9 ~6 q+ F% j& G6 F2 c$ C9 r
  53.             })3 \' T- Y6 @# A; r  ]
  54.           }5 @  S2 R6 p8 Y# ]$ ?% w0 Z
  55.         })
    - [! P5 D, S4 n" x
  56.       }
    " D% b! j! ~4 f4 i' f5 a
  57.      })2 i4 r( Z) {$ J" P% E, K
  58.   }
复制代码
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
  1. var mqtt=require("../../utils/mqtt.min.js")
    " A9 [) i: D3 [3 H2 L3 J
  2. var client=null1 q" x) \* z. c
  3. Page({5 F6 a6 M' e; x. y* M- G
  4.   /**1 y" L" x1 v4 F, {1 u% @4 p
  5.    * 页面的初始数据
    5 ?1 Z$ R9 @1 T- C4 g
  6.    */* x5 o( y6 a) ~2 V$ [/ ?
  7.   data: {$ X. s% x, [$ P9 t" u
  8. " T5 q4 @3 `% t- ]# u# S) V5 `( ~
  9.   },
    ' B, s# n* K3 n4 H& _& O
  10. / X( e/ T! Z% [: G( ]- v/ W7 J
  11.   onLoad(){
    7 }% I* b' [  d4 b# _4 r6 W5 f' q
  12.     this.connectmqtt()8 A/ m2 s/ O$ v: C
  13.   },& |# I! R7 q1 {4 y9 i

  14. 1 \7 z. `. B! J
  15.   connectmqtt:function(){% Q' v4 s5 S* ^' E) j* N" N% B1 r
  16.     var that=this;//this是指外层的对象,如果在这里进行提取,后面进入函数后,他的this就是connectmqtt函数的对象+ _: r% s) [( E. F+ I$ s
  17.     /*杰叔叔、EMQX专用*/! Z$ @, Q1 V) N' o) o, h
  18.     const options={
    " g: Q6 m4 S, E8 T/ a( }4 Q
  19.       connectTimeout:4000,$ Q# c: f7 ~6 V* n
  20.       clientId:"zsd", //此变量随便写" c( `- q5 G5 i& X
  21.       port:8084,1 @; ?: S( r) C2 T9 U6 x& g; I6 n8 C. L
  22.       //杰叔叔的服务器是私有,所以需要账号和密码,而EMQX的免费服务器不需要账号密码3 x. G6 c  n. e6 t, Y
  23.       username:"f6d61178afa1003ac5d41dc9ae10f0c6",
    * e9 @% _' T- n* b* Q& `
  24.       password:"123123"' Z' X: A& v0 K2 m! ?3 n/ c
  25.     }
    0 E6 v) o: \) k6 b  B
  26.     /*腾讯云MQTT服务器专用*/- F* q  w& k9 S3 u6 k' @
  27.     /*  const options={' y2 h- l5 ]0 U* F
  28.       connectTimeout:4000,+ U$ v. \4 _  P% t% s3 c( D+ }
  29.       clientId:"zsd", //此变量随便写% P* h' V9 v0 {
  30.       port:80,
    $ M# W$ \, s+ g" B4 U7 O% U
  31.       username:"S2ME0J3F8Xtest1;12010126;bee9c;1656302400000",( t  D+ Z0 Z7 K* e7 T; x0 e5 y! v' R
  32.       password:"d58ce11e6725c4de9549c61d564f8bc0c7211707642ae92c63dd94b27943f85e;hmacsha256"# k5 p6 @* z6 q3 p2 v9 F! _
  33.     }*/
    ( l( t, _% `% J. O& G4 ?
  34.     /*百度云MQTT服务器专用*/, e% v8 S  s! g. w
  35.     /*  const options={
    2 |: w6 A; Q( J% G# U2 U) o0 z
  36.       connectTimeout:4000,/ c$ X9 r' w0 I
  37.       clientId:"zsd", //此变量随便写* C! x9 X. Y' U. ^; y* U
  38.       port:443,8 [7 w7 \6 _# ~0 n) F  x' a
  39.       username:"thingidp@acwbepc|test2|0|SHA256",
    . n2 r8 t" n# a) O$ l1 S  U; E
  40.       password:"6fac92df9ce9cb5839cf95da0c0d8f60e3d5d333fff8b7d85bcaf5b5e71d8517"
    1 i9 B8 H9 P7 t" @& q5 L
  41.     }*/
    ' T+ ~/ u! u$ I" e
  42.           /*小程序连接远程服务器时,用wxs(wss)加密连接出去,其他客户端工具,$ s7 Z2 }4 P% L  I4 e
  43.                   例如emqx在线测试工具可以使用wss协议连接服务器一;mqttbox软件也可以使用mqtt/tcp协议连接服务器一, r" f9 a% y- M8 n9 W1 v/ ]+ W  k+ h
  44.                   原因是因为服务器支持这些协议,本质上wss、mqtt都是基于tcp进行封装的
    - O0 `. C6 G3 M* _, e
  45.                   实际上下面借助wxs协议连接服务器一,而其他工具也是借助服务器支持的协议进行连接,然后就可以进行数据的传输& [3 q; n2 V4 X) a0 S8 ]
  46.             如果连接的协议是ws或wss,需要在服务器地址后面加上/mqtt,如果不是前面这两个协议的地址,则直接连接服务器地址即可*/
    + F0 u/ D4 O) M
  47.     //client=mqtt.connect("wxs://t.yoyolife.fun/mqtt", options)杰叔叔的服务器地址(wss协议需加上mqtt路径)& N- Z  q) k) e8 E+ n( f
  48.     client=mqtt.connect("wxs://broker-cn.emqx.io/mqtt", options)//EMQX的服务器地址(wss协议需加上mqtt路径)
    " e) U0 }6 o2 C4 p, g' b# }
  49.     //client=mqtt.connect("wxs://broker.emqx.io/mqtt", options)//EMQX的服务器地址(wss协议需加上mqtt路径)  r8 V; J/ A/ b' o" y
  50.     //client=mqtt.connect("wxs://S2ME0J3F8X.ap-guangzhou.iothub.tencentdevices.com/mqtt", options)//腾讯云服务器地址(wss协议需加上mqtt路径)/ z2 i, r( n7 ~" h
  51.     //client=mqtt.connect("wxs://acwbepc.iot.gz.baidubce.com/mqtt", options)//百度云服务器地址(wss协议需加上mqtt路径)
    4 g% O. r5 E4 z
  52.     client.on("connect",(e)=>{; R2 d6 O$ ?& F7 t2 J2 ^% p* G
  53.       console.log("服务器连接成功");
    * e) P3 q' S- \5 T8 a
  54.       client.subscribe("/iot/1009/zsd2", {qos:0}, function(err){//杰叔叔的服务器需要主题前缀、EMQX服务器不需要主题前缀' {, Y" d& [; x" E& X
  55.         if(!err){
    2 f) d# u0 s4 _: Q- n
  56.           console.log("订阅成功");# _. L6 n" }* M& d
  57.         }
    7 V, s/ C( p% K3 H, p
  58.       })
    / u3 r6 U) d2 K% k  O, ^1 B* \
  59.     /*  client.subscribe("S2ME0J3F8X/test1/data", {qos:0}, function(err){//腾讯云服务器需要主题前缀( I2 b: T& P- L' ~  K
  60.         if(!err){
    3 }# f  s3 p2 C' l. T7 _0 l
  61.           console.log("订阅成功");
    ' ~# m; v$ _* ]! Z$ m' N* C, L
  62.         }
    & D0 E/ z8 C* s) q
  63.       })*/0 d  l( o( I" z' v: x0 M! D) Z
  64.     /*  client.subscribe("$iot/test2/user/test2", {qos:0}, function(err){//百度云服务器需要主题前缀: W5 n+ {* r1 b" }
  65.         if(!err){
    , |3 w  _1 q. u- @) i3 u8 J. n" q: ^
  66.           console.log("订阅成功");
    ' t  T  C! x, d+ K/ O% m: ~
  67.         }+ J. Z. J8 R; h; M$ g; B2 v2 r
  68.       })*/
    ) U, i' b- L+ J- z- {
  69.     })) o% M  F5 n; C9 M. k
  70.     //信息监听事件. e- J; h$ a/ H3 E; `, j% ~3 ~6 g! X6 D
  71.     client.on("message", function(topic, message){
    . i& U9 o) I( l- h/ V) p- ~  I
  72.       let tem=JSON.parse(message)
    ! n8 c/ z  O+ D3 H0 f! T
  73.       console.log(tem);" P- L( B; m6 R. w1 W) _
  74.       that.setData({% @% s! [; g7 \. g" ]7 q% u
  75.         temp:tem.a,# k6 s9 q2 A3 I( j' ~6 M3 e
  76.         humi:tem.b
    * m5 Q* C6 G5 p; d% F/ l( Q
  77.       })! e# B3 `( L$ x' w$ a; ^
  78.       console.log("收到"+message.toString());, X3 A- p# k2 I% k6 A) `1 f
  79.     })
    % g. U9 O% s" B
  80.     //发送reconnect类型给服务器,一旦连接中断,就会触发重新连接8 t# s9 w+ m' h+ I: H+ Y/ J2 e
  81.     client.on("reconnect", (err)=>{$ G: h- N# B8 m- q; d
  82.       console.log("正在重新连接",err);" j% P- s( |% I2 a; o
  83.     })
    : V1 u# G! d6 [0 w5 A
  84.     client.on("error", (err)=>{* e* k( G2 ^6 V' x
  85.       console.log("连接失败",err);* k" }6 F# u7 S
  86.     })% K! w7 \" g. V' `* l. |$ |
  87.   }% O% e; B* L5 I

  88. & e. J& L% f# @. K. j* k
  89. })& 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
赞 收藏 评论0 发布时间:2022-10-16 22:09

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版