详细!基于ESP32的智能门禁系统(华为云iot+微信小程序)_esp32连接华为云-程序员宅基地

技术标签: 微信小程序  华为云  物联网  单片机  iot  

git地址:智能门禁(云IOT+微信小程序)

开关门效果

设备侧

产品创建

创建产品

创建产品协议类型选择MQTT,数据格式选择JSON,其他参数自定

在这里插入图片描述

设备注册

找到所属产品,认证类型选择密钥,单击确定后注册成功

在这里插入图片描述

注册成功后出现如下页面,点击保存并关闭,会自动下载好"device_id"和"secret",保存好

在这里插入图片描述

模型定义

产品->选择你的产品->查看->模型定义->自定义模型->定义产品的服务

在这里插入图片描述

在这里插入图片描述

添加属性,定义好一系列参数点击确定

可参考技术文档 在线开发产品模型

在这里插入图片描述

添加命令,添加好下发参数和响应参数

在这里插入图片描述

在这里插入图片描述

产品连接

头文件包含

#include<WiFiMulti.h>
#include<Arduino.h>
#include<WebServer.h>
#include<PubsubClient.h>
#include<ArduinoJson.h>

静态参数定义

const char* wifiName = "";//ESP32连接的WiFi名称
const char* wifiPwd = "";//wifi密码
const char* mqttServer = "cdee1c2246.iot-mqtts.cn-north-4.myhuaweicloud.com";//华为云MQTT接入地址
const int   mqtt = 1883;//端口
//下面三个参数为设备接入华为云iot的鉴权参数
const char* clientID = "";
const char* userName = "";
const char* passWord = "";

华为云接入地址可在总览->平台接入地址中查看

在这里插入图片描述

鉴权参数通过参数生成工具生成 MQTT ClientId生成工具

在这里插入图片描述

topic参数定义

topic参数在产品->选择要查看的产品->topic管理可查看

在这里插入图片描述

{device_id}需要替换为设备ID

在这里插入图片描述

const char* topic_report = "$oc/devices/6346a83e06cae4010b4d1387_esp32_door/sys/properties/report";//设备上报
const char* topic_command = "$oc/devices/6346a83e06cae4010b4d1387_esp32_door/sys/commands/#";//设备接收命令
const char* topic_command_response = "$oc/devices/6346a83e06cae4010b4d1387_esp32_door/sys/commands/response/request_id=";//设备发送响应

WIFI连接和MQTT连接

void WifiSetup()
{
  wifiMulti.addAP(wifiName,wifiPwd);//wifi连接
  Serial.print("connecting to:");
  Serial.println(WiFi.SSID());//打印wifi名称
  while(wifiMulti.run() != WL_CONNECTED)
  {
    delay(1000);
    Serial.print(".");
  }
  Serial.println("connection  success!");
  Serial.println("IP address:");
  Serial.println(WiFi.localIP());
}

void MQTT_Init()
{
  client.setServer(mqttServer,mqtt);//设置mqtt服务器参数
  client.setKeepAlive(60);//设置心跳时间
  while(!client.connected())
  {
    Serial.println("Connecting to MQTT...");
    if(client.connect(clientID,userName,passWord))//和华为云iot服务器建立mqtt连接
    {
      Serial.println("connected");
    }else{
      Serial.print("failed with state:");
      Serial.print(client.state());
    }
  }
  client.setCallback(callback);//监听平台下发命令
}

在callback函数定义需要的服务

属性上报和命令响应

属性上报

可参考技术文档 https://support.huaweicloud.com/api-iothub/iot_06_v5_3010.html

在这里插入图片描述

时间戳可有可无,设备上报数据不带该参数或参数格式错误时,则数据上报时间以平台时间为准

修改完成后使用ArduinoJSON官网生成代码 ArduinoJson

选择ESP32->序列化->String

在这里插入图片描述

修改后的JSON数据如下,根据参数不同自行修改

在这里插入图片描述

属性上报详细代码如下

void MQTT_Report()
{
  String JSONmessageBuffer;//定义字符串接收序列化好的JSON数据
//以下将生成好的JSON格式消息格式化输出到字符数组中,便于下面通过PubSubClient库发送到服务器
StaticJsonDocument<96> doc;

JsonObject services_0 = doc["services"].createNestedObject();
services_0["service_id"] = "door";
services_0["properties"]["doorState"] = doorState;//doorState为全局变量

serializeJson(doc, JSONmessageBuffer);

  Serial.println("Sending message to MQTT topic..");
  Serial.println(JSONmessageBuffer);
  
  if(client.publish(topic_report,JSONmessageBuffer.c_str())==true)//使用c_str函数将string转换为char
  {
    Serial.println("Success sending message");
  }else{
    Serial.println("Error sending message");
  }
  client.loop();//保持硬件活跃度
  Serial.println("---------------");
}

