【智能家居入门3】(MQTT服务器、MQTT协议、微信小程序、STM32)
前面已经写了三篇博客关于智能家居的,服务器全都是使用ONENET中国移动,他最大的优点就是作为数据收发的中转站是免费的。本篇使用专门适配MQTT协议的MQTT服务器,有公用的,也可以自己搭建(应该要钱),项目源码在最后
- 前言
- 一、项目总览
- 二、总体流程分析
- 1、了解mqtt协议
- 2、测试下位机与服务器的通信(mqtt.fx)
- 3、搭建自己的MQTT服务器
- 三、代码
- 1、下位机:
- 2、微信小程序:
- 四、项目获取
前言
本篇博客实现的功能和之前的智能家居系列类似,仅仅是把服务器换成了公用的mqtt服务器,在经过实测之后,个人觉得智能家居这种场景还是比较适合使用mqtt协议,仅仅是个人感觉。其实功能这一块我想到一个比较有意思的,就是用雨滴传感器和步进电机来模拟自动晾晒衣服的功能,大家应该能想象出来是啥意思,就是下雨了通过步进电机将晒衣服的架子给缩回来,不下雨了又给推出去,这还蛮有意思的。
前几篇博客:
①http+onenet实现数据上传给微信小程序
②http+onenet实现小程序下发指令控制开发板
③mqtt+onenet
一、项目总览
由于面包板还没到,线接的很乱就不拍照了,找到了之前做类似项目的照片,用这个代替一下:
微信小程序:
基本功能首先是检测家庭内部环境信息,其次就是微信小程序控制外设动作。
上面的实物图中有一个sim900A模块,是以前用到的,可以用于拨打电话和发送短信,要是有兴趣可以评论或者私信,我单独出一期。
可以看到本次微信小程序大改动,不再是前几篇那样简陋了,但是实现的功能还是一样的,这里就不再介绍了,请移步前几篇博客。
二、总体流程分析
1、了解mqtt协议
mqtt协议我单独出了一篇博客,参考:https://blog.csdn.net/m0_71523511/article/details/135905690
2、测试下位机与服务器的通信(mqtt.fx)
可以看到免费的mqtt服务器的域名是:broker.emqx.io,下位机上传数据使用TCP端口:1883。
通常当下位机上传数据逻辑写好之后不会直接用微信小程序进行测试,而是使用软件连接服务器来观察数据是否成功上传给了服务器,如果成功即可开始微信小程序的代码编写,没成功就调试,还是比较方便的。
这里使用mqtt.fx来进行测试:
在网上已经不好找到这个软件的早些版本了,这里给出网盘资源,下载后直接安装即可:
我用夸克网盘分享了「mqttfx-1.7.1-windows-x64.exe」,点击链接即可保存。打开「夸克APP」,无需下载在线播放视频,畅享原画5倍速,支持电视投屏。
链接:https://pan.quark.cn/s/8013f5c2151c
安装完成之后按照下面步骤设置:
首先点击那个蓝色的设置按钮,按下面这样设置好:
然后订阅单片机向服务器发送数据的topic:/smarthome/pub
此时只要下载在本篇文章结尾开源的代码(记得修改esp8266.c中的wifi名称和密码,其他的不用修改)并烧录,一会儿就可以在mqtt.fx软件的右边那个框看到上传上去的数据了。由于是公用的服务器,所以可能会导致数据流紊乱。如果测试没问题就可以打开微信小程序愉快的调试了。
3、搭建自己的MQTT服务器
这里我还没有尝试,但是有一个比较靠谱的视频:https://b23.tv/p8RkhU5
一般来说自己搭建多少是要钱的,如果免费的能满足尽量不要自己搭建,或者可以淘宝租一个月玩玩。
三、代码
1、下位机:
代码结构没变,还是那四个文件组成网络通信部分的代码:
①上传数据也没啥可以说的,直接参照上一篇博客即可(这次代码写的更漂亮,有参考价值)。
②接收数据在这里做了比较大的改动,这里使用两个键值对的逻辑进行发送和解析:
小程序下发的指令:
实际上对应的就是:{target:“fen”,value:“1”}
下位机解析:
首先解析出前面这个键值对的值,后面的逻辑就是判断这个值是多少,比如是leds的话就再进行第二个键值对的解析,此时判断第二个键值对的值是0还是1以控制对应的外设。这种逻辑相较于前几次博客的项目而言是可以减少内存占用的,因为只需要初始化一个:cJSON *json , *json_value;
2、微信小程序:
代码风格跟之前的完全不一样,如果想详细了解的话可以学一学javascript,或者直接gpt问各行代码的意思。本设计用微信开发者工具原生框架进行小程序设计,用到了多个不同的文件来设计小程序,其中app.json文件是对小程序进行全局配置的,可以配置顶部文字和底部tabBar栏;以.wxml为后缀的文件用来设置小程序的整个页面及页面各部分内部的文字、数据、图片等;以wxss为后缀的文件用来在.wxml文件构建好的部分中设置规则,比如字体大小、颜色等;以.js为后缀的文件使用JavaScript语言处理小程序和用户的交互(与单片机的数据接收和发送)
①index.js
const app = getApp()const{ connect } = require('../../utils/mqtt')const mqttHost = 'broker.emqx.io'
const mqttPort = 8084const deviceSub = '/mysmarthome/sub' //小程序发布指令的Topic
const devicePub = '/smarthome/pub' //小程序接收数据的Topicconst mpSubTopic = devicePub //mp指小程序(这样更直观)
const mpPubTopic = deviceSub //小程序发布指令的TopicPage({data: {client: null,Humi:0,Temp:0,huoyan:1,gas:0,leds:false,ranqi:0,fen:false,water:false},//下发指令:ledonledsChange(event){const that = thisconsole.log(event.detail.value);const sw = event.detail.valuethat.setData({leds:sw})if(sw){that.data.client.publish(mpPubTopic,JSON.stringify({target:"leds",value:1}),function (err) {if(!err){console.log('成功下发指令打开led')console.log('{target:"leds",value:1}')}})}else{that.data.client.publish(mpPubTopic,JSON.stringify({target:"leds",value:0}),function (err) {if(!err){console.log('成功下发指令关闭led')console.log('{target:"leds",value:0}')}})}},//下发指令:风扇onfenChange(event){const that = thisconsole.log(event.detail.value);const sw = event.detail.valuethat.setData({fen:sw})if(sw){that.data.client.publish(mpPubTopic,JSON.stringify({target:"fen",value:1}),function (err) {if(!err){console.log('成功下发指令打开排气扇')}})}else{that.data.client.publish(mpPubTopic,JSON.stringify({target:"fen",value:0}),function (err) {if(!err){console.log('成功下发指令关闭排气扇')}})}},//下发指令:水泵onwaterChange(event){const that = thisconsole.log(event.detail.value);const sw = event.detail.valuethat.setData({water:sw})if(sw){that.data.client.publish(mpPubTopic,JSON.stringify({target:"water",value:1}),function (err) {if(!err){console.log('成功下发指令打开水泵')}})}else{that.data.client.publish(mpPubTopic,JSON.stringify({target:"water",value:0}),function (err) {if(!err){console.log('成功下发指令关闭水泵')}})}},//显示接受到的数据onShow(){const that = thisthat.setData({client:connect(`wxs://${mqttHost}:${mqttPort}/mqtt`)})that.data.client.on('connect',function (params) {console.log('成功连接到mqtt服务器')wx.showToast({title: '连接成功',icon:'success',mask:true})that.data.client.subscribe(mpSubTopic,function (err) {if(!err){console.log('成功订阅设备上行数据Topic')}})})that.data.client.on('message',function (topic,message) {console.log(topic);let dataFromDev = {}try {dataFromDev = JSON.parse(message)console.log(dataFromDev);that.setData({Temp:dataFromDev.Temp,Humi:dataFromDev.Humi,huoyan:dataFromDev.huoyan,gas:dataFromDev.gas,ranqi:dataFromDev.ranqi,})} catch (error) {console.log('JSON解析失败',error)}})},
})
②index.wxml
<!--index.wxml-->
<view class="page-container">
<!--头部部分--><view class="header-container"><view class="header-one"><view>战损版</view></view><view class="header-two"><view>智能家居</view></view></view>
<!--数据部分-->
<view class="data-container"><!--温度--><view class="data-card"><image class="data-card__icon" src="/static/wendu.png" /><view class="data-card__text"><view class="data-card__title">温度</view><view class="data-card__value">{{ Temp }} ℃</view></view></view><!--湿度--><view class="data-card"><image class="data-card__icon" src="/static/shidu.png" /><view class="data-card__text"><view class="data-card__title">湿度</view><view class="data-card__value">{{ Humi }}%rh</view></view></view><!--可燃气体浓度--><view class="data-card"><image class="data-card__icon" src="/static/gas.png" /><view class="data-card__text"><view class="data-card__title">可燃气浓度</view><view class="data-card__value">{{ ranqi }} ppm</view></view></view><!--烟雾浓度--><view class="data-card"><image class="data-card__icon" src="/static/yanwu.png" /><view class="data-card__text"><view class="data-card__title">天然气浓度</view><view class="data-card__value">{{ gas }} ppm</view></view></view><view class="data-card"><image class="data-card__icon" src="/static/huoyan.png" /><view class="data-card__text"><view class="data-card__title">火焰</view><view class="data-card__value"><view wx:if="{{huoyan == 1}}">无</view><view wx:elif="{{huoyan == 0}}">有</view></view></view></view><!--雨水--><view class="data-card"><image class="data-card__icon" src="/static/yudi.png" /><view class="data-card__text"><view class="data-card__title">雨</view><view class="data-card__value"><view wx:if="{{xiayu==1}}">下雨</view><view wx:elif="{{xiayu==0}}">未下雨</view></view></view></view><!--开启or关闭排气扇--><view class="data-card"><image class="data-card__icon" src="/static/fen.png"/><view class="data-card__text"><view class="data-card__title">排气扇</view><view class="data-card__value"><switch checked="{{fen}}" bindchange="onfenChange" color="#3d7ef9"/></view></view></view><!--开启or关闭水泵--><view class="data-card"><image class="data-card__icon" src="/static/water.png"/><view class="data-card__text"><view class="data-card__title">水泵</view><view class="data-card__value"><switch checked="{{water}}" bindchange="onwaterChange" color="#3d7ef9"/></view></view></view><!--开启or关闭卧室灯--><view class="data-card"><image class="data-card__icon" src="/static/leds.png" /><view class="data-card__text"><view class="data-card__title">卧室灯</view><view class="data-card__value"><switch checked="{{ leds }}" bindchange="onledsChange" color="#3d7ef9"/></view></view></view></view></view>
③index.wxss
/**小程序整个页面的设置**/
.page-container{padding: 36rpx;
}
/**设置顶部大筐筐**/
.header-container{background-color: #fff;color: black;box-shadow: #d6d6d6 0 0 20rpx;border-radius: 36rpx;padding: 3rpx 3rpx;
}
/**设置顶部大筐筐内的第一行字**/
.header-container .header-one{display: flex;justify-content: center;padding: 10rpx;font-size: 50rpx;font: bold;
}
/**设置顶部大筐筐内的第二行字**/
.header-container .header-two{ display: flex;justify-content: center;padding: 10rpx;font-size: 40rpx;font: bold;
}.choice {display: flex;flex-direction: row;font-size: 20px;justify-content: center;color: rgb(38, 38, 39);margin-top: 30rpx;margin-bottom: 20rpx;top: 3rpx;box-shadow:0px 0px 10px #bfbfc0 inset;
}.btn1 {/* float:left;background-color: rgb(112, 107, 107);color: rgb(66, 63, 63); */float:left;top: 3rpx;box-shadow:0px 0px 8px #999 inset;
}.btn-class{float:left;top: 3rpx;box-shadow:0px 0px 10px #b8b9bd inset;
}.btn2 {float:right; top: 3rpx;box-shadow:0px 0px 8px #999 inset;
}
.btn-class2{float:right;top: 3rpx;box-shadow:0px 0px 10px #b8b9bd inset;
}.btn3 {float:left;top: 3rpx;box-shadow:0px 0px 8px #999 inset;
}
.btn-class3{float:left;top: 3rpx;box-shadow:0px 0px 10px #b8b9bd inset;
}.btn4 {float:right;top: 3rpx;box-shadow:0px 0px 8px #999 inset;
}
.btn-class4{float:right;top: 3rpx;box-shadow:0px 0px 10px #b8b9bd inset;
}.s_view{bottom: 0rpx; width: 100%;
}/**设置数据部分总体布局**/
.data-container{margin-top: 30rpx;display: grid;justify-content: center;grid-template-columns: repeat(auto-fill,300rpx);grid-gap: 30rpx;
}
/**设置数据部分小卡片内的格式**/
.data-container .data-card{position: relative;background-color: #fff;height: 140rpx;box-shadow: #d6d6d6 0 0 8rpx;border-radius: 36rpx;display: flex;justify-content: space-between;padding: 16rpx;
}
/**以下是小卡片内的文本、图片、标题、数值设置**/
.data-container .data-card .data-card__text{position: absolute;top: 20rpx;right: 24rpx;text-align: right;white-space: nowrap;
}.data-container .data-card .data-card__icon{position: absolute;height: 72rpx;width: 72rpx;left: 32rpx;top: 16rpx;
}.data-container .data-card .data-card__value{font-size: 40rpx;margin-top: 20rpx;
}.data-container .data-card .data-card__title{font-size: 34rpx;
}
至此整个项目的关键点介绍完毕,可以想象出裸机还是可能会漏消息的,下一篇就是使用freertos来进行编程,使得整个系统的实时性再一次提高。
四、项目获取
我用夸克网盘分享了「智能家居(mqtt服务器+mqtt协议).rar」,点击链接即可保存。打开「夸克APP」,无需下载在线播放视频,畅享原画5倍速,支持电视投屏。
链接:https://pan.quark.cn/s/42127dfa3d3a
提取码:2Nmg
相关文章:

