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

stm32利用mqtt与小程序通信

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

1 |9 Y, F" H9 ^! _, T. T
5 x& I% |+ L6 s, o1 Y4 j" J& v* D
6cde9575277f4238b6a7eae9d6c5019d.png

8 ]( F* D( t9 |$ J
1 m2 J. G* I$ f1 [- C
453801fdbcc24fb58c01654c6d1759d3.png
  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 @# \
60a454561882413c9e135d241e0b90da.png
) 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
2ea29e4152434a6d9ac4e7a2acae9341.png
) A% s1 f3 S2 L$ f' S$ a. ?! r

& |7 @) ]% n; j
959f20157eb240dc8a77746f1df9108d.png
# 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
31c485dd56364a24b3ee2e80c96f1222.png
' 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
ef03ad84687344d0bef3551db07d271a.png

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

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
  1. weahterdata:function(){
    2 B$ W4 \6 L/ q5 V+ |
  2.     var that=this& E4 t; A$ l! t
  3.     wx.getLocation({//获取位置(经纬度)API
    - Q( `3 p+ k9 ^/ ]8 {# X7 a
  4.       type: 'wgs84',
    8 @2 W4 F& Y& i
  5.       success (res) {
    ' j# E! H, t6 F. e) O. t( I
  6.         const latitude = res.latitude
    / O+ |; m8 d. y! N0 s/ h0 C) w3 H
  7.         const longitude = res.longitude
    + v, v+ y' N0 P7 _/ Z) ]" N
  8.         const key="432a8840589546338cae4c5a825f47db"//和风天气开发平台上控制台创建的应用得到的KEY,只有得到这个,才能获取各种数据
    . V( T9 z# \; T3 ?, J
  9.         wx.request({//网络请求API
    6 t0 |) l8 d; F4 v/ K: f. _8 Q# y, k
  10.           //下面使用模板字符串
    / F+ x: m( a" r1 e& I5 q
  11.           //获取天气数据的API接口地址
    7 b; o4 \* j9 n7 u! [8 ~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}`, ( b/ ]9 H1 x+ O+ R1 A3 k( t
  13.           success (res) {
    ; f7 f' [# V/ `* w& T. l' {( A
  14.             const weather_data=res.data.now ( \1 T# F% Y5 @
  15.             const weather=weather_data.text //解构赋值
    $ @5 B9 Z! C$ @4 r
  16.             that.setData({5 V' E5 c) j) M; Q
  17.               weather, U) h- s6 V, M, |, X4 N
  18.             })
    1 e; W0 i2 V& j  H. G9 a$ F' A
  19.           }
    * Y2 @( J% Q% E" n2 @# f
  20.         })
    : J4 R9 r2 J: m. S% r! p8 P
  21.         wx.request({6 B% p$ b+ |- z( o  r
  22.           //获取地点的API接口地址
    ( [' W2 \* z( R) D, _! b+ T* i2 `! t
  23.           url: , 4 j' F; c( C# W' u% T! G
  24.           success (res) {' K! P& J2 E9 V. u/ ]: X4 A1 G
  25.             const location=res.data.location[0]  1 z8 ^+ a5 E0 t3 z
  26.             const {adm2, name}=location     //解构赋值
    / R6 R* E) s- q- V& @5 X
  27.             that.setData({
    1 X  R5 M0 n* H
  28.               city:adm2,
    " D! k9 c1 a7 ]0 T6 L/ `7 k4 k" k
  29.               area:name
    . l& ~7 r; |" h3 Z: S
  30.             })
    0 \" Z7 R5 K/ h) t  l
  31.           }
    0 ^3 y! S+ j) I3 [0 i- ?" y
  32.         })
    5 o7 Y" B* K- J3 ~
  33.         wx.request({
    9 M8 s# r. |% B) I- ~2 {
  34.           //获取空气质量的API接口地址
    * v; a9 ]3 h, [4 |( W% h" p
  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}`,
    % d+ f, M! j# y$ \; M
  36.           success (res) {/ Y$ \" b+ T2 j$ v. q2 K0 e
  37.             const air=res.data.now  
    * n! q7 K; \* m  d: O" s* Q
  38.             const {aqi, category}=air       //解构赋值: \2 B: c1 {/ \6 d/ V9 {
  39.             that.setData({
    8 u' r* W+ A6 E  S# }* W' [0 `
  40.               aqi,. O5 q* ^- l: P' L0 \
  41.               airText:category+ s( j: r+ _6 W; N% y
  42.             })
    : d5 W( `# t$ I/ ^/ Y
  43.           }/ z5 |" ]: L/ K& Y+ ?
  44.         })
    : W. W) i" A: b, L% @
  45. - x3 o2 j7 }9 j7 L
  46.         wx.request({, A0 |1 A+ L: F8 t% S% p5 e
  47.           //获取生活质量的API接口地址; R9 [2 @8 S5 |6 T7 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}`, 9 d% J$ K# Y" K3 _5 x$ c: g
  49.           success (res) {
    ( O2 k9 {- i1 ?$ D+ W
  50.             const {text}=res.data.daily[0]  //解构赋值
    " C- W' K2 v0 q: T% n) W. n
  51.             that.setData({  c( O9 J& [# _! k5 {6 V# e3 J/ O/ N
  52.               weatherAdvice:text5 C" L' N2 u. Z, L2 h$ x( _. @
  53.             })
    7 ]$ R6 }/ n$ Z6 |2 ?0 _: W( l  O
  54.           }4 s1 n* ]$ o* o7 I) ?% F. ~4 M
  55.         })" }' T$ s" q# y/ r% @
  56.       }' M5 x' g9 ?$ b- V4 B0 V0 e) `6 y
  57.      })
    , t$ h2 k/ ?5 f
  58.   }
复制代码

, 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$ [
  1. var mqtt=require("../../utils/mqtt.min.js")
    / ^) _: Q- m8 o
  2. var client=null
    ' b5 U' {: P; d1 D
  3. Page({( c8 Y& s& a% d3 L/ v" V+ Q4 Z: r
  4.   /**
    ! I5 i# c5 L2 u# r% h  k
  5.    * 页面的初始数据' M! k1 f% q4 l/ Q
  6.    */
    ( q" b: ~1 i$ y% I0 M
  7.   data: {2 r9 D8 j3 K# ?9 ?7 M8 P0 V

  8. , z+ V5 j' o) ^
  9.   },1 W, Z5 p5 K9 H' b& x/ q

  10. : n7 N# @6 T1 G
  11.   onLoad(){  ^- J, w1 u7 T6 D5 a0 G
  12.     this.connectmqtt()
    : |) w  R, k" r! }1 ]) K- n0 `
  13.   },
    9 \0 U1 {  C, i. v3 A- D7 a

  14. " x( K* L: Q9 _+ [+ S' {
  15.   connectmqtt:function(){
    " {+ t9 c+ _' d2 ?0 n5 j" ~
  16.     var that=this;//this是指外层的对象,如果在这里进行提取,后面进入函数后,他的this就是connectmqtt函数的对象
    & t2 t6 f* D/ q% [# D, n
  17.     /*杰叔叔、EMQX专用*/
    . M  Y5 W2 Y% ^- u7 R
  18.     const options={6 ]2 m; ]( v7 B8 p
  19.       connectTimeout:4000,4 e+ R1 z% z: U" W9 P9 G
  20.       clientId:"zsd", //此变量随便写# ]2 ?( z6 q$ X' f
  21.       port:8084,
    & R: Z& O  g1 g& \" c  r9 S1 Q) G
  22.       //杰叔叔的服务器是私有,所以需要账号和密码,而EMQX的免费服务器不需要账号密码
    5 y# A$ x' t7 [$ V
  23.       username:"f6d61178afa1003ac5d41dc9ae10f0c6",/ [/ T9 W1 n. j2 b2 }  ?
  24.       password:"123123"7 M4 {8 H( l% O
  25.     }
    : ]3 [& w7 p" u( s% L7 i( I& o( J
  26.     /*腾讯云MQTT服务器专用*/
    + y- ~+ g+ f! x! k4 }0 f( x
  27.     /*  const options={: [9 i' l; q/ a2 k! m! F  F( c
  28.       connectTimeout:4000,
    2 I' T/ ?! j0 s$ H
  29.       clientId:"zsd", //此变量随便写
    ' _, o5 d, a! L8 t& |4 H
  30.       port:80,- e( ^" h0 _: t! W) j8 l' c  i8 }0 j
  31.       username:"S2ME0J3F8Xtest1;12010126;bee9c;1656302400000",
    1 g" P4 ]' s3 z! J
  32.       password:"d58ce11e6725c4de9549c61d564f8bc0c7211707642ae92c63dd94b27943f85e;hmacsha256"; j7 z. q7 f1 U6 V6 I) ^+ u
  33.     }*/
    % K  ~9 ]! m, |" I! W
  34.     /*百度云MQTT服务器专用*/8 L+ c  j1 ~3 Z' S- l, V
  35.     /*  const options={
    # p* z5 x; \( j: n
  36.       connectTimeout:4000,
    5 @6 i  C( y0 R2 s& ]! U2 O
  37.       clientId:"zsd", //此变量随便写
    1 N1 i7 P2 l' G9 L8 f. Q
  38.       port:443,
    , H: Y; k0 v) i3 Y0 S( M0 B
  39.       username:"thingidp@acwbepc|test2|0|SHA256",! x* j" b! P) u5 T5 X7 V
  40.       password:"6fac92df9ce9cb5839cf95da0c0d8f60e3d5d333fff8b7d85bcaf5b5e71d8517"
    ) l1 V! i/ y- G/ `: V
  41.     }*/5 \. f( z! R# e0 g. H# L
  42.           /*小程序连接远程服务器时,用wxs(wss)加密连接出去,其他客户端工具,
    " R9 f; u6 C3 M9 D
  43.                   例如emqx在线测试工具可以使用wss协议连接服务器一;mqttbox软件也可以使用mqtt/tcp协议连接服务器一( o& R% ]! F8 Y' q
  44.                   原因是因为服务器支持这些协议,本质上wss、mqtt都是基于tcp进行封装的5 g$ K" }, r7 d8 G) ]: A
  45.                   实际上下面借助wxs协议连接服务器一,而其他工具也是借助服务器支持的协议进行连接,然后就可以进行数据的传输8 c4 V, e9 s( A- d' T. d& V/ t
  46.             如果连接的协议是ws或wss,需要在服务器地址后面加上/mqtt,如果不是前面这两个协议的地址,则直接连接服务器地址即可*/
    3 C; q% l& |9 G( x7 H
  47.     //client=mqtt.connect("wxs://t.yoyolife.fun/mqtt", options)杰叔叔的服务器地址(wss协议需加上mqtt路径)
    5 d4 M5 p6 K4 T' |+ S7 U/ ?
  48.     client=mqtt.connect("wxs://broker-cn.emqx.io/mqtt", options)//EMQX的服务器地址(wss协议需加上mqtt路径)
    2 k" u# m: E) R8 d: c
  49.     //client=mqtt.connect("wxs://broker.emqx.io/mqtt", options)//EMQX的服务器地址(wss协议需加上mqtt路径)
    . Q7 @# E* c+ Q7 o5 Q
  50.     //client=mqtt.connect("wxs://S2ME0J3F8X.ap-guangzhou.iothub.tencentdevices.com/mqtt", options)//腾讯云服务器地址(wss协议需加上mqtt路径)
    ( Y% n) r& U, s4 ]8 W
  51.     //client=mqtt.connect("wxs://acwbepc.iot.gz.baidubce.com/mqtt", options)//百度云服务器地址(wss协议需加上mqtt路径)
    ( \/ s1 Y) U+ n1 x
  52.     client.on("connect",(e)=>{4 d( X/ D' c5 g0 z1 v7 h; L
  53.       console.log("服务器连接成功");
    7 \2 T0 n, H2 b! q- K) g- V
  54.       client.subscribe("/iot/1009/zsd2", {qos:0}, function(err){//杰叔叔的服务器需要主题前缀、EMQX服务器不需要主题前缀
    ! D; B; U: c& ]( c
  55.         if(!err){! g9 X$ U/ O3 I( L* K# s
  56.           console.log("订阅成功");
    5 z$ U' s. a4 Q: w. o: S
  57.         }/ \8 O1 m* i# ]
  58.       })
    1 F# o2 `' @! h: F% G
  59.     /*  client.subscribe("S2ME0J3F8X/test1/data", {qos:0}, function(err){//腾讯云服务器需要主题前缀
    " T1 S3 C  ?! z' i2 g
  60.         if(!err){$ }5 o' Y  z' H. \% d3 w
  61.           console.log("订阅成功");  s# C( t6 s/ {$ _- ]0 g
  62.         }
    8 S# v' m. ], l; g
  63.       })*/
    0 \+ ^! s  n/ F* L: Y' v
  64.     /*  client.subscribe("$iot/test2/user/test2", {qos:0}, function(err){//百度云服务器需要主题前缀7 J. W6 m% }. z6 l/ f* _
  65.         if(!err){# J5 H1 @8 m! J, R" b% Z
  66.           console.log("订阅成功");
    & t$ j: H; K; j
  67.         }5 r$ ~6 J9 t1 c* |0 {' @
  68.       })*/
    " C* I2 q! K% A( ?/ B5 f5 U% R# @5 U
  69.     }), M- d) K8 |- |- x" H  i9 M
  70.     //信息监听事件
    ( F8 p8 r, M5 E- ~
  71.     client.on("message", function(topic, message){
    , n5 f. |  ~5 S. t1 W1 `/ L
  72.       let tem=JSON.parse(message)
    * C, U# v+ X0 L# ^* u
  73.       console.log(tem);
    % i$ G/ j- Y9 N& V! C' J) B/ w+ Q/ s2 }
  74.       that.setData({
    ) A6 T& k$ a9 U+ L/ o
  75.         temp:tem.a,( |) y" ?  A9 G0 a& W' E4 E
  76.         humi:tem.b
    9 s2 F" o! @5 ?" Q2 e. w
  77.       })& X3 j0 m7 I7 p  l  d$ s
  78.       console.log("收到"+message.toString());
    6 ~% l+ ]# `( Y  g; o
  79.     })
    9 W- l) W) u% H: U, C
  80.     //发送reconnect类型给服务器,一旦连接中断,就会触发重新连接, v7 P, o! v0 ?$ {
  81.     client.on("reconnect", (err)=>{
    9 {* @) Z/ s* Q, a
  82.       console.log("正在重新连接",err);  l$ N4 ?# z( Y  E# i
  83.     })
    3 t- [, K- v; c" n( j+ t
  84.     client.on("error", (err)=>{. l8 t, E) a2 L, n6 @. v) z( {& H( \
  85.       console.log("连接失败",err);
    & o/ e9 d# c! I! v% J) k
  86.     })$ R% ?3 n9 s, L5 O
  87.   }
      L- B, F/ I% n( \

  88. , `- B4 G) y( A7 `2 ]! M9 H& e
  89. })
    ( 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
收藏 评论0 发布时间:2022-10-16 22:09

举报

0个回答

所属标签

相似分享

官网相关资源

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