git地址:智能門禁(云IOT+微信小程序)
開關(guān)門效果
設(shè)備側(cè)
產(chǎn)品創(chuàng)建
創(chuàng)建產(chǎn)品
創(chuàng)建產(chǎn)品,協(xié)議類型選擇MQTT,數(shù)據(jù)格式選擇JSON,其他參數(shù)自定
設(shè)備注冊
找到所屬產(chǎn)品,認證類型選擇密鑰,單擊確定后注冊成功
注冊成功后出現(xiàn)如下頁面,點擊保存并關(guān)閉,會自動下載好"device_id"和"secret",保存好
模型定義
產(chǎn)品->選擇你的產(chǎn)品->查看->模型定義->自定義模型->定義產(chǎn)品的服務(wù)
添加屬性,定義好一系列參數(shù)點擊確定
可參考技術(shù)文檔 在線開發(fā)產(chǎn)品模型
添加命令,添加好下發(fā)參數(shù)和響應(yīng)參數(shù)
產(chǎn)品連接
頭文件包含
#include<WiFiMulti.h>
#include<Arduino.h>
#include<WebServer.h>
#include<PubsubClient.h>
#include<ArduinoJson.h>
靜態(tài)參數(shù)定義
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;//端口
//下面三個參數(shù)為設(shè)備接入華為云iot的鑒權(quán)參數(shù)
const char* clientID = "";
const char* userName = "";
const char* passWord = "";
華為云接入地址可在總覽->平臺接入地址中查看
鑒權(quán)參數(shù)通過參數(shù)生成工具生成 MQTT ClientId生成工具
topic參數(shù)定義
topic參數(shù)在產(chǎn)品->選擇要查看的產(chǎn)品->topic管理可查看
{device_id}需要替換為設(shè)備ID
const char* topic_report = "$oc/devices/6346a83e06cae4010b4d1387_esp32_door/sys/properties/report";//設(shè)備上報
const char* topic_command = "$oc/devices/6346a83e06cae4010b4d1387_esp32_door/sys/commands/#";//設(shè)備接收命令
const char* topic_command_response = "$oc/devices/6346a83e06cae4010b4d1387_esp32_door/sys/commands/response/request_id=";//設(shè)備發(fā)送響應(yīng)
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);//設(shè)置mqtt服務(wù)器參數(shù)
client.setKeepAlive(60);//設(shè)置心跳時間
while(!client.connected())
{
Serial.println("Connecting to MQTT...");
if(client.connect(clientID,userName,passWord))//和華為云iot服務(wù)器建立mqtt連接
{
Serial.println("connected");
}else{
Serial.print("failed with state:");
Serial.print(client.state());
}
}
client.setCallback(callback);//監(jiān)聽平臺下發(fā)命令
}
在callback函數(shù)定義需要的服務(wù)
屬性上報和命令響應(yīng)
屬性上報
可參考技術(shù)文檔 https://support.huaweicloud.com/api-iothub/iot_06_v5_3010.html
時間戳可有可無,設(shè)備上報數(shù)據(jù)不帶該參數(shù)或參數(shù)格式錯誤時,則數(shù)據(jù)上報時間以平臺時間為準
修改完成后使用ArduinoJSON官網(wǎng)生成代碼 ArduinoJson
選擇ESP32->序列化->String
修改后的JSON數(shù)據(jù)如下,根據(jù)參數(shù)不同自行修改
屬性上報詳細代碼如下
void MQTT_Report()
{
String JSONmessageBuffer;//定義字符串接收序列化好的JSON數(shù)據(jù)
//以下將生成好的JSON格式消息格式化輸出到字符數(shù)組中,便于下面通過PubSubClient庫發(fā)送到服務(wù)器
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函數(shù)將string轉(zhuǎn)換為char
{
Serial.println("Success sending message");
}else{
Serial.println("Error sending message");
}
client.loop();//保持硬件活躍度
Serial.println("---------------");
}
命令下發(fā)
在產(chǎn)品模型中定義了命令下發(fā)和響應(yīng)參數(shù),就可以通過iot平臺對設(shè)備下發(fā)命令,設(shè)備接收命令后按JSON格式像平臺發(fā)送響應(yīng),平臺收到響應(yīng)后才確認下發(fā)成功
可參考技術(shù)文檔 平臺命令下發(fā)
const char* topic_command = "$oc/devices/6346a83e06cae4010b4d1387_esp32_door/sys/commands/#";//設(shè)備接收命令
const char* topic_command_response = "$oc/devices/6346a83e06cae4010b4d1387_esp32_door/sys/commands/response/request_id=";//設(shè)備發(fā)送響應(yīng)
響應(yīng)參數(shù)需要將request_id參數(shù)返回給平臺,所以需要在callback函數(shù)中將平臺下發(fā)的request_id提取出來
在下發(fā)命令中request_id可以使用通配符#代替,但是響應(yīng)中的request_id必須與下發(fā)命令的request_id一致
上文定義的callback函數(shù)在此實現(xiàn)
需要提取request_id,打印JSON數(shù)據(jù),對下發(fā)命令做出對應(yīng)的硬件處理
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'; //在收到的內(nèi)容后面加上字符串結(jié)束符
char strPayload[255] = {0};
strcpy(strPayload, (const char*)payload);
Serial.println((char *)payload); //打印出收到的內(nèi)容
Serial.println(strPayload);
/*request_id解析部分*///后文有詳細解釋為什么要提取下發(fā)命令的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);
/*將命令響應(yīng)topic與resquest_id結(jié)合起來*/
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();//對應(yīng)的硬件響應(yīng)函數(shù)
delay(5000);
ledcWrite(channel, calculatePWM(0));
}if (paras_doorOpen == 0)
{
closeDoor();
}
MQTT_response(topicRes);//發(fā)送響應(yīng)參數(shù)
}
內(nèi)容根據(jù)具體需求修改
MQTT.fx
下載和詳細操作可以查看文檔,這里只做簡單使用
使用MQTT.fx調(diào)測
可以使用MQTT.fx工具查看下發(fā)命令對應(yīng)的JSON數(shù)據(jù)
點擊apply
通過iot控制臺 產(chǎn)品->選擇你的產(chǎn)品->命令->同步命令下發(fā)
即可通過MQTT.fx工具查看到下發(fā)命令的JSON數(shù)據(jù)
復(fù)制到ArduinoJSON官網(wǎng)解析數(shù)據(jù) ArduinoJson
選擇ESP32->反序列化->Stream
命令響應(yīng)
參考技術(shù)文檔 平臺命令下發(fā)
由于三個參數(shù)都是可選的,所以直接返回空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);
}
物理層面
使用舵機拉動門把手,延遲后歸為即可實現(xiàn)簡易的智能門禁系統(tǒng)
舵機控制
舵機是伺服電機的一種,伺服電機就是帶有反饋環(huán)節(jié)的電機,我們可以通過伺服電機進行精確的位置控制或者輸出較高的扭矩;
一般舵機的旋轉(zhuǎn)范圍是0°~ 180°。舵機是由可變寬度的脈沖控制。脈沖的參數(shù)有最小值、最大值和頻率。一般而言,舵機的基準信號周期為20ms,所以頻率為50kHz。脈沖寬度和舵機的轉(zhuǎn)角0°~ 180°相對應(yīng)的。
這里使用的是180°舵機MG995,如果門把手很難拉動,需要更換扭矩更大的舵機。
PWM信號線可以連接GPIO口上,具體可查看ESP32手冊,這里接的是16IO口
代碼如下
int freq = 50; // 頻率(20ms周期)
int channel = 8; // 通道(高速通道(0 ~ 7)由80MHz時鐘驅(qū)動,低速通道(8 ~ 15)由 1MHz 時鐘驅(qū)動。)
int resolution = 8; // 分辨率
const int led = 16;
int calculatePWM(int degree)
{ //0-180度
//20ms周期,高電平0.5-2.5ms,對應(yīng)0-180度角度
const float deadZone = 6.4;//對應(yīng)0.5ms(0.5ms/(20ms/256)) 舵機轉(zhuǎn)動角度與占空比的關(guān)系:(角度/90+0.5)*1023/20
const float max = 32;//對應(yīng)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函數(shù)中增加硬件響應(yīng)函數(shù),這里是對平臺下發(fā)的doorOpen做判斷
if(paras_doorOpen == 1)
{
openDoor();//對應(yīng)的硬件響應(yīng)函數(shù)
delay(5000);
ledcWrite(channel, calculatePWM(0));
}else if (paras_doorOpen == 0)
{
closeDoor();
}
應(yīng)用側(cè)
使用http請求調(diào)用API實現(xiàn)應(yīng)用側(cè)的開發(fā)
微信小程序
新建小程序
不使用云服務(wù)->JavaScript
刪除模板文件pages->新建一個page->輸入名稱->回車自動生成4個配置文件
獲取Token
Token在計算機系統(tǒng)中代表令牌(臨時)的意思,擁有Token就代表擁有某種權(quán)限。Token認證就是在調(diào)用API的時候?qū)oken加到請求消息頭,從而通過身份認證,獲得操作API的權(quán)限。
詳情可查看文檔 認證鑒權(quán)
wx.request方法
wx.request({
url: '',
data:'',
method: '', // OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT
header: {}, // 設(shè)置請求的 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: {}, // 設(shè)置請求的 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'}, // 設(shè)置請求的 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調(diào)試
獲取IAM用戶Token(使用密碼)
設(shè)置好參數(shù)->點擊調(diào)試->可以看到響應(yīng)頭的Token
傳出Token
settoken:function(_token){
this.data.token=_token;
wx.setStorageSync('token', _token);//將Token保存到緩存中
console.log('外部獲取到token:'+this.data.token);
this.setData({result:"token認證成功"});
},
命令下發(fā)
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("失敗");
},
})
},
//關(guān)門
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("失敗");
},
})
},
頁面設(shè)計
為界面添加兩個按鈕
設(shè)置相應(yīng)的響應(yīng)函數(shù)文章來源:http://www.zghlxwxcb.cn/news/detail-425739.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-425739.html
到了這里,關(guān)于詳細!基于ESP32的智能門禁系統(tǒng)(華為云iot+微信小程序)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!