【智能家居入门3】(MQTT服务器、MQTT协议、微信小程序、STM32)
前面已经写了三篇博客关于智能家居的,服务器全都是使用ONENET中国移动,他最大的优点就是作为数据收发的中转站是免费的。本篇使用专门适配MQTT协议的MQTT服务器,有公用的,也可以自己搭建(应该要钱)…...

C语言第二十四弹---指针(八)
✨个人主页: 熬夜学编程的小林 💗系列专栏: 【C语言详解】 【数据结构详解】 指针 1、数组和指针笔试题解析 1.1、字符数组 1.1.1、代码1: 1.1.2、代码2: 1.1.3、代码3: 1.1.4、代码4: 1…...
m1芯片xcode15编译cocos2dx一些报错处理
报错1: No matching function for call to ‘iconv’ No matching function for call to ‘iconv_close’ 解决: 强转: iconv_close((iconv_t)_iconv); iconv((iconv_t)_iconv, (char**)&pin, &inLen, &pout, &outLen); 报错2: Proper…...

代码+视频基于R语言进行K折交叉验证
我们在建立数据模型后通常希望在外部数据验证模型的检验能力。然而当没有外部数据可以验证的时候,交叉验证也不失为一种方法。交叉验验证(交叉验证,CV)则是一种评估模型泛化能力的方法,广泛应用…...