命令下发

在产品模型中定义了命令下发和响应参数,就可以通过iot平台对设备下发命令,设备接收命令后按JSON格式像平台发送响应,平台收到响应后才确认下发成功

可参考技术文档 平台命令下发

在这里插入图片描述

const char* topic_command = "$oc/devices/6346a83e06cae4010b4d1387_esp32_door/sys/commands/#";//设备接收命令
const char* topic_command_response = "$oc/devices/6346a83e06cae4010b4d1387_esp32_door/sys/commands/response/request_id=";//设备发送响应

响应参数需要将request_id参数返回给平台,所以需要在callback函数中将平台下发的request_id提取出来

在下发命令中request_id可以使用通配符#代替,但是响应中的request_id必须与下发命令的request_id一致

上文定义的callback函数在此实现

需要提取request_id,打印JSON数据,对下发命令做出对应的硬件处理

void callback(char *topic,byte *payload,unsigned int length)
{

  char *pstr = topic; //指向topic字符串,提取request_id用
 
  /*串口打印出收到的平台消息或者命令*/
  Serial.println();
  Serial.println();
  Serial.print("Message arrived [");
  Serial.print(topic);  //将收到消息的topic展示出来
  Serial.print("] ");
  Serial.println();
 
  payload[length] = '\0'; //在收到的内容后面加上字符串结束符
  char strPayload[255] = {0}; 
  strcpy(strPayload, (const char*)payload);
  Serial.println((char *)payload);  //打印出收到的内容
  Serial.println(strPayload);
 
 
  /*request_id解析部分*///后文有详细解释为什么要提取下发命令的request_id
  char arr[100];  //存放request_id
  int flag = 0;
  char *p = arr;
  while(*pstr)  //以'='为标志,提取出request_id
  {
    if(flag) *p ++ = *pstr;
    if(*pstr == '=') flag = 1;
    pstr++;
  }
  *p = '\0';  
  Serial.println(arr);
 
 
  /*将命令响应topic与resquest_id结合起来*/
  char topicRes[200] = {0};
  strcat(topicRes, topic_command_response);
  strcat(topicRes, arr);
  Serial.println(topicRes);

 // Stream& input;

StaticJsonDocument<192> doc;

DeserializationError error = deserializeJson(doc, payload);

if (error) {
  Serial.print("deserializeJson() failed: ");
  Serial.println(error.c_str());
  return;
}

int paras_doorOpen = doc["paras"]["doorOpen"]; // 1

const char* service_id = doc["service_id"]; // "door"
const char* command_name = doc["command_name"]; // "doorControl"

if(paras_doorOpen == 1)
{
  openDoor();//对应的硬件响应函数
  delay(5000);
ledcWrite(channel, calculatePWM(0));
}if (paras_doorOpen == 0)
{
  closeDoor();
}
MQTT_response(topicRes);//发送响应参数
}

内容根据具体需求修改

MQTT.fx

下载和详细操作可以查看文档,这里只做简单使用

使用MQTT.fx调测

可以使用MQTT.fx工具查看下发命令对应的JSON数据

在这里插入图片描述

点击apply

在这里插入图片描述

通过iot控制台 产品->选择你的产品->命令->同步命令下发

在这里插入图片描述

即可通过MQTT.fx工具查看到下发命令的JSON数据

在这里插入图片描述

复制到ArduinoJSON官网解析数据 ArduinoJson

选择ESP32->反序列化->Stream

在这里插入图片描述

命令响应

参考技术文档 平台命令下发

在这里插入图片描述

在这里插入图片描述

由于三个参数都是可选的,所以直接返回空JSON也是可以的

在这里插入图片描述

void MQTT_response(char *topic)
{
String response;

StaticJsonDocument<128> doc;

JsonObject response = doc.createNestedObject("response");
doc["result_code"] = 0;
doc["response_name"] = "doorControl";
doc["paras"]["doorRes"] = "1";

serializeJson(doc, response);

client.publish(topic,response.c_str());
Serial.println(response);
}

