1. 前言
随着智能家居的快速发展,智能门锁作为家庭安全的重要组成部分,受到了越来越多用户的关注和需求。为了满足用户对安全和便捷的需求,决定设计一款基于STM32的智能门锁,并将其与华为云IOT平台相结合。
传统的门锁存在一些弊端,比如使用钥匙容易丢失、开锁过程繁琐等。而智能门锁的出现,有效地解决了这些问题。我选择使用STM32作为智能门锁的核心控制器,因为STM32系列具有低功耗、高性能和丰富的外设接口等优点,非常适合嵌入式应用。
华为云IOT平台作为一个强大的云服务平台,提供了丰富的物联网解决方案和强大的数据处理能力。将智能门锁与华为云IOT平台相结合,可以实现远程控制、数据监测和智能化的功能,为用户带来更加便捷和安全的居家体验。
智能门锁设计具有以下主要特点和功能:
安全可靠:采用先进的加密算法和身份验证机制,确保门锁的安全性。用户可以通过手机APP、指纹识别或密码等方式进行开锁,有效防止非法入侵。
远程控制:通过与华为云IOT平台的连接,用户可以通过手机APP在任何地方实现对门锁的远程控制。比如,可以远程开关门锁、查看开锁记录等。
多种开锁方式:除了传统的钥匙开锁方式外,我们的智能门锁还支持多种开锁方式,如指纹识别、密码输入、手机APP控制等。用户可以根据自己的需求选择最方便的开锁方式。
实时监测:智能门锁可以实时监测门锁状态、开锁记录等信息,并将这些数据上传到华为云IOT平台进行存储和分析。用户可以通过手机APP查看相关数据,了解家庭安全状况。
智能化功能:基于华为云IOT平台的数据处理能力,我们的智能门锁还可以实现一些智能化的功能。比如,可以设置自动开锁时间、远程授权开锁等。
2. 设备硬件与功能介绍
这篇文章就介绍如何使用华为物联网云平台实现智能锁的应用场景构建,硬件采用STM32F103ZET6 + ESP8266+步进电机实现。在华为云IOT物联网平台构建智能锁项目,配置好云端,设备端通过ESP8266连接华为物联网平台,实现数据上报,交互,实现远程开锁、关锁、获取锁的状态等功能,不用担心忘记出门关锁,也不用担心忘记带钥匙无法开门的情况。
ESP8266是物联网解决方案里比较热门的WIFI设备,支持串口+AT指令控制,任意支持串口的单片机都可以使用ESP8266快速实现联网。
步进电机采用常规28BYJ-48来模拟当做门锁的电机,驱动板采用ULN2003。
3. 创建云端设备
登录官网: https://www.huaweicloud.com/
直接搜索物联网,打开页面。
选择设备接入:
选择免费试用:
在产品页面,点击右上角创建产品:
填上产品信息:
得到产品ID,保存好ID,点击查看详情:
产品ID为:61b9ba3a2b2aa20288c1e7f1.
点击设备页面,注册设备:
填充信息进行注册:
保存设备密匙和设备ID,点击保存关闭会自动下载文件保存,后面生成密码和登录账号需要使用
关闭后就看到创建好的设备了:
点击产品页面,选择刚才创建的产品:
选择自定义模型---创建数据模型服务:
选择新增属性,创建设备的属性
4. 创建MQTT登录账号和密匙
设备创建完成接来下生成MQTT登录账号、密匙,方便设备登录云端平台。
官网工具地址: https://iot-tool.obs-website.cn-north-4.myhuaweicloud.com/
打开刚才创建设备时,下载的密匙文件,把内容复制出来对应的填进去,生成即可。
5. 拼接主题订阅与发布的格式
官方文档介绍: https://support.huaweicloud.com/devg-iothub/iot_01_2127.html
在产品页面可以,看到主题的全部格式:
总结的格式如下:
格式: $oc/devices/{device_id}/sys/messages/down
//订阅主题: 平台下发消息给设备
$oc/devices/61b9ba3a2b2aa20288c1e7f1_QQ1126626497_0_0_2021121510/sys/messages/down
格式: $oc/devices/{device_id}/sys/properties/report
//设备上报数据
$oc/devices/61b9ba3a2b2aa20288c1e7f1_QQ1126626497_0_0_2021121510/sys/properties/report
上属性的数据格式:
//上报的属性消息 (一次可以上报多个属性,在json里增加就行了)
{'services': [{'service_id': 'lock','properties':{'门锁':1}}]}
上面属性里的服务ID和属性里的名称,在设备页面,影子设备页面查看。
6. MQTT客户端模拟设备登录云端
下面使用MQTT客户端模拟设备登录服务器测试,看设备创建的是否OK。
服务器的IP地址是: 121.36.42.100
端口号是: 1883
打开MQTT客户端软件,按照提示,输入相关参数后,点击连接,然后再点击订阅主题,发布主题即可:
查看云端服务器的情况: 可以看到设备已经在线了,并且收到上传的数据。
修改一下锁的状态,上报属性再查看:
发现云端的状态也已经改变,现在设备上报已经OK。
接下来测试命令下发,实现远程开锁关锁的功能:
打开产品页面,新增加命令:
命令添加成功:
在设备页面,选择同步命令下发:
点击确定后,查看MQTT客户端,发现已经收到数据了:
$oc/devices/61b9ba3a2b2aa20288c1e7f1_QQ1126626497/sys/commands/request_id=88e2626f-290d-405e-962d-51554445a8fd{'paras':{'lock':1},'service_id':'lock','command_name':'lock'}
设备端解析收到的数据,就可以完成多步进电机的控制,完成开锁关锁。
7. STM32+ESP8266连接云端
工程是keil5工程
项目源码:https://download.csdn.net/download/xiaolong1126626497/81993720
main函数代码如下:
#include 'stm32f10x.h'
#include 'led.h'
#include 'delay.h'
#include 'key.h'
#include 'usart.h'
#include < string.h >
#include 'timer.h'
#include 'bluetooth.h'
#include 'esp8266.h'
#include 'mqtt.h'
//华为物联网服务器的设备信息
#define MQTT_ClientID '61b9ba3a2b2aa20288c1e7f1_QQ1126626497_0_0_2021121510'
#define MQTT_UserName '61b9ba3a2b2aa20288c1e7f1_QQ1126626497'
#define MQTT_PassWord '385ce91dfe7da5b7431868d5d87e7998163c493344040935d5a00024d6324242'
//订阅与发布的主题
#define SET_TOPIC '$oc/devices/61b9ba3a2b2aa20288c1e7f1_QQ1126626497_0_0_2021121510/sys/messages/down' //订阅
#define POST_TOPIC '$oc/devices/61b9ba3a2b2aa20288c1e7f1_QQ1126626497_0_0_2021121510/sys/properties/report' //发布
char mqtt_message[200];//上报数据缓存区
int main()
{
u32 time_cnt=0;
u32 i;
u8 key;
LED_Init();
BEEP_Init();
KEY_Init();
USART1_Init(115200);
TIMER1_Init(72,20000); //超时时间20ms
USART2_Init(9600);//串口-蓝牙
TIMER2_Init(72,20000); //超时时间20ms
USART3_Init(115200);//串口-WIFI
TIMER3_Init(72,20000); //超时时间20ms
USART1_Printf('正在初始化WIFI请稍等. ');
if(ESP8266_Init())
{
USART1_Printf('ESP8266硬件检测错误. ');
}
else
{
//非加密端口
USART1_Printf('WIFI:%d ',ESP8266_STA_TCP_Client_Mode('CMCC-Cqvn','99pu58cb','121.36.42.100',1883,1));
}
//2. MQTT协议初始化
MQTT_Init();
//3. 连接华为服务器
while(MQTT_Connect(MQTT_ClientID,MQTT_UserName,MQTT_PassWord))
{
USART1_Printf('服务器连接失败,正在重试... ');
delay_ms(500);
}
USART1_Printf('服务器连接成功. ');
//3. 订阅主题
if(MQTT_SubscribeTopic(SET_TOPIC,0,1))
{
USART1_Printf('主题订阅失败. ');
}
else
{
USART1_Printf('主题订阅成功. ');
}
while(1)
{
key=KEY_Scan(0);
if(key==2)
{
time_cnt=0;
sprintf(mqtt_message,'{'services': [{'service_id': 'lock','properties':{'门锁':1}}]}');
MQTT_PublishData(POST_TOPIC,mqtt_message,0);
USART1_Printf('发送状态1 ');
}
else if(key==3)
{
time_cnt=0;
sprintf(mqtt_message,'{'services': [{'service_id': 'lock','properties':{'门锁':0}}]}');
MQTT_PublishData(POST_TOPIC,mqtt_message,0);
USART1_Printf('发送状态0 ');
}
if(USART3_RX_FLAG)
{
USART3_RX_BUFFER[USART3_RX_CNT]=' ';
for(i=0;i< USART3_RX_CNT;i++)
{
USART1_Printf('%c',USART3_RX_BUFFER[i]);
}
USART3_RX_CNT=0;
USART3_RX_FLAG=0;
}
//定时发送心跳包,保持连接
delay_ms(10);
time_cnt++;
if(time_cnt==500)
{
MQTT_SentHeart();//发送心跳包
time_cnt=0;
}
}
}