【智能家居入门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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/683851.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Java程序员面试专栏 分布式中间件】ElasticSearch 核心面试指引

关于ElasticSearch 部分的核心知识进行一网打尽,包括ElasticSearch 的基本概念,基本架构,工作流程,存储机制等,通过一篇文章串联面试重点,并且帮助加强日常基础知识的理解,全局思维导图如下所示 基础概念 从数据分类入手,考察全文索引的基本概念 现实世界中数据有哪…

量子算法入门——2.线性代数与复数

参考资料&#xff1a; 【【零基础入门量子计算-第03讲】线性代数初步与复数】 来自b站up&#xff1a;溴锑锑跃迁 建议关注他的更多高质量文章&#xff1a;CSDN&#xff1a;【溴锑锑跃迁】 0. 前言 强烈建议搭配b站原视频进行观看&#xff0c;这只是我当时看的笔记&#xff0c…

【机器学习笔记】4 朴素贝叶斯

贝叶斯方法 贝叶斯分类 贝叶斯分类是一类分类算法的总称&#xff0c;这类算法均以贝叶斯定理为基础&#xff0c;故统称为贝叶斯分类。 朴素贝叶斯分类是这一类算法中最简单的较为常见的算法。 先验概率 根据以往经验和分析得到的概率。我们用&#x1d443;(&#x1d44c;)来代…

FL Studio 21.2.3.4004 All Plugins Edition Win/Mac音乐软件

FL Studio 21.2.3.4004 All Plugins Edition 是一款功能强大的音乐制作软件&#xff0c;提供了丰富的音频处理工具和插件&#xff0c;适用于专业音乐制作人和爱好者。该软件具有直观的用户界面&#xff0c;支持多轨道录音、混音和编辑&#xff0c;以及各种音频效果和虚拟乐器。…

华清远见嵌入式学习——春节作业——2.15日

作业要求&#xff1a; 编写led驱动&#xff0c;通过应用程序控制三盏灯亮灭 作业答案&#xff1a; 作业效果&#xff1a; mychrdev.c #include <linux/init.h> #include <linux/module.h> #include <linux/fs.h> #include <linux/uaccess.h> #incl…

基于GPT-4一键完成数据分析全流程的AI Agent: Streamline Analyst

大型语言模型&#xff08;LLM&#xff09;的兴起不仅为获取知识和解决问题开辟了新的可能性&#xff0c;而且催生了一些新型智能系统&#xff0c;例如旨在辅助用户完成特定任务的AI Copilot以及旨在自动化和自主执行复杂任务的AI Agent&#xff0c;使得编程、创作等任务变得高效…

医卫答案在哪搜?九个公众号和软件推荐清单! #笔记#笔记#微信

在这个信息爆炸的时代&#xff0c;合理利用学习工具可以帮助我们过滤和获取有用的知识。 1.粉鹿搜题 这是一个公众号 题库包括四六级答案、各学校往期课后答案、期末考试题等&#xff0c;使用比较简单。 下方附上一些测试的试题及答案 1、最有可能担任债券发行受托人的个人…

装饰工程|装饰工程管理系统-项目立项子系统的设计与实现|基于Springboot的装饰工程管理系统设计与实现(源码+数据库+文档)

装饰工程管理系统-项目立项子系统目录 目录 基于Springboot的装饰工程管理系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、管理员功能实现 &#xff08;2&#xff09;合同报价管理 &#xff08;3&#xff09;装饰材料总计划管理 &#xff08;4&#xff0…

Java与JavaScript的区别与联系

Java是目前编程领域使用非常广泛的编程语言&#xff0c;相较于JavaScript&#xff0c;Java更被人们熟知。很多Java程序员想学门脚本语言&#xff0c;一看JavaScript和Java这么像&#xff0c;很有亲切感&#xff0c;那干脆就学它了&#xff0c;这也间接的帮助了JavaScript的发展…

OLED显示红外遥控键码

基本原理 本遥控器的编码是NEC编码&#xff0c;为PWM&#xff08;脉冲宽度调制&#xff09;。 发射红外载波的时间固定&#xff0c;通过改变不发射载波的时间来改变占空比。 逻辑“0”是由0.56ms的38KHZ载波和0.560ms的无载波间隔组成&#xff1b;逻辑“1”是由0.56ms的38KHZ…