第一篇【传奇开心果系列】Python的pyttsx3库技术点案例示例:文本转换语言
传奇开心果短博文系列 系列短博文目录Python的pyttsx3库技术点案例示例系列 短博文目录前言一、pyttsx3主要特点和功能介绍二、pyttsx3文字转语音操作步骤介绍三、多平台支持介绍和示例代码四、多语言支持介绍和示例代码五、自定义语言引擎介绍和示例代码六、调整语速和音量介绍…...
@ 代码随想录算法训练营第7周(C语言)|Day43(动态规划)
代码随想录算法训练营第7周(C语言)|Day43(动态规划) Day41、动态规划(包含题目 ● 1049. 最后一块石头的重量 II ● 494. 目标和 ● 474.一和零 ) 1049. 最后一块石头的重量 II 题目描述 有一堆石头&am…...

深度学习的新进展:探索人工智能的未来
文章目录 📑引言深度学习技术概述计算机视觉领域的深度应用自然语言处理的深度革命跨领域应用的深度拓展深度学习的挑战与未来展望结语 📑引言 在科技日新月异的今天,深度学习作为人工智能领域的一颗璀璨明珠,正在引领着技术创新…...
Vue中@change、@input和@blur、@focus的区别及@keyup介绍
Vue中change、input和blur、focus的区别及keyup介绍 1. change、input、blur、focus事件2. keyup事件3. 补充:el-input的change事件自定义传参 1. change、input、blur、focus事件 change在输入框发生变化且失去焦点后触发; input在输入框内容发生变化后…...
Raspbian简易RTSP服务
Raspbian简易RTSP服务 1. 源由2. 搭建简易RTSP服务器2.1 系统安装2.2 软件安装2.3 命令介绍2.3.1 libcamera-hello2.3.2 libcamera-vid2.3.3 cvlc 3. 实测4. 参考资料 1. 源由 鉴于前期的一些准备工作: 《ArduPilot开源飞控之Companion Computers简单分析》《Ardu…...
【ASP.NET 6 Web Api 全栈开发实战】--前言
《ASP.NET 6 Web Api 实战》专栏通过一步一步的开发并完善一个记账软件项目,来引导大家学习相关的知识,其中的知识包括但不限于如下内容: Web Api 开发.NET 6 项目微服务架构的搭建身份认证移动端应用开发more。。。 专栏结构 专栏分为单体…...
跳过mysql8.0密码重置密码 Shell脚本
要在 MySQL 8.0 中通过 Shell 脚本跳过密码验证以重置密码,你可以遵循以下步骤:首先,确保你有足够的权限来编辑配置文件和重启 MySQL 服务。下面是一个简单的 Shell 脚本示例,该脚本展示了如何跳过密码验证以重置 MySQL 8.0 的 ro…...