物理层面

使用舵机拉动门把手,延迟后归为即可实现简易的智能门禁系统

舵机控制

舵机是伺服电机的一种,伺服电机就是带有反馈环节的电机,我们可以通过伺服电机进行精确的位置控制或者输出较高的扭矩;
一般舵机的旋转范围是0°~ 180°。舵机是由可变宽度的脉冲控制。脉冲的参数有最小值、最大值和频率。一般而言,舵机的基准信号周期为20ms,所以频率为50kHz。脉冲宽度和舵机的转角0°~ 180°相对应的。

在这里插入图片描述

在这里插入图片描述

这里使用的是180°舵机MG995,如果门把手很难拉动,需要更换扭矩更大的舵机。

PWM信号线可以连接GPIO口上,具体可查看ESP32手册,这里接的是16IO口

代码如下

int freq = 50;      // 频率(20ms周期)
int channel = 8;    // 通道(高速通道(0 ~ 7)由80MHz时钟驱动,低速通道(8 ~ 15)由 1MHz 时钟驱动。)
int resolution = 8; // 分辨率
const int led = 16;

int calculatePWM(int degree)
{ //0-180度
 //20ms周期,高电平0.5-2.5ms,对应0-180度角度
  const float deadZone = 6.4;//对应0.5ms(0.5ms/(20ms/256)) 舵机转动角度与占空比的关系:(角度/90+0.5)*1023/20
  const float max = 32;//对应2.5ms
  if (degree < 0)
    degree = 0;
  if (degree > 180)
    degree = 180;
  return (int)(((max - deadZone) / 180) * degree + deadZone);
}

void closeDoor()
{
  ledcWrite(channel, calculatePWM(0));
}
void openDoor()
{
  ledcWrite(channel, calculatePWM(180));
}

接下来只需在callback函数中增加硬件响应函数,这里是对平台下发的doorOpen做判断

if(paras_doorOpen == 1)
{
  openDoor();//对应的硬件响应函数
  delay(5000);
ledcWrite(channel, calculatePWM(0));
}else if (paras_doorOpen == 0)
{
  closeDoor();
}

应用侧

使用http请求调用API实现应用侧的开发

微信小程序

新建小程序

不使用云服务->JavaScript

在这里插入图片描述

删除模板文件pages->新建一个page->输入名称->回车自动生成4个配置文件

在这里插入图片描述

获取Token

Token在计算机系统中代表令牌(临时)的意思,拥有Token就代表拥有某种权限。Token认证就是在调用API的时候将Token加到请求消息头,从而通过身份认证,获得操作API的权限。

详情可查看文档 认证鉴权

wx.request方法
wx.request({
    
       url: '',
       data:'',
       method: '', // OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT
       header: {
    }, // 设置请求的 header 
       success: function(res){
    // success
       // success
       },
        fail:function(){
    
        // fail
       },
        complete: function() {
    
       // complete
       } 
 });
包装request方法为gettoken方法
  gettoken:function(){
    
    var that=this;
    wx.request({
    
      url: '',
      data:'',
      method: '', // OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT
      header: {
    }, // 设置请求的 header 
      success: function(res){
    // success
      // success
      },
       fail:function(){
    
       // fail
      },
       complete: function() {
    
      // complete
      } 
    });
    },
补全请求体

在这里插入图片描述

在这里插入图片描述

  gettoken:function(){
    
    var that=this;
    wx.request({
    
      url: 'https://iam.cn-north-4.myhuaweicloud.com/v3/auth/tokens',
      data:'{ "auth": { "identity": { "methods":[  "password" ], "password": {  "user": {  "name": "hw82982217", "password": "",  "domain": { "name": "hw82982217"  } } } },  "scope": { "project": {  "name": "cn-north-4" } } }  }',
      method: 'POST', // OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT
      header: {
    'Content-Type': 'application/json'}, // 设置请求的 header 
      success: function(res){
    // success
      // success
      var token='';
      console.log(res);
      token=JSON.stringify(res.header['X-Subject-Token']);//解析Token
      token=token.replaceAll("\"","");
      console.log("获取token=\n"+token);
      that.settoken(token);
      },
       fail:function(){
    
       // fail
      },
       complete: function() {
    
      // complete
      } 
    });
    },
API Explorer调试

获取IAM用户Token(使用密码)
设置好参数->点击调试->可以看到响应头的Token

在这里插入图片描述