LabVIEW高效电磁阀性能测试

LabVIEW高效电磁阀性能测试 在核电站的安全运营中&#xff0c;电磁阀作为关键组件&#xff0c;其性能的可靠性至关重要。设计一套基于LabVIEW的电磁阀测试平台&#xff0c;既能精准测试电磁阀的多项性能指标&#xff0c;又能提高检修效率与准确性&#xff0c;进而保障核电站的…

接口测试全流程扫盲

扫盲内容&#xff1a; 1.什么是接口&#xff1f; 2.接口都有哪些类型&#xff1f; 3.接口的本质是什么&#xff1f; 4.什么是接口测试&#xff1f; 5.问什么要做接口测试&#xff1f; 6.怎样做接口测试&#xff1f; 7.接口测测试点是什么&#xff1f; 8.接口测试都要掌…

​StableSwarmUI#超越文本的prompt

今天看到一个新的webui方案&#xff0c;是Stability-AI开源的&#xff1a; StableSwarmUI 是一个模块化的稳定扩散web用户界面&#xff0c;着重于使强大的工具易于访问、高性能和可扩展性。 由于项目还在开发中&#xff0c;我们可以先了解下&#xff0c;翻看了它的特点&#xf…

ELAdmin 发送邮件

邮箱配置 ELAdmin目录中选择系统工具->邮件工具。 发件人邮箱&#xff1a;发送者的邮箱地址发件用户名&#xff1a;一般都是发件人邮箱前面的部分&#xff0c;也可以任意写邮箱密码&#xff1a;如果是 qq 邮箱或者腾讯企业邮箱&#xff0c;需要使用授权码。SMTP地址&…

表的连接

目录 内连接实现效果 使用左外连接&#xff0c;将所有的员工信息都显示出来&#xff0c;即便他没有对应的部门 使用右外连接&#xff0c;将所有的部门信息都显示出来 查询每个员工的编号、姓名、职位&#xff0c;以及所在各部门的领导姓名、领导职位 确定所需要的数据表 确…

多模态基础--- word Embedding

1 word Embedding 原始的单词编码方式&#xff1a; one-hot&#xff0c;维度太大&#xff0c;不同单词之间相互独立&#xff0c;没有远近关系区分。 wordclass&#xff0c;将同一类单词编码在一起&#xff0c;此时丢失了类别和类别间的相关信息&#xff0c;比如class1和class3…

应急响应实战笔记02日志分析篇(3)

第3篇:Web日志分析 ox01 Web日志 Web访问日志记录了Web服务器接收处理请求及运行时错误等各种原始信息。通过对WEB日志进行的安全分析&#xff0c;不仅可以帮助我们定位攻击者&#xff0c;还可以帮助我们还原攻击路径&#xff0c;找到网站存在的安全漏洞并进行修复。 我们来…

【牛客面试必刷TOP101】Day21.BM11 链表相加(二)和BM12 单链表的排序

作者简介&#xff1a;大家好&#xff0c;我是未央&#xff1b; 博客首页&#xff1a;未央.303 系列专栏&#xff1a;牛客面试必刷TOP101 每日一句&#xff1a;人的一生&#xff0c;可以有所作为的时机只有一次&#xff0c;那就是现在&#xff01;&#xff01;&#xff01;&…

算法详解:滑动窗口-- 最大连续1的个数 III

题目来源:力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 本期讲解滑动窗口经典例题,我会从三个点开始讲解题目1.题目解析2.算法原理 3.编写代码 1.题目解析 这道题目理解起来还是比较简单的,我们简单分析一下,也就是给定一个数组,数组是由1和0组成…

红日靶场2学习

靶场下载来自&#xff1a; http://vulnstack.qiyuanxuetang.net/vuln/detail/3/ 靶场统一登录密码&#xff1a;1qazWSX 按大佬的说法是 环境需要模拟内网和外网两个网段&#xff0c;PC端虚拟机相当于网关服务器&#xff0c;所以需要两张网卡&#xff0c;一个用来向外网提供web…