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

stm32利用mqtt与小程序通信

[复制链接]
STMCU小助手 发布时间:2022-10-16 22:09
stm32连接服务器端* ^* q% K& a  |* o( }* c
本章所用到的器件如下:
/ m) B. w: X7 g# \+ t: m4 e  SSTM32F103ZET6最小系统板
9 S# }1 G- H* E/ d: ]ESP8266-01S模块
( ?2 z7 S) Z6 D  F& CUSB转microUSB数据线" F( q  r' ^4 n
四根杜邦线
% T& \" _0 g7 \% p  E7 k  d$ L8 ?连接如下:
- h3 ~* Z0 b8 p' n* t32板3.3v----------->ESP8266的3.3v6 _0 d  @( I5 ^! s& D( }1 J( m
32板GND---------->ESP8266的GND
: w+ n  H' I- Z, K% v$ _32板的PC10-------->ESP8266的RX) {' y$ ~  b! {1 F
32板的PC11-------->ESP8266的TX* |% f" B8 M5 g$ e- N, P5 x
% w! u$ M" w  b$ ?3 N
  在这里说明一下,由于本项目是用在其他项目上的,所以在编写此项目时,是基于另一个项目还未被使用到的串口资源进行设计的,所以我这里用了串口4。各位需根据自己硬件已有的串口资源,自行手动修改串口4初始化的函数。* O3 }  V( N: K$ }3 L+ n- F# T: g* {

" D) q# @# W/ X5 u0 B  ​本项目程序是参考onenet平台上的源码进行二次开发的,onenet平台上源码的位置如下:进入onenet官网后,登录账号,在上方有一个社区->论坛,里面就有源码,点进去后就有一个链接是百度网盘的,这里我用的是OneNET标准板中的裸机基础教程->EDP例程。# E' c) C9 Q- P

( ?( i+ V. x* ~2 ?
3eaa322c7ba340d098d5e65c9a79ef86.png
8 d+ `/ e* I; j3 L* ~. W& Z8 z
' _: |' a( S" N7 D3 X! a
6cde9575277f4238b6a7eae9d6c5019d.png

! l2 [2 l$ D* I; i2 s/ O3 [1 S% ~, Y0 D- Y& m
453801fdbcc24fb58c01654c6d1759d3.png
/ H9 T2 L" x" z5 H: x$ r5 I" i

3 X* h1 R7 _+ ^+ M" A" t) S​  既然用到了MQTT协议,少不了要用到cJSON格式的一个文件,将cJSON.c和cJSON.h文件导入到stm32程序所在的文件夹下,接着在程序中onenet.c文件里面包含头文件cJSON.h,方便我们下面对接收到的cJSON格式的数据进行解析。
- y4 {0 z; n' x  N& s/ o5 a  m% o9 ^- J
60a454561882413c9e135d241e0b90da.png
9 f) q0 f( ], v; u! f& z+ c
8 ^4 N& ]! b( ?' Q* {, ?6 ^' d
​  接下来,我们需要修改的是esp8266.c文件中的ESP8266_WIFI_INFO及ESP8266_ONENET_INFO,他们分别表示的是ESP8266需要连接的WIFI及服务器地址(修改成自己的WIFI名称、密码和服务器地址、端口号),本项目中给出了五个MQTT服务器地址,其中EMQX服务器是公有服务器,可以直接连接,至于其他三个服务器是自己在其他平台创建的私有服务器,需要用到onenet.c文件中的设备ID和密码。EMQX服务器连接的时候不需要用到设备ID和密码,所以设备ID和密码可以随便写。 / _- S. a  u& O) M
& a$ A% [5 D1 o+ m
2ea29e4152434a6d9ac4e7a2acae9341.png

; K* I- R% v& |! C$ {& ~7 s! l4 u* t+ H5 {+ q7 G
959f20157eb240dc8a77746f1df9108d.png

- _- l8 a* a+ H2 M9 f, n
5 q( n. C8 V% B) k4 o​  最后,需要设置一下主题的发布和订阅,对于公有服务器来说,是没有主题前缀的,而对于私有服务器来说,他有平台自带的主题前缀。 此项目中连接的是EMQX的服务器,是不需要主题前缀的,所以这里我随便写了一个发布主题和订阅主题(同时这两个主题也可用于我创建的私有服务器的设备相对应的主题)。
; P3 W$ ]) f7 t1 t2 f! r0 u  P( S5 `' I
31c485dd56364a24b3ee2e80c96f1222.png
$ X  W6 @: @  P9 H, ^- n. e* U

6 F& b, z; n- W( e2 p2 ^0 W- q- G1 o. U​  至此,stm32部分的程序已经搞好了,接下来进行小程序部分的制作。$ v' w5 O9 n/ `4 A3 B! a0 a* f3 j

; V% b; J# ]2 N) \4 t$ E小程序连接服务器
3 a4 ]) G& M2 O& Q% M​  先上小程序的效果展示图
1 P+ a$ |9 q$ ]  Z# {2 W" R2 f; {1 C; K: y
ef03ad84687344d0bef3551db07d271a.png