传出Token

    settoken:function(_token){
    
      this.data.token=_token;
      wx.setStorageSync('token', _token);//将Token保存到缓存中
      console.log('外部获取到token:'+this.data.token);
      this.setData({
    result:"token认证成功"});
    },

命令下发

    issuecom1:function(){
    
      var that=this;
      var token=wx.getStorageSync('token');
      wx.request({
    
        url: 'https://cdee1c2246.iotda.cn-north-4.myhuaweicloud.com:443/v5/iot/0ab004b22500f4b72fa3c00977112a06/devices/6346a83e06cae4010b4d1387_esp32_door/commands',
        data:'{"service_id": "door","command_name": "doorControl","paras": {"doorOpen": "1"} }',
        method:'POST',
        header:{
    "X-Auth-Token": token,"Content-Type": "application/json"},
        success:function(res){
    
          console.log("成功\n");
          console.log(res);
        },
        fail:function(){
    
          console.log("失败");
        },
      })
    },
    //关门
    issuecom0:function(){
    
      var that=this;
      var token=wx.getStorageSync('token');
      wx.request({
    
        url: 'https://cdee1c2246.iotda.cn-north-4.myhuaweicloud.com:443/v5/iot/0ab004b22500f4b72fa3c00977112a06/devices/6346a83e06cae4010b4d1387_esp32_door/commands',
        data:'{"service_id": "door","command_name": "doorControl","paras": {"doorOpen": "0"} }',
        method:'POST',
        header:{
    "X-Auth-Token": token,"Content-Type": "application/json"},
        success:function(res){
    
          console.log("成功\n");
          console.log(res);
        },
        fail:function(){
    
          console.log("失败");
        },
      })
    },

页面设计

为界面添加两个按钮

在这里插入图片描述

设置相应的响应函数

在这里插入图片描述

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/zxyxm_/article/details/127398280

智能推荐

从零开始搭建Hadoop_创建一个hadoop项目-程序员宅基地

文章浏览阅读331次。第一部分:准备工作1 安装虚拟机2 安装centos73 安装JDK以上三步是准备工作,至此已经完成一台已安装JDK的主机第二部分:准备3台虚拟机以下所有工作最好都在root权限下操作1 克隆上面已经有一台虚拟机了,现在对master进行克隆,克隆出另外2台子机;1.1 进行克隆21.2 下一步1.3 下一步1.4 下一步1.5 根据子机需要,命名和安装路径1.6 ..._创建一个hadoop项目

心脏滴血漏洞HeartBleed CVE-2014-0160深入代码层面的分析_heartbleed代码分析-程序员宅基地

文章浏览阅读1.7k次。心脏滴血漏洞HeartBleed CVE-2014-0160 是由heartbeat功能引入的,本文从深入码层面的分析该漏洞产生的原因_heartbleed代码分析

java读取ofd文档内容_ofd电子文档内容分析工具(分析文档、签章和证书)-程序员宅基地

文章浏览阅读1.4k次。前言ofd是国家文档标准,其对标的文档格式是pdf。ofd文档是容器格式文件,ofd其实就是压缩包。将ofd文件后缀改为.zip,解压后可看到文件包含的内容。ofd文件分析工具下载:点我下载。ofd文件解压后,可以看到如下内容: 对于xml文件,可以用文本工具查看。但是对于印章文件(Seal.esl)、签名文件(SignedValue.dat)就无法查看其内容了。本人开发一款ofd内容查看器,..._signedvalue.dat

基于FPGA的数据采集系统(一)_基于fpga的信息采集-程序员宅基地

文章浏览阅读1.8w次,点赞29次,收藏313次。整体系统设计本设计主要是对ADC和DAC的使用,主要实现功能流程为:首先通过串口向FPGA发送控制信号,控制DAC芯片tlv5618进行DA装换,转换的数据存在ROM中,转换开始时读取ROM中数据进行读取转换。其次用按键控制adc128s052进行模数转换100次,模数转换数据存储到FIFO中,再从FIFO中读取数据通过串口输出显示在pc上。其整体系统框图如下:图1:FPGA数据采集系统框图从图中可以看出,该系统主要包括9个模块:串口接收模块、按键消抖模块、按键控制模块、ROM模块、D.._基于fpga的信息采集

微服务 spring cloud zuul com.netflix.zuul.exception.ZuulException GENERAL-程序员宅基地