Maven之安装自定义jar到本地Maven仓库中
Maven之安装自定义jar到本地Maven仓库中 文章目录 Maven之安装自定义jar到本地Maven仓库中1. 命令行窗口安装方式1. 常用参数说明2. 安装实例 2. IDEA中安装方式3. 使用 1. 命令行窗口安装方式 安装指定文件到本地仓库命令:mvn install:install-file; 在windows的cm…...

SPI控制8_8点阵屏
协议与硬件概述 SPI SPI是串行外设接口(Serial Peripheral Interface)的缩写。是一种高速的(10Mbps)的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线。 引脚介绍 SCLK:…...
2.10
头文件: #include <sqlite3.h> 编译时候要加上-lsqlite3 gcc a.c -lsqlite3 1)sqlite3_open 打开一个数据库,如果数据库不存在,则创建一个数据库 2)sqlite3_close 关闭数据库,断开句柄所拥有的资…...

计算机服务器中了360后缀勒索病毒怎么办?360后缀勒索病毒处理流程
网络技术的不断应用与发展,为企业的生产运营提供了有利保障,越来越多的企业走向数字化办公模式,并且企业的发展离不开数据支撑,重视数据安全成为了众多企业关心的主要话题。春节前后,云天数据恢复中心接到很多企业的求…...