& @% l$ |' b6 [8 t+ u8 O6 a# R5 I! X- S# |. F1 H

* A" j) p: L) Q$ j6 W​  此项目的小程序我没有用过任何框架,都是使用微信原生框架进行开发,其中首页涉及到天气数据的获取,这里请求的天气数据API接口采用的是和风天气开发平台上的Web API接口,其链接如下:和风天气开发平台# o5 U+ R3 @4 B. \. x
​​  要请求该平台上面的API接口,需要在该平台上登录账号,然后进入控制台,在上面创建一个应用(目的是获取到一个KEY),如下所示:+ _, Z/ @6 w1 @
0 j% D" v. R  v) A1 Q- }4 g- M& s
fcd7d662c2014fd3ac4489f303b2ca14.png
2 ^! S7 U: u, k8 }* u

4 S1 E2 m0 A5 z​  接着到该平台的开发文档->天气数据Web API开发文档中去找对应的请求地址,上面清楚的写了该地址的格式及请求的参数等信息,下面是小程序端的获取天气数据的自定义函数:2 y/ G* T" J! p
# N6 v6 C- P' e
  1. weahterdata:function(){
    & n9 i( C: q# U$ `2 F
  2.     var that=this
    1 n4 K9 z0 \  R* C- Z
  3.     wx.getLocation({//获取位置(经纬度)API7 P+ q& |- A7 o  O# s3 b" s
  4.       type: 'wgs84',, d$ e- W& Y( T, D, @
  5.       success (res) {' l. e$ @. l# M9 s0 u- D
  6.         const latitude = res.latitude
    ; k0 ]$ H  \5 V+ Q( L! ^2 v
  7.         const longitude = res.longitude1 z- a3 C1 n7 }8 `: I
  8.         const key="432a8840589546338cae4c5a825f47db"//和风天气开发平台上控制台创建的应用得到的KEY,只有得到这个,才能获取各种数据; J3 f! v6 I: ^6 s# d$ ]( m
  9.         wx.request({//网络请求API$ g5 n! b, [& ]1 L% G
  10.           //下面使用模板字符串8 I9 A0 s5 s, l! Z
  11.           //获取天气数据的API接口地址
    2 ~- F. i( u; [' [7 {: T
  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}`, : V1 x# w* P% v9 G9 w4 c
  13.           success (res) {
    7 s4 M8 C, f  z, v2 P* ]
  14.             const weather_data=res.data.now 0 Q" |; `5 D" c8 ^/ K
  15.             const weather=weather_data.text //解构赋值0 d8 y$ P" P' [( R. W
  16.             that.setData({
    " b$ @* g/ a/ h9 {1 q
  17.               weather
    ( R: V1 J' k( Y- G: S0 S: @0 o
  18.             })* [2 N( N/ h& N$ o1 n: X# A; R) M$ z
  19.           }
    + |0 X2 |" h. d7 Z
  20.         })1 U& E. F6 V5 P" ]2 U% O" n& @7 h  L( N
  21.         wx.request({7 i# a' `: {5 G$ R$ k; q% E/ `
  22.           //获取地点的API接口地址
      {6 A: E) Q7 F3 @( b
  23.           url: , 2 Z' P- }+ ^1 G) i$ M- b
  24.           success (res) {
    ' P$ q+ ?% _5 @& T5 l4 W2 @6 l6 f' [$ S
  25.             const location=res.data.location[0]  
    % Z7 k6 A. [9 j4 Q, Z- P
  26.             const {adm2, name}=location     //解构赋值2 H8 v  V- I0 `: ]# ~- }6 A" f) u
  27.             that.setData({$ @. g6 u- V$ E3 l0 X, V# Y+ f8 U
  28.               city:adm2," d6 W+ C9 y3 G; q/ o; Y' `& B" @
  29.               area:name4 r. g: ]- j$ p" e$ G) P% T
  30.             })
    & @  W1 b: U) X, W
  31.           }( _* j2 w3 c, M: L$ g* m9 u
  32.         })
    6 {$ v3 W' T4 S3 [8 X2 t8 {8 Y
  33.         wx.request({
    , K& ]  H1 B/ l
  34.           //获取空气质量的API接口地址
    # e/ @( X# O4 o* J& V
  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}`,
    9 N9 ~8 D& h# E& F& Z  W9 L
  36.           success (res) {5 A7 i8 u; B" D9 ^0 h
  37.             const air=res.data.now  
    ' e+ f8 U+ z1 N7 z
  38.             const {aqi, category}=air       //解构赋值
    1 p' a! I% j$ M$ m5 W# H
  39.             that.setData({8 Q: `# F4 b' a
  40.               aqi,
    + N6 J# c3 |# S" K6 X( Z3 Z4 \  b
  41.               airText:category
    4 a4 x# K  o+ o3 N- M
  42.             })
    5 @& F$ l9 @. J+ T0 ~: m
  43.           }8 _/ ~& w9 O- V. Q3 B
  44.         })
    ( h+ D3 @2 U# |
  45. ( x) c& {, _* N
  46.         wx.request({* @" G* t6 y' H
  47.           //获取生活质量的API接口地址" W0 D% m7 O8 ^5 x9 z
  48.           url:<a href="https://devapi.qweather.com/v7/indices/1d?type=3&location=" target="_blank">type=3&location=</a>${longitude},${latitude}&key=${key}`,
    ) S$ w2 X+ d6 T8 j
  49.           success (res) {/ i; i  F0 B4 O+ k
  50.             const {text}=res.data.daily[0]  //解构赋值' D" j: }  o9 F; d6 w5 e
  51.             that.setData({
    4 H/ D/ t9 z- |; l
  52.               weatherAdvice:text
    9 ~" k- [8 V1 B6 V
  53.             })
    " p3 T4 I$ ~! ]- n* L, a/ j7 X
  54.           }2 H4 p9 M" E" S& U- _8 D5 R
  55.         })
    * R8 o# @* J+ ^" I& B' X2 h
  56.       }1 m4 O- i) b' a" p
  57.      })
      t+ O8 c! A- J3 T( b
  58.   }
复制代码

  T& f; R/ j1 X( F- I( B​  接下来是小程序端的MQTT连接部分,首先需要导入一个连接服务器的库,这个库叫mqtt.min.js。该库的地址如下:mqtt.min.js文件
: a  e0 O8 q' B' B; e! E4 U% h# V6 _​  下载后,直接在小程序中建一个文件夹存放解压出来的文件,其中有两个文件分别为mqtt.js、mqtt.min.js,在小程序的js文件中只需引用mqtt.min.js文件即可,详细的引用代码及具体的自定义函数如下所示:(如果连接的是私有服务器需要多修改设备ID和密码,否则只需修改连接的服务器地址及端口号):" \( h, Q  C4 @
8 {, Z& ?2 U) r- j! V
  1. var mqtt=require("../../utils/mqtt.min.js")
    ! E3 h! {' C  o" |% v! @
  2. var client=null
    # ?* G+ f9 q& y: x- u# d
  3. Page({
    4 I2 Q5 i" t0 Q
  4.   /**
    . T4 j$ S7 D. y' }+ I
  5.    * 页面的初始数据
    3 q% v/ L# ^4 u) l+ k/ f
  6.    */
    ) ~6 L) \4 Q4 e
  7.   data: {
    9 c& F+ D$ F8 Y! d

  8. + Y2 G& A5 ]6 j8 c# n
  9.   },
    , X$ b$ N0 O1 Y7 j! Y
  10. , p0 }9 P) S3 }
  11.   onLoad(){. T" ?# ?: s1 E5 `$ S- O8 }
  12.     this.connectmqtt()+ b" T2 _: b( A" N! t
  13.   },
    6 N8 P/ _5 y8 }. l

  14. 5 p. I# |& b# a8 U( b+ g3 ~& |
  15.   connectmqtt:function(){5 f0 ]5 q, d7 W/ K
  16.     var that=this;//this是指外层的对象,如果在这里进行提取,后面进入函数后,他的this就是connectmqtt函数的对象! G# w, {& Z4 K2 P2 n' x, p* `% ?
  17.     /*杰叔叔、EMQX专用*/, ^! I' t0 M/ A# f# m( K
  18.     const options={
    % u& @# l# U, P4 `& M& f
  19.       connectTimeout:4000,
    & X7 m; H- H* C3 Y5 e8 E, C! r1 n, b, U
  20.       clientId:"zsd", //此变量随便写
    5 @1 g' V  C4 a+ \6 ]( i4 s, h
  21.       port:8084,: l  H$ t; J0 D" u
  22.       //杰叔叔的服务器是私有,所以需要账号和密码,而EMQX的免费服务器不需要账号密码" X. p) K  b4 g8 l4 Z: L) N
  23.       username:"f6d61178afa1003ac5d41dc9ae10f0c6",
    2 \# D$ w! C- H+ _
  24.       password:"123123"- O1 _- |9 L% E
  25.     }
    4 b+ z. V7 ^/ S$ \8 a( ?3 w5 e
  26.     /*腾讯云MQTT服务器专用*/
    + z9 P( g/ ~+ H2 V  `* x) I
  27.     /*  const options={
    % ]8 F! f; z& ^0 M+ c
  28.       connectTimeout:4000,
    : k9 T! q4 y1 l2 u5 a, Q
  29.       clientId:"zsd", //此变量随便写
    5 V/ y: K: e6 }1 }: H& m6 A
  30.       port:80,
    $ w% K! m, S! W/ b. \
  31.       username:"S2ME0J3F8Xtest1;12010126;bee9c;1656302400000",
    , |+ v9 ^# a4 B3 |! c2 H( Z# d/ P
  32.       password:"d58ce11e6725c4de9549c61d564f8bc0c7211707642ae92c63dd94b27943f85e;hmacsha256"  v& k! Q. u6 q( u3 x% ?$ b
  33.     }*/
    6 Z: J( G1 v; c$ O) t0 r
  34.     /*百度云MQTT服务器专用*/
    8 d: `; E9 u6 s( z4 x
  35.     /*  const options={$ Z3 G) k% [+ D5 ?9 j
  36.       connectTimeout:4000,
      Y7 b2 O' [, X" P
  37.       clientId:"zsd", //此变量随便写
    4 {8 H) ?3 o" Y" F  R5 t& T
  38.       port:443,! Y5 h3 o9 Z" b$ A4 c
  39.       username:"thingidp@acwbepc|test2|0|SHA256",* R  H# _) o  X. e% r
  40.       password:"6fac92df9ce9cb5839cf95da0c0d8f60e3d5d333fff8b7d85bcaf5b5e71d8517". U! H* v) z0 B- t
  41.     }*/
    ' ]) r2 @0 u  H, o; U- A8 M0 }3 r! [% o
  42.           /*小程序连接远程服务器时,用wxs(wss)加密连接出去,其他客户端工具,
    / Q  p# y+ t9 Q& A
  43.                   例如emqx在线测试工具可以使用wss协议连接服务器一;mqttbox软件也可以使用mqtt/tcp协议连接服务器一
    6 e5 \0 @0 l$ j( G9 x! u. W" Z
  44.                   原因是因为服务器支持这些协议,本质上wss、mqtt都是基于tcp进行封装的
    ( v) B2 k! X  G' c; C1 d. g
  45.                   实际上下面借助wxs协议连接服务器一,而其他工具也是借助服务器支持的协议进行连接,然后就可以进行数据的传输8 Z2 P4 N; @- `! _0 Y7 `. T
  46.             如果连接的协议是ws或wss,需要在服务器地址后面加上/mqtt,如果不是前面这两个协议的地址,则直接连接服务器地址即可*/! y& b0 y+ \, h! E
  47.     //client=mqtt.connect("wxs://t.yoyolife.fun/mqtt", options)杰叔叔的服务器地址(wss协议需加上mqtt路径)
    : ]/ j! U  q2 ?' o1 C
  48.     client=mqtt.connect("wxs://broker-cn.emqx.io/mqtt", options)//EMQX的服务器地址(wss协议需加上mqtt路径)- n6 K/ N0 N3 M4 o* ]
  49.     //client=mqtt.connect("wxs://broker.emqx.io/mqtt", options)//EMQX的服务器地址(wss协议需加上mqtt路径)  a0 b* U0 {+ e" ]
  50.     //client=mqtt.connect("wxs://S2ME0J3F8X.ap-guangzhou.iothub.tencentdevices.com/mqtt", options)//腾讯云服务器地址(wss协议需加上mqtt路径)3 [/ u4 B6 H# f0 B2 ?( {& z  e7 |
  51.     //client=mqtt.connect("wxs://acwbepc.iot.gz.baidubce.com/mqtt", options)//百度云服务器地址(wss协议需加上mqtt路径). f* t& r7 j& ]% i5 l5 H2 _
  52.     client.on("connect",(e)=>{
    : ~4 w5 }7 |% k+ c/ T, ?7 A
  53.       console.log("服务器连接成功");
    ! ?" Y- b6 U/ A# E8 @. N
  54.       client.subscribe("/iot/1009/zsd2", {qos:0}, function(err){//杰叔叔的服务器需要主题前缀、EMQX服务器不需要主题前缀& t5 s! i# G  q3 i# W5 ]
  55.         if(!err){4 c7 _7 s) _/ r+ s7 j- Z
  56.           console.log("订阅成功");
    - N& _' O0 L- l, c+ y
  57.         }3 O  ~' t/ s- h& \" M7 L3 |: H
  58.       })
    6 g6 h6 `8 ?; Q- E; }
  59.     /*  client.subscribe("S2ME0J3F8X/test1/data", {qos:0}, function(err){//腾讯云服务器需要主题前缀+ u. {/ V/ ^0 t; S4 [
  60.         if(!err){" o7 b/ o% A, G& i/ b
  61.           console.log("订阅成功");9 C, c! q. |  Z
  62.         }
    # N2 O( F9 e0 S# M/ g' c
  63.       })*/
    1 e) D. t0 q, |- y5 T, Y
  64.     /*  client.subscribe("$iot/test2/user/test2", {qos:0}, function(err){//百度云服务器需要主题前缀
    5 _: t+ f% C% s% m- M; }3 K. d/ Q
  65.         if(!err){- w( A2 N) u% g$ Y
  66.           console.log("订阅成功");
    4 c3 o$ m. ]) i# ~' I3 \$ e7 U
  67.         }
    9 x* l/ C. L" r2 [. Q& O6 F
  68.       })*/6 g% k  H) P! [& T) p* R( R+ N
  69.     })
    6 C) @/ n" V5 {9 |3 s
  70.     //信息监听事件6 f; W- X, Z9 [4 Y6 u  e
  71.     client.on("message", function(topic, message){
    7 {- ^6 H4 [* G4 k
  72.       let tem=JSON.parse(message). n. U" X* F* @$ R7 I
  73.       console.log(tem);
    ; Q" ^/ U- }5 t4 D8 d
  74.       that.setData({) N, X. w$ i7 Q( z9 i+ v
  75.         temp:tem.a,
    6 s/ S2 r/ \7 b9 f  G0 g( h6 V
  76.         humi:tem.b6 V; l$ f5 C* [4 ?
  77.       })
    8 N2 R/ Y& B5 Z* m4 p8 z
  78.       console.log("收到"+message.toString());
    . r/ `& H. I! {7 l* J& m9 K1 G
  79.     })
    ) g' w4 n. a5 O. T
  80.     //发送reconnect类型给服务器,一旦连接中断,就会触发重新连接
    # N: F& _# t& \
  81.     client.on("reconnect", (err)=>{3 l8 h  \6 I/ S& |
  82.       console.log("正在重新连接",err);
    7 L7 N3 x5 l! v1 D% b7 N
  83.     })6 y/ b5 a  K9 @# @6 |1 P# `* t
  84.     client.on("error", (err)=>{5 [& E4 i# R: v' j
  85.       console.log("连接失败",err);
    : R4 I+ K9 P4 v4 ]7 Y8 {& v5 S
  86.     })5 _% H2 }7 O, Q
  87.   }5 @& q# ^6 R; ~2 U* O
  88. % W( W3 @0 N" N
  89. })
    * o) N0 l: I) f0 O
复制代码
: B9 o+ d8 j2 q
​  至此,小程序部分的天气数据获取和MQTT连接已经基本完成,至于界面的优化,那就需要各位去学习小程序的界面优化啦。
3 H0 O4 P, Z. k————————————————& I  Z9 I7 F! P$ o( U
版权声明:i土豆
% T5 w+ s; ?4 o+ R) T* B! N
  A" ], F3 s/ K# N1 d) C9 [
7 j/ w9 v3 v# y9 u; W$ r4 A+ J
赞 收藏 评论0 发布时间:2022-10-16 22:09

举报

0个回答

所属标签

相似技术帖

官网相关资源

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