文章浏览阅读2.5w次。1.背景错误信息:-- [http-nio-9904-exec-5] o.s.c.n.z.filters.post.SendErrorFilter : Error during filteringcom.netflix.zuul.exception.ZuulException: Forwarding error at org.springframework.cloud..._com.netflix.zuul.exception.zuulexception

邻接矩阵-建立图-程序员宅基地

文章浏览阅读358次。1.介绍图的相关概念  图是由顶点的有穷非空集和一个描述顶点之间关系-边(或者弧)的集合组成。通常,图中的数据元素被称为顶点,顶点间的关系用边表示,图通常用字母G表示,图的顶点通常用字母V表示,所以图可以定义为:  G=(V,E)其中,V(G)是图中顶点的有穷非空集合,E(G)是V(G)中顶点的边的有穷集合1.1 无向图:图中任意两个顶点构成的边是没有方向的1.2 有向图:图中..._给定一个邻接矩阵未必能够造出一个图

随便推点

MDT2012部署系列之11 WDS安装与配置-程序员宅基地

文章浏览阅读321次。(十二)、WDS服务器安装通过前面的测试我们会发现,每次安装的时候需要加域光盘映像,这是一个比较麻烦的事情,试想一个上万个的公司,你天天带着一个光盘与光驱去给别人装系统,这将是一个多么痛苦的事情啊,有什么方法可以解决这个问题了?答案是肯定的,下面我们就来简单说一下。WDS服务器,它是Windows自带的一个免费的基于系统本身角色的一个功能,它主要提供一种简单、安全的通过网络快速、远程将Window..._doc server2012上通过wds+mdt无人值守部署win11系统.doc

python--xlrd/xlwt/xlutils_xlutils模块可以读xlsx吗-程序员宅基地

文章浏览阅读219次。python–xlrd/xlwt/xlutilsxlrd只能读取,不能改,支持 xlsx和xls 格式xlwt只能改,不能读xlwt只能保存为.xls格式xlutils能将xlrd.Book转为xlwt.Workbook,从而得以在现有xls的基础上修改数据,并创建一个新的xls,实现修改xlrd打开文件import xlrdexcel=xlrd.open_workbook('E:/test.xlsx') 返回值为xlrd.book.Book对象,不能修改获取sheett_xlutils模块可以读xlsx吗

关于新版本selenium定位元素报错:‘WebDriver‘ object has no attribute ‘find_element_by_id‘等问题_unresolved attribute reference 'find_element_by_id-程序员宅基地

文章浏览阅读8.2w次,点赞267次,收藏656次。运行Selenium出现'WebDriver' object has no attribute 'find_element_by_id'或AttributeError: 'WebDriver' object has no attribute 'find_element_by_xpath'等定位元素代码错误,是因为selenium更新到了新的版本,以前的一些语法经过改动。..............._unresolved attribute reference 'find_element_by_id' for class 'webdriver

DOM对象转换成jQuery对象转换与子页面获取父页面DOM对象-程序员宅基地

文章浏览阅读198次。一:模态窗口//父页面JSwindow.showModalDialog(ifrmehref, window, 'dialogWidth:550px;dialogHeight:150px;help:no;resizable:no;status:no');//子页面获取父页面DOM对象//window.showModalDialog的DOM对象var v=parentWin..._jquery获取父window下的dom对象

什么是算法?-程序员宅基地

文章浏览阅读1.7w次,点赞15次,收藏129次。算法(algorithm)是解决一系列问题的清晰指令,也就是,能对一定规范的输入,在有限的时间内获得所要求的输出。 简单来说,算法就是解决一个问题的具体方法和步骤。算法是程序的灵 魂。二、算法的特征1.可行性 算法中执行的任何计算步骤都可以分解为基本可执行的操作步,即每个计算步都可以在有限时间里完成(也称之为有效性) 算法的每一步都要有确切的意义,不能有二义性。例如“增加x的值”,并没有说增加多少,计算机就无法执行明确的运算。 _算法

【网络安全】网络安全的标准和规范_网络安全标准规范-程序员宅基地

文章浏览阅读1.5k次,点赞18次,收藏26次。网络安全的标准和规范是网络安全领域的重要组成部分。它们为网络安全提供了技术依据,规定了网络安全的技术要求和操作方式,帮助我们构建安全的网络环境。下面,我们将详细介绍一些主要的网络安全标准和规范,以及它们在实际操作中的应用。_网络安全标准规范