ESP32對接巴法云實現配網

目錄

    • 序言
    • 準備工作
      • 巴法云注冊與使用
      • Arduino準備
    • 開發
    • 開始配網

序言

本文部分內容摘抄原創作者巴法云-做優秀的物聯網平臺
代碼有部分修改并測試運行正常

巴法云支持免費用戶通過開發對接實現各智能音箱設備語音控制智能家居設備,并有自己的App進行配網和控制,在開發過程中省去了很多工作,推薦大家使用

巴法云關于個人開發者使用描述

準備工作

巴法云注冊與使用

巴法云開發者文檔
進入巴法云
下載App
首先需要在巴法云注冊用戶。
注冊完成之后下載App并登錄
至此巴法云準備工作就完成啦

Arduino準備

本次開發基于Arduino
請移步ESP32入門之arduino IDE環境搭建 1
或轉載

開發

以下是實現的具體配網流程代碼

//需要在arduino IDE軟件中---工具-->管理庫-->搜索arduinojson并安裝
#include <WiFi.h>
#include <WiFiUDP.h>
#include <ArduinoJson.h>
#include <EEPROM.h>
#include <Ticker.h>
#include <HTTPClient.h>//根據需要修改的信息
String aptype = "009";   //設備類型,001插座設備,002燈類設備,003風扇設備,005空調,006開關,009窗簾
String Name = "窗簾";    //設備昵稱,可隨意修改
String verSion = "3.1";  //3是tcp設備端口8344,1是MQTT設備
String room = "臥室";    //房間。例如客廳、臥室等,默認空
int protoType = 3;       //3是tcp設備端口8344,1是MQTT設備
int adminID = 0;         //默認空即可。企業id,建議企業用戶配置,該設備會自動綁定到該企業下,獲取id方法見接入文檔5.17節
WiFiClient client_bemfa_WiFiClient;
HTTPClient http_bemfa_HTTPClient;//檢測是否是第一次連接WIFI
bool firstWIfiConfig = false;
String topic = "";
struct config_type {char stassid[32];char stapsw[16];char cuid[40];char ctopic[32];uint8_t reboot;uint8_t magic;
};
config_type config;char config_flag = 0;      //判斷是否配網
#define MAGIC_NUMBER 0xAA  //判斷是否配網
char packetBuffer[255];    //發送數據包
WiFiUDP Udp;/** 從EEPROM加載參數
*/
uint8_t* p = (uint8_t*)(&config);
void loadConfig() {uint8_t mac[6];Serial.println(" LoadConfig.......");WiFi.macAddress(mac);EEPROM.begin(512);for (int i = 0; i < sizeof(config); i++) {*(p + i) = EEPROM.read(i);}config.reboot = config.reboot + 1;if (config.reboot >= 4) {restoreFactory();}if (config.magic != 0xAA) {config_flag = 1;}EEPROM.begin(512);for (int i = 0; i < sizeof(config); i++) {EEPROM.write(i, *(p + i));}EEPROM.commit();delay(2000);Serial.println("loadConfig Over");EEPROM.begin(512);config.reboot = 0;for (int i = 0; i < sizeof(config); i++) {EEPROM.write(i, *(p + i));}EEPROM.commit();
}/* * 恢復出廠設置
*/
void restoreFactory() {Serial.println("\r\n Restore Factory....... ");config.magic = 0x00;strcpy(config.stassid, "");strcpy(config.stapsw, "");strcpy(config.cuid, "");strcpy(config.ctopic, "");config.magic = 0x00;saveConfig();delayRestart(1);
}
/*
保存WIFI信息
*/
void saveConfig() {config.reboot = 0;EEPROM.begin(512);  // 與loadConfig統一為512字節(足夠存儲config結構體)uint8_t* p = (uint8_t*)(&config);for (int i = 0; i < sizeof(config); i++) {EEPROM.write(i, *(p + i));}EEPROM.commit();
}
Ticker delayTimer;
void delayRestart(float t) {delayTimer.attach(t, []() {ESP.restart();});
}
void apConfig(String mac) {if (config_flag == 1) {WiFi.softAP("bemfa_" + mac);Udp.begin(8266);Serial.println("Started Ap Config...");}topic = mac + aptype;// Removed blocking while loop
}/*第一次配網檢查WIFI,保存WIFI配置信息,并創建主題
*/
void checkFirstConfig() {if (firstWIfiConfig) {// 設置目標 URLhttp_bemfa_HTTPClient.begin(client_bemfa_WiFiClient, "http://pro.bemfa.com/vs/web/v1/deviceAddTopic");// 創建 JSON 對象StaticJsonDocument<200> jsonDoc;jsonDoc["uid"] = config.cuid;jsonDoc["name"] = Name;jsonDoc["topic"] = topic;jsonDoc["type"] = protoType;jsonDoc["room"] = room;jsonDoc["adminID"] = adminID;jsonDoc["wifiConfig"] = 1;  //必填字段// 將 JSON 對象轉換為字符串String jsonString;serializeJson(jsonDoc, jsonString);http_bemfa_HTTPClient.addHeader("Content-Type", "application/json; charset=UTF-8");// 發送請求int httpCode = http_bemfa_HTTPClient.POST(jsonString);if (httpCode == 200) {Serial.println("POST succeeded with code:");Serial.println(httpCode);String payload = http_bemfa_HTTPClient.getString();Serial.println(payload);//json數據解析StaticJsonDocument<200> doc;DeserializationError error = deserializeJson(doc, payload);if (error) {Serial.print(F("deserializeJson() failed: "));Serial.println(error.c_str());}int code = doc["code"];if (code == 0) {int resCode = doc["data"]["code"];if (resCode == 40006 || resCode == 0) {String docUID = doc["uid"];Serial.print("create topic ok:");Serial.println(topic);if (firstWIfiConfig) {config.reboot = 0;config.magic = 0xAA;saveConfig();}} else {Serial.println(" config ERROR.........");}} else {Serial.println(" config ERROR.........");}} else if (httpCode != 200) {Serial.println("POST failed with code:");Serial.println(httpCode);} else {Serial.println("Unknown error");}http_bemfa_HTTPClient.end();}
}// 復位或上電后運行一次:
void setup() {//在這里加入初始化相關代碼,只運行一次:Serial.begin(115200);String mac = WiFi.macAddress();mac.replace(":", "");                            //去掉:號topic = mac.substring(8) + aptype; //取mac地址的后半部分做主題用,并拼接設備類型// 初始化WiFi模式以確保MAC地址正確獲取(關鍵修改)WiFi.mode(WIFI_STA);  // 設置為STA模式初始化硬件delay(1000);           // 等待WiFi模塊初始化完成// 初始化配網(此時可正確獲取MAC地址)mac = WiFi.macAddress();mac.replace(":", "");loadConfig();                                      //加載存儲的數據apConfig(mac);                                   //加載ap// Only try to connect to WiFi if not in config modeif (config_flag == 0) {Serial.println("Connecting to WiFi...");WiFi.disconnect();                          //斷開連接WiFi.mode(WIFI_STA);                        //STA模式WiFi.begin(config.stassid, config.stapsw);  //連接路由器// Removed blocking while loop here}
}//一直循環執行:
void loop() {if (config_flag == 1) { // If in config mode, handle UDP packetsint packetSize = Udp.parsePacket();if (packetSize) {Serial.print("Received packet of size ");Serial.println(packetSize);Serial.print("From ");IPAddress remoteIp = Udp.remoteIP();Serial.print(remoteIp);Serial.print(", port ");Serial.println(Udp.remotePort());int len = Udp.read(packetBuffer, 255);if (len > 0) {packetBuffer[len] = 0;}Serial.println("Contents:");Serial.println(packetBuffer);StaticJsonDocument<200> doc;DeserializationError error = deserializeJson(doc, packetBuffer);if (error) {Serial.print(F("deserializeJson() failed: "));Serial.println(error.f_str());return;}int cmdType = doc["cmdType"].as<int>();if (cmdType == 1) {const char* ssid = doc["ssid"];const char* password = doc["password"];const char* token = doc["token"];strcpy(config.stassid, ssid);strcpy(config.stapsw, password);strcpy(config.cuid, token);//收到信息,并回復String ReplyBuffer = "{\"cmdType\":2,\"productId\":\"" + topic + "\",\"deviceName\":\"" + Name + "\",\"protoVersion\":\"" + verSion + "\"}";const char* replyBufferData = ReplyBuffer.c_str();size_t replyBufferLength = ReplyBuffer.length();Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());Udp.write((const uint8_t*)replyBufferData, replyBufferLength);Udp.endPacket();} else if (cmdType == 3) {config_flag = 0;firstWIfiConfig = true;// 徹底停止UDP并清理網絡資源Udp.stop();WiFi.disconnect(true);  // 強制斷開所有連接(包括AP和STA)WiFi.mode(WIFI_OFF);    // 關閉所有WiFi模式delay(1500);            // 延長等待時間確保硬件完成釋放// 切換為STA模式并連接WiFi(添加連接前的參數校驗)Serial.println("Connecting to WiFi after provisioning...");if (strlen(config.stassid) == 0 || strlen(config.stapsw) == 0) {Serial.println("Error: SSID or password is empty");return;}WiFi.mode(WIFI_STA);WiFi.begin(config.stassid, config.stapsw);// 等待連接結果(設置超時避免永久阻塞)unsigned long start = millis();while (WiFi.status() != WL_CONNECTED && (millis() - start) < 15000) {delay(100);}if (WiFi.status() == WL_CONNECTED) {Serial.printf("Connected to %s, IP: %s\n", config.stassid, WiFi.localIP().toString().c_str());checkFirstConfig();} else {Serial.println("WiFi connection failed (timeout)");}}}} else { // If not in config mode, run normal operation// Your normal device operation code goes here// Serial.println("Config success"); // This will print repeatedly, move to setup or only print once// Removed delay(1000)}
}

代碼中的aptype與Name變量將是你在配往后自動添加的設備類型與名稱
代碼中的protoType參數將會控制您在巴法云建立MQTT主題還是TCP主題,根據智能家居類型自行配置
自行燒錄哦,如不會燒錄請查詢官方文檔

開始配網

第一次開機后硬件會檢查是否已配置網絡,沒有配置將會打開WiFi熱點,名稱為bemfa_mac地址

  1. 連接ESP32需要連接的WiFi不是ESP32的WiFi哦
  2. 打開巴法App-右上角+號或微信小程序搜索巴法,找到一鍵配網小程序
  3. 進入配網頁面,切換協議為AP配網,小程序為Soft AP 配網
  4. WiFi名稱會自動填寫你當前連接的WiFi,輸入WiFi密碼,點擊開始配網
  5. 此時會提示您連接到設備WiFi,點擊打開設置,在WiFi界面連接bemfa開頭的WiFi
  6. 回到App或小程序,此時將開始配網流程,硬件接收到信息后開始連接目標WiFi
  7. 連接成功后會在用戶的巴法云控制臺建立硬件主題,主題一般為:硬件mac地址+設備類型
  8. App或小程序檢測到主題創建成功,代表配網結束,在App中就可以看到該設備啦

至此,配網功能結束
當然,該文章僅為使用巴法云方式實現配網功能,開發者也可以通過代碼邏輯,來建立自己的MQTT服務,進行自己的個人后端開發,實現家庭智能


  1. ESP32-C6接入巴法云,Arduino方式 ??

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/83744.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/83744.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/83744.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

深度學習習題3

1.訓練神經網絡過程中&#xff0c;損失函數在一些時期&#xff08;Epoch&#xff09;不再減小, 原因可能是&#xff1a; 1.學習率太低 2.正則參數太大 3.卡在了局部最小值 A1 and 2 B. 2 and 3 C. 1 and 3 D. 都是 2.對于分類任務&#xff0c;我們不是將神經網絡中的隨機權重…

【EasyExcel】導出時添加頁眉頁腳

一、需求 使用 EasyExcel 導出時添加頁眉頁腳 二、添加頁眉頁腳的方法 通過配置WriteSheet或WriteTable對象來添加頁眉和頁腳。以下是具體實現步驟&#xff1a; 1. 創建自定義頁眉頁腳實現類 public class CustomFooterHandler implements SheetWriteHandler {private final…

c++ 類型轉換函數

測試代碼&#xff1a; void testTypeTransfer() { // 測試類型轉換函數class Distance {private:int meters;public:// 類型轉換函數&#xff0c;int表示轉化為int類型operator int() {std::cout << "調用了類型轉換函數" << endl;return meters; }Dist…

Conda 基本使用命令大全

Conda 基本使用命令大全 Conda 是一個開源的包管理和環境管理系統&#xff0c;廣泛用于 Python 開發、數據科學和機器學習。以下是 最常用的 Conda 命令&#xff0c;涵蓋環境管理、包安裝、配置等核心操作。 1. 環境管理 創建環境 conda create --name myenv # 創…

基于SpringBoot和PostGIS的OSM時空路網數據入庫實踐

目錄 前言 一、空間表的設計 1、屬性信息 2、空間表結構設計 二、路網數據入庫 1、實體類設計 2、路網數據寫入 3、pgAdmin數據查詢 三、總結 前言 在當今數字化時代&#xff0c;隨著信息技術的飛速發展&#xff0c;地理空間數據的應用范圍越來越廣泛&#xff0c;尤其是…

代付入賬是什么意思?怎么操作?

代付入賬就是指商戶委托銀行通過企業銀行賬戶向指定持卡人賬戶劃付款項&#xff0c;款項劃入指定賬戶即為入賬。 具體操作流程如下&#xff1a; 1. 向第三方支付公司指定賬戶充值加款。 2. 通過操作后臺提交代付銀行卡信息。 3. 第三方支付公司受理業務申請。 4. 第三方審…

數學復習筆記 27

前言 太難受了。因為一些事情。和朋友傾訴了一下&#xff0c;也沒啥用&#xff0c;幾年之后不知道自己再想到的時候&#xff0c;會怎么考慮呢。另外&#xff0c;筆記還是有框架一點比較好&#xff0c;這樣比較有邏輯感受。不然太亂了。這篇筆記是關于線代第五章&#xff0c;特…

第四十五天打卡

知識點回顧&#xff1a; tensorboard的發展歷史和原理 tensorboard的常見操作 tensorboard在cifar上的實戰&#xff1a;MLP和CNN模型 效果展示如下&#xff0c;很適合拿去組會匯報撐頁數&#xff1a; 作業&#xff1a;對resnet18在cifar10上采用微調策略下&#xff0c;用tensor…

使用高斯樸素貝葉斯算法對鳶尾花數據集進行分類

高斯樸素貝葉斯算法通常用于特征變量是連續變量&#xff0c;符合高素分布的情況。 使用高斯樸素貝葉斯算法對鳶尾花數據集進行分類 """ 使用高斯貝葉斯堆鳶尾花進行分類 """ #導入需要的庫 from sklearn.datasets import load_iris from skle…

【docker】Windows安裝docker

環境及工具&#xff08;點擊下載&#xff09; Docker Desktop Installer.exe &#xff08;windows 環境下運行docker的一款產品&#xff09; wsl_update_x64 &#xff08;Linux 內核包&#xff09; 前期準備 系統要求2&#xff1a; Windows 11&#xff1a;64 位系統&am…

量化Quantization初步之--帶量化(QAT)的XOR異或pyTorch版250501

量化(Quantization)這詞兒聽著玄&#xff0c;經常和量化交易Quantitative Trading (量化交易)混淆。 其實機器學習(深度學習)領域的量化Quantization是和節約內存、提高運算效率相關的概念&#xff08;因大模型的普及&#xff0c;這個量化問題尤為迫切&#xff09;。 揭秘機器…

【Redis】zset 類型

zset 一. zset 類型介紹二. zset 命令zaddzcard、zcountzrange、zrevrange、zrangebyscorezpopmax、zpopminzrank、zrevrank、zscorezrem、zremrangebyrank、zremrangebyscorezincrby阻塞版本命令&#xff1a;bzpopmax、bzpopmin集合間操作&#xff1a;zinterstore、zunionstor…

Mermaid 繪圖--以企業權限視圖為例

文章目錄 一、示例代碼二、基礎結構設計2.1 組織架構樹2.2 權限視圖設計 三、銷售數據權限系統四、關鍵語法技巧匯總 一、示例代碼 在企業管理系統開發中&#xff0c;清晰的權限視圖設計至關重要。本文將分享如何使用 Mermaid 繪制直觀的企業權限關系圖&#xff0c;復制以下代…

[pdf、epub]300道《軟件方法》強化自測題業務建模需求分析共257頁(202505更新)

DDD領域驅動設計批評文集 做強化自測題獲得“軟件方法建模師”稱號 《軟件方法》各章合集 在本賬號CSDN資源下載&#xff0c;或者訪問鏈接&#xff1a; http://www.umlchina.com/url/quizad.html 如果需要提取碼&#xff1a;umlc 文件夾中的“300道軟件方法強化自測題2025…

std__map,std__unordered_map,protobuf__map之間的性能比較

簡單比較下 std::map、std::unordered_map 和 protobuf::Map 的性能&#xff0c;主要關注在 插入、查找 和 刪除 操作上的效率以及內存管理的差異。 std::map 底層實現&#xff1a;std::map 使用紅黑樹作為底層數據結構&#xff0c;紅黑樹是一種平衡二叉查找樹的變體結構&…

文檔處理組件Aspose.Words 25.5全新發布 :六大新功能與性能深度優化

在數字化辦公日益普及的今天&#xff0c;文檔處理的效率與質量直接影響到企業的運營效率。Aspose.Words 作為業界領先的文檔處理控件&#xff0c;其最新發布的 25.5 版本帶來了六大新功能和多項性能優化&#xff0c;旨在為開發者和企業用戶提供更強大、高效的文檔處理能力。 六…

Three.js + Vue3 加載GLB模型項目代碼詳解

本說明結合 src/App.vue 代碼,詳細解釋如何在 Vue3 項目中用 three.js 加載并顯示 glb 模型。 1. 依賴與插件導入 import {onMounted, onUnmounted } from vue import * as THREE from three import Stats from stats.js import {OrbitControls } from three/examples/jsm/co…

Flutter如何支持原生View

在 Flutter 中集成原生 View&#xff08;如 Android 的 SurfaceView、iOS 的 WKWebView&#xff09;是通過 平臺視圖&#xff08;Platform View&#xff09; 實現的。這一機制允許在 Flutter UI 中嵌入原生組件&#xff0c;解決了某些場景下 Flutter 自身渲染能力的不足&#x…

vue-11(命名路由和命名視圖)

命名路由和命名視圖 命名路由和命名視圖提供了組織和導航 Vue.js 應用程序的強大方法&#xff0c;尤其是在它們的復雜性增加時。它們提供了一種語義更合理、可維護的路由方法&#xff0c;使您的代碼更易于理解和修改。命名路由允許您按名稱引用路由&#xff0c;而不是依賴 URL…

微軟認證考試科目眾多?該如何選擇?

在云計算、人工智能、數據分析等技術快速發展的今天&#xff0c;微軟認證&#xff08;Microsoft Certification&#xff09;已成為IT從業者、開發者、數據分析師提升競爭力的重要憑證。但面對眾多考試科目&#xff0c;很多人不知道如何選擇。本文將詳細介紹微軟認證的考試方向、…