BigDecimal的常用API
BigDecimal用于解决浮点型运算时结果出现失真的问题。 这里0.20.1等于0.3就出现了失真 import java.math.BigDecimal; import java.math.RoundingMode;public class Test {public static void main(String[] args) {//BigDeciaml的使用:解决小数运算失真的问题doub…...

Android---Jetpack Compose学习005
动画 1. 简单值动画 示例:背景颜色在紫色和绿色之间,以动画形式切换。使用 animateColorAsState() val backgroundColor by animateColorAsState(if (tabPage TabPage.Home) Purple100 else Green300) 该句代码中,有一个 backgroundColo…...

安卓价值1-如何在电脑上运行ADB
ADB(Android Debug Bridge)是Android平台的调试工具,它是一个命令行工具,用于与连接到计算机的Android设备进行通信和控制。ADB提供了一系列命令,允许开发人员执行各种操作,包括但不限于: 1. 安…...

第三百四十七回
文章目录 1. 概念介绍2. 原理与方法2.1 知识对比2.2 使用方法 3. 示例代码4. 内容总结 我们在上一章回中介绍了"加密包crypto"相关的内容,本章回中将介绍characters包.闲话休提,让我们一起Talk Flutter吧。 1. 概念介绍 在项目中会遇到获取字…...
23种设计模式之原型模式
目录 什么是原型模式 为什么使用原型模式 原型模式的基本结构 原型模式的实现步骤 实现代码(含注释) 使用场景 什么是原型模式 原型模式是一种创建型设计模式,该模式的核心思想是基于现有的对象创建新的对象,而不是从头开…...

idea大量爆红问题解决
问题描述 在学习和工作中,idea是程序员不可缺少的一个工具,但是突然在有些时候就会出现大量爆红的问题,发现无法跳转,无论是关机重启或者是替换root都无法解决 就是如上所展示的问题,但是程序依然可以启动。 问题解决…...
OpenLayers 可视化之热力图
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 热力图(Heatmap)又叫热点图,是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...
云计算——弹性云计算器(ECS)
弹性云服务器:ECS 概述 云计算重构了ICT系统,云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台,包含如下主要概念。 ECS(Elastic Cloud Server):即弹性云服务器,是云计算…...

微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】
微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来,Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...
前端倒计时误差!
提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...

【大模型RAG】Docker 一键部署 Milvus 完整攻略
本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装;只需暴露 19530(gRPC)与 9091(HTTP/WebUI)两个端口,即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...
C++.OpenGL (10/64)基础光照(Basic Lighting)
基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...

微信小程序云开发平台MySQL的连接方式
注:微信小程序云开发平台指的是腾讯云开发 先给结论:微信小程序云开发平台的MySQL,无法通过获取数据库连接信息的方式进行连接,连接只能通过云开发的SDK连接,具体要参考官方文档: 为什么? 因为…...

视频行为标注工具BehaviLabel(源码+使用介绍+Windows.Exe版本)
前言: 最近在做行为检测相关的模型,用的是时空图卷积网络(STGCN),但原有kinetic-400数据集数据质量较低,需要进行细粒度的标注,同时粗略搜了下已有开源工具基本都集中于图像分割这块,…...

【笔记】WSL 中 Rust 安装与测试完整记录
#工作记录 WSL 中 Rust 安装与测试完整记录 1. 运行环境 系统:Ubuntu 24.04 LTS (WSL2)架构:x86_64 (GNU/Linux)Rust 版本:rustc 1.87.0 (2025-05-09)Cargo 版本:cargo 1.87.0 (2025-05-06) 2. 安装 Rust 2.1 使用 Rust 官方安…...