在過(guò)去的幾年中,物聯(lián)網(wǎng) (IoT) 呈指數(shù)級(jí)增長(zhǎng)。國(guó)際數(shù)據(jù)公司 (IDC) 的一項(xiàng)新研究估計(jì),到 2025 年,將有近 420 億臺(tái)聯(lián)網(wǎng)設(shè)備,產(chǎn)生超過(guò) 80 澤字節(jié) (ZB) 的數(shù)據(jù)。隨著物聯(lián)網(wǎng)設(shè)備數(shù)量的增長(zhǎng);數(shù)據(jù)量的增長(zhǎng),隨之而來(lái)的是對(duì)高級(jí)網(wǎng)絡(luò)儀器的需求;可以支持這個(gè)負(fù)載。
但是,如果我們考慮一個(gè)通用主機(jī)(如通用路由器),它可以連接到有限數(shù)量的節(jié)點(diǎn),準(zhǔn)確地說(shuō)少于 32 個(gè)。隨著越來(lái)越多的物聯(lián)網(wǎng)設(shè)備可能出現(xiàn)在我們的家庭或行業(yè)中,這還不夠。目前,這個(gè)問(wèn)題有兩種解決方案:第一種是使用Mesh 路由器,與通用路由器相比,它可以處理更多的連接,或者我們可以使用稱為Mesh Network的網(wǎng)絡(luò)協(xié)議。
因此,在本文中,我們將制作一個(gè)簡(jiǎn)單的ESP Mesh 網(wǎng)絡(luò)設(shè)置,它由四個(gè) ESP 設(shè)備組成,它們將在Wi-Fi Mesh 網(wǎng)絡(luò)的幫助下相互通信。最后,我們要將單個(gè) ESP 連接到我們的筆記本電腦,以便從網(wǎng)絡(luò)上的所有四個(gè)傳感器獲取數(shù)據(jù)。請(qǐng)注意,我們將在本教程中同時(shí)使用 ESP32 和 ESP8266 板,以便您可以 使用相同的方法創(chuàng)建ESP8266 Mesh 網(wǎng)絡(luò)或ESP32 Mesh 網(wǎng)絡(luò)。
什么是 ESP-MESH 及其工作原理?
根據(jù) ESP-MESH 的官方文檔,它是一個(gè)自組織和自愈網(wǎng)絡(luò),意味著網(wǎng)絡(luò)可以自主構(gòu)建和維護(hù)。
網(wǎng)狀網(wǎng)絡(luò)是網(wǎng)絡(luò)上的一組連接設(shè)備,它們充當(dāng)單個(gè)網(wǎng)絡(luò)。ESP-Mesh與傳統(tǒng)的網(wǎng)格設(shè)置完全不同。在 ESP-Mesh 中,節(jié)點(diǎn)或單個(gè)設(shè)備可以同時(shí)連接到其鄰居。一個(gè)節(jié)點(diǎn)可以連接到多個(gè)節(jié)點(diǎn),它們可以將數(shù)據(jù)從一個(gè)節(jié)點(diǎn)中繼到另一個(gè)節(jié)點(diǎn)。這個(gè)過(guò)程不僅高效,而且是多余的。如果任何一個(gè)節(jié)點(diǎn)發(fā)生故障;來(lái)自其他節(jié)點(diǎn)的數(shù)據(jù)可以毫無(wú)問(wèn)題地到達(dá)目的地。這也開(kāi)啟了在不需要中央節(jié)點(diǎn)的情況下實(shí)現(xiàn)互連的可能性,從而顯著擴(kuò)展了網(wǎng)狀網(wǎng)絡(luò)的覆蓋范圍。有了這些特性,這個(gè)網(wǎng)絡(luò)就不太容易合并,因?yàn)榫W(wǎng)絡(luò)中的節(jié)點(diǎn)總數(shù)不受單個(gè)中心節(jié)點(diǎn)的限制。
為了簡(jiǎn)單起見(jiàn),我們決定使用四個(gè) ESP 模塊;但是如果你正在構(gòu)建這個(gè)網(wǎng)絡(luò),你可以使用盡可能多的 ESP 設(shè)備。為了構(gòu)建網(wǎng)狀網(wǎng)絡(luò),我們將使用 Arduino 的painlessMesh 庫(kù),它支持ESP8266和ESP32模塊。
使用 ESP 構(gòu)建 Mesh 網(wǎng)絡(luò)所需的組件
該項(xiàng)目所需的組件列表如下。為了構(gòu)建這個(gè)項(xiàng)目,我使用了非常通用的組件,您可以在當(dāng)?shù)氐膼?ài)好商店中找到它們。
NodeMCU(ESP8266) - 2
ESP32 開(kāi)發(fā)板 - 2
BMP280 傳感器 - 2
DHT22 傳感器 - 1
DS18B20 傳感器 - 1
面包板
USB 數(shù)據(jù)線(用于電源和數(shù)據(jù))
ESP Wi-Fi Mesh - 電路圖
下圖用于構(gòu)建基于 ESP8266 和 ESP32 的 Wi-Fi Mesh 網(wǎng)絡(luò)的硬件部分。
對(duì)于這個(gè)電路,我們將兩個(gè)BME280 傳感器連接到ESP32 板,我們將 DHT22 傳感器連接到其中一個(gè)ESP8266 板,并將 DS18B20 傳感器連接到另一個(gè) ESP8266 板。我們之前曾在不同的項(xiàng)目中單獨(dú)使用過(guò)所有這些傳感器。在這里,我們將在不同的 NodeMCU/ESP32 板上使用它們,然后通過(guò)ESP Mesh 網(wǎng)絡(luò)將它們?nèi)窟B接起來(lái)。硬件設(shè)置的圖像如下所示。
為網(wǎng)狀網(wǎng)絡(luò)編程 ESP8266 和 ESP32
在本文中,我們將使用 Arduino IDE 對(duì) ESP32 和 ESP8266 板進(jìn)行編程。在這里,我們將使用Painless Mesh 庫(kù)來(lái)構(gòu)建我們的網(wǎng)格網(wǎng)絡(luò)。要安裝庫(kù),請(qǐng)轉(zhuǎn)到Sketch-》Include Library-》Manage Libraries并搜索painlessMesh。完成后,只需單擊安裝,該庫(kù)將安裝在 Arduino IDE 中。如下圖所示,單擊安裝后,該庫(kù)會(huì)要求您安裝其他依賴項(xiàng)。您需要安裝它們才能使庫(kù)正常工作。
正如您在硬件部分已經(jīng)知道的那樣,我們將使用一個(gè) DS18B20 傳感器、一個(gè) DHT22 傳感器和兩個(gè) BME 280 傳感器。我們需要安裝所有這些,并且可以使用板管理器方法簡(jiǎn)單地完成。
您也可以從下面給出的鏈接下載這些庫(kù)。一旦我們下載并安裝了所有必需的庫(kù),我們就可以繼續(xù)創(chuàng)建我們的代碼。
注意:您接下來(lái)看到的代碼解釋是所有四個(gè)板中使用的代碼。我們?cè)O(shè)計(jì)了代碼,以便我們可以稍微調(diào)整一下,我們可以將它上傳到我們的任何 ESP 板上,盡管它是 ESP32 或 ESP8266 板。
將代碼上傳到連接了 BME280 傳感器的 ESP32 開(kāi)發(fā)板:
正如您在硬件示意圖中看到的,我們已經(jīng)連接了一個(gè) BME280 傳感器。為此,您需要取消注釋BME_280傳感器的宏并為其指定一個(gè)唯一的節(jié)點(diǎn)名稱。在我們的例子中,我們將Node_1和Node_2用于我們連接 BME280 傳感器的兩個(gè) ESP32 板
?
#define BME_280 //#定義DHT22 //#定義DS18B20 //#define ENABLE_LOG 字符串節(jié)點(diǎn)名 = "NODE_1";
?
將代碼上傳到連接了 DHT 傳感器的 ESP8266 開(kāi)發(fā)板:
在我們的一個(gè) ESP8266 板上,我們有一個(gè) DHT22 傳感器,在另一個(gè)板上,我們有一個(gè) DS18B20 傳感器。要將代碼上傳到 DHT22 板,我們必須遵循相同的過(guò)程。首先,我們?nèi)∠⑨?DHT22 的宏,然后注釋掉 BME280 的宏,并將代碼上傳到我們連接了 DHT 22 傳感器的板上。
?
//#define BME_280 #定義DHT22 //#定義DS18B20 //#define ENABLE_LOG 字符串節(jié)點(diǎn)名 = "NODE_3";
?
將代碼上傳到連接了 DS18B20 傳感器的 ESP8266 開(kāi)發(fā)板:
該電路板的過(guò)程也完全相同。我們?nèi)∠⑨?DS18B20 傳感器的宏,并對(duì)其他宏進(jìn)行注釋。
?
//#define BME_280 //#定義DHT22 #define DS18B20 //#define ENABLE_LOG 字符串節(jié)點(diǎn)名 = "NODE_3";
?
最后,要啟用或禁用其他日志語(yǔ)句,您可以取消注釋 ENABLE_LOG 宏?,F(xiàn)在我們已經(jīng)了解了代碼的工作原理,我們可以進(jìn)一步解釋代碼。
我們將通過(guò)包含 painlessMesh 庫(kù)和 Arduino_JSON 庫(kù)來(lái)開(kāi)始我們的代碼。?
?
#include#include
?
接下來(lái),我們定義一些宏,我們將使用它們來(lái)啟用或禁用我們的代碼部分。這是必需的,因?yàn)椴⒎撬泄?jié)點(diǎn)都使用相同的傳感器類型和。因此,為了包含或排除部分代碼,我們可以將四個(gè)不同的代碼放入一個(gè)文件中。
?
//#define BME_280 #定義DHT22 //#定義DS18B20 //#define ENABLE_LOG
?
接下來(lái),我們定義一個(gè)String類型的變量nodeName。這將用于唯一標(biāo)識(shí)網(wǎng)絡(luò)中的節(jié)點(diǎn)。除此之外,我們還定義了浮點(diǎn)類型變量來(lái)存儲(chǔ)溫度、濕度和氣壓數(shù)據(jù)。
?
字符串節(jié)點(diǎn)名 = "NODE_4"; // 名稱需要唯一 浮動(dòng)溫度(NAN),嗡嗡聲(NAN),壓力(NAN);
?
從這一步開(kāi)始,我們將使用#ifdef和#endif宏來(lái)包含或排除部分代碼。代碼的第一部分用于 BME280 傳感器。如前所述,我們將從#ifdef BME_280語(yǔ)句開(kāi)始。接下來(lái),我們?yōu)?BME280 傳感器定義所有必需的庫(kù)。BME 傳感器也使用線庫(kù),所以我們也定義了它。接下來(lái),我們制作一個(gè)BME280I2C對(duì)象bme。接下來(lái),使用范圍解析運(yùn)算符,我們?cè)L問(wèn)類的變量,并使用 endif 語(yǔ)句完成它。
?
#ifdef BME_280 #include#include BME280I2C bme; BME280::TempUnit tempUnit(BME280::TempUnit_Celsius); BME280::PresUnit presUnit(BME280::PresUnit_Pa); #萬(wàn)一
?
我們也對(duì) DHT 庫(kù)做同樣的事情。我們從#ifdef DHT22語(yǔ)句開(kāi)始,然后包含DHT.h庫(kù)。接下來(lái),我們?yōu)?DHT 定義 PIN,并為 DHT22 添加一個(gè)原型。此后,我們通過(guò)傳遞上述定義的語(yǔ)句來(lái)創(chuàng)建一個(gè)對(duì)象。我們以#endif語(yǔ)句結(jié)束。?
?
#ifdef DHT22 #include "DHT.h" #define DHTPIN 4 #define DHTTYPE DHT22 DHT dht(DHTPIN, DHTTYPE); #萬(wàn)一
?
我們也為 DS18B20 傳感器做同樣的事情。我們從#ifdef DS18B20語(yǔ)句開(kāi)始。
由于 DS18B20 傳感器需要OneWire庫(kù),我們將其與DallasTemperature庫(kù)一起提供。接下來(lái),我們?yōu)閭鞲衅鞫x引腳并通過(guò)傳遞引腳變量創(chuàng)建一個(gè) OneWire 對(duì)象。接下來(lái),我們通過(guò)創(chuàng)建一個(gè)新的 DallasTemperature 對(duì)象將 OneWire 對(duì)象的地址傳遞給 DallasTemperature 對(duì)象。
?
#ifdef DS18B20 #include#include <達(dá)拉斯溫度.h> 常量 int oneWireBus = 4; 單線單線(oneWireBus); DallasTemperature ds18b20(&oneWire); #萬(wàn)一
?
接下來(lái),我們定義 Wi-Fi 憑據(jù)以及端口號(hào)。對(duì)于網(wǎng)絡(luò)中的所有節(jié)點(diǎn),此憑據(jù)和端口號(hào)應(yīng)保持不變。
?
#define MESH_PREFIX "whateverYouLike" #define MESH_PASSWORD "somethingSneaky" #define MESH_PORT 5555
?
接下來(lái),我們制作三個(gè)實(shí)例。一個(gè)用于調(diào)度器,另一個(gè)用于painlessMesh,最后一個(gè)用于 JSON 庫(kù)JSONVar
?
調(diào)度器用戶調(diào)度器;// 控制你的任務(wù) 無(wú)痛網(wǎng)眼; JSONVar myVar;
?
接下來(lái),我們創(chuàng)建了一個(gè)任務(wù),它就像一個(gè)線程,總是在一段時(shí)間后運(yùn)行并調(diào)用一個(gè)函數(shù)。下面定義的任務(wù)將用于向所有節(jié)點(diǎn)發(fā)送廣播消息。該任務(wù)立即采用三個(gè)參數(shù)。第一個(gè)定義任務(wù)調(diào)用函數(shù)的頻率,接下來(lái),它要求任務(wù)的生命周期,最后,它需要一個(gè)指向調(diào)用函數(shù)的指針。
?
任務(wù)taskSendMessage(TASK_SECOND * 1, TASK_FOREVER, &sendMessage);
?
接下來(lái),我們有調(diào)用函數(shù)sendMessage()。此函數(shù)調(diào)用另一個(gè)返回 JSON 字符串的函數(shù)。顧名思義,sendMessage 任務(wù)用于向所有節(jié)點(diǎn)發(fā)送消息。
?
無(wú)效發(fā)送消息(){ 字符串味精 = construnct_json(); 網(wǎng)格.sendBroadcast(味精); taskSendMessage.setInterval(隨機(jī)(TASK_SECOND * 1, TASK_SECOND * 5)); }
?
接下來(lái),我們有我們的receivedCallback()函數(shù)。每當(dāng)有新消息到達(dá)時(shí),此函數(shù)就會(huì)被調(diào)用。如果你想對(duì)收到的消息做些什么,你需要調(diào)整這個(gè)函數(shù)來(lái)完成你的工作。這個(gè)函數(shù)有兩個(gè)參數(shù)——節(jié)點(diǎn)id和作為指針的消息。
?
無(wú)效接收回調(diào)(uint32_t來(lái)自,字符串&msg){ Serial.printf("startHere: 接收自 %u msg=%s\n", from, msg.c_str()); }
?
接下來(lái),我們有我們的newConnectionCallback(?) 函數(shù)。每當(dāng)有新設(shè)備添加到網(wǎng)絡(luò)時(shí),此函數(shù)都會(huì)調(diào)用,并將打印語(yǔ)句發(fā)送到串行監(jiān)視器。
?
無(wú)效新連接回調(diào)(uint32_t nodeId){ Serial.printf("--> startHere: 新連接, nodeId = %u\n", nodeId); }
?
接下來(lái),我們有我們的nodeTimeAdjustedCallback()。此回調(diào)函數(shù)負(fù)責(zé)無(wú)痛網(wǎng)格所需的所有時(shí)間必需品。
?
無(wú)效節(jié)點(diǎn)時(shí)間調(diào)整回調(diào)(int32_t 偏移量){ Serial.printf("調(diào)整時(shí)間 %u.Offset = %d\n", mesh.getNodeTime(), offset); }
?
接下來(lái),我們有我們的setup()函數(shù)。在設(shè)置中,我們初始化串口并打印節(jié)點(diǎn)名稱。這很有幫助,因?yàn)橐坏?duì)所有節(jié)點(diǎn)進(jìn)行了編程,我們就可以使用串行監(jiān)視器輕松識(shí)別節(jié)點(diǎn)。我們還有記錄任何 ERROR | 的網(wǎng)格對(duì)象的setDebugMsgTypes()類。啟動(dòng)消息。接下來(lái),我們通過(guò)將 SSID、密碼和端口號(hào)傳遞給init()函數(shù)來(lái)初始化網(wǎng)格。請(qǐng)記住,這些函數(shù)還需要指向調(diào)度程序的指針才能正常工作。
?
序列號(hào).開(kāi)始(115200); Serial.println(nodeName); 網(wǎng)格.setDebugMsgTypes(錯(cuò)誤|啟動(dòng));// 在 init() 之前設(shè)置,以便您可以看到啟動(dòng)消息 mesh.init(MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT);
?
現(xiàn)在,我們將初始化我們上面討論過(guò)的所有回調(diào)函數(shù)。每當(dāng)需要執(zhí)行某個(gè)任務(wù)時(shí),就會(huì)調(diào)用這些回調(diào)函數(shù)。
?
網(wǎng)格.onReceive(&receivedCallback); 網(wǎng)格.onNewConnection(&newConnectionCallback); 網(wǎng)格.onChangedConnections(&changedConnectionCallback); mesh.onNodeTimeAdjusted(&nodeTimeAdjustedCallback);
?
現(xiàn)在我們將任務(wù)添加到任務(wù)調(diào)度程序中,并在 taskSendMessage.enable() 方法的幫助下啟用它。當(dāng)它執(zhí)行時(shí),不同的任務(wù)開(kāi)始在后臺(tái)同時(shí)運(yùn)行。
?
userScheduler.addTask(taskSendMessage); taskSendMessage.enable();
?
接下來(lái),在設(shè)置部分,我們擁有所有必要的ifdef和endif宏,它們用于根據(jù)要求初始化不同的傳感器。首先,我們將配置 BME280 傳感器。下面的代碼初始化 BME280 傳感器并檢查傳感器的版本,因?yàn)?BME280 傳感器帶有許多不同的版本。
?
#ifdef BME_280 Wire.begin(); 而(!bme.begin()) { Serial.println("找不到 BME280 傳感器!"); 延遲(1000); } // bme.chipID(); // 已棄用。請(qǐng)參閱芯片模型()。 開(kāi)關(guān) (bme.chipModel()) { 案例 BME280::ChipModel_BME280: Serial.println("找到 BME280 傳感器!成功。"); 休息; 案例 BME280::ChipModel_BMP280: Serial.println("找到 BMP280 傳感器!沒(méi)有可用的濕度。"); 休息; 默認(rèn): Serial.println("發(fā)現(xiàn)未知傳感器!錯(cuò)誤!"); } #萬(wàn)一
?
最后,我們?cè)趇fdef和#endif方法的幫助下配置了 DHT22 和 DS18B20 傳感器。這標(biāo)志著setup()函數(shù)的結(jié)束。
?
#ifdef DHT22 Serial.println(F("DHTxx 開(kāi)始!")); dht.begin(); #萬(wàn)一 #ifdef DS18B20 ds18b20.begin(); Serial.println(F("DS18B20 開(kāi)始!")); #萬(wàn)一
?
接下來(lái),我們有我們的循環(huán)。在這段代碼中,循環(huán)?劑量沒(méi)有做太多,它只是在mesh.update()方法的幫助下更新網(wǎng)格。它負(fù)責(zé)所有任務(wù)。如果此更新方法不存在,這些任務(wù)將不起作用。
?
無(wú)效循環(huán)() { 網(wǎng)格。更新(); // construnct_json(); }
?
接下來(lái),我們有我們的最終功能。此函數(shù)構(gòu)造 JSON 字符串并將其返回給調(diào)用函數(shù)。在這個(gè)函數(shù)中,我們首先調(diào)用bme.read()方法,然后傳遞所有使用新值更新的預(yù)定義變量。接下來(lái),我們將壓力值除以 100,因?yàn)槲覀円獙⑵滢D(zhuǎn)換為毫巴。接下來(lái),我們定義 JSON 數(shù)組并放置傳感器名稱、節(jié)點(diǎn)名稱、溫度、壓力值,并使用JSON.stringify()函數(shù)返回值。最后,我們定義另一個(gè) ifdef 和 endif 宏來(lái)啟用或禁用日志參數(shù)。?
?
字符串 construnct_json() { #ifdef BME_280 bme.read(pres, temp, hum, tempUnit, presUnit); 壓力 = 壓力 / 100; myVar["傳感器類型"] = "BME280"; myVar["節(jié)點(diǎn)名稱"] = nodeName; myVar["Temperature"] = serialized(String(temp, 2)); myVar["pres"] = 序列化(String(pres, 2)); #ifdef ENABLE_LOG Serial.println(JSON.stringify(myVar)); #萬(wàn)一 返回 JSON.stringify(myVar); #萬(wàn)一
?
最后,我們對(duì) DHT22 和 DS18B20 傳感器代碼執(zhí)行相同的操作。
?
#ifdef DHT22 temp = dht.readTemperature(); 嗡嗡聲 = dht.readHumidity(); myVar["傳感器類型"] = "DHT22"; myVar["節(jié)點(diǎn)名稱"] = nodeName; myVar["Temperature"] = 序列化(String(temp)); myVar["濕度"] = 序列化(String(hum)); #ifdef ENABLE_LOG Serial.println(JSON.stringify(myVar)); #萬(wàn)一 返回 JSON.stringify(myVar); #萬(wàn)一 #ifdef DS18B20 ds18b20.requestTemperatures(); temp = ds18b20.getTempCByIndex(0); myVar["傳感器類型"] = "DS18B20"; myVar["節(jié)點(diǎn)名稱"] = nodeName; myVar["Temperature"] = 序列化(String(temp)); #ifdef ENABLE_LOG Serial.println(JSON.stringify(myVar)); #萬(wàn)一 返回 JSON.stringify(myVar); #萬(wàn)一 }
?
現(xiàn)在,隨著編碼過(guò)程的完成;我們注釋或取消注釋頂部定義的宏;根據(jù)我們要上傳的板。接下來(lái),我們給每個(gè)節(jié)點(diǎn)一個(gè)唯一的名稱,我們只需上傳代碼。如果一切正常,代碼將正確編譯和上傳,沒(méi)有任何錯(cuò)誤。
基于 ESP8266 和 ESP32 的網(wǎng)狀網(wǎng)絡(luò) - 測(cè)試
基于 esp8266 和 esp32 的網(wǎng)狀網(wǎng)絡(luò)的測(cè)試設(shè)置如下所示。如上圖所示,我已經(jīng)為所有 esp 模塊連接了電源,您還可以在筆記本電腦的屏幕上看到輸出數(shù)據(jù)。串行監(jiān)視器窗口的屏幕截圖如下所示。
在上面的窗口中,您可以看到我們正在輕松接收來(lái)自所有四個(gè)傳感器的數(shù)據(jù)。
#include
#include
//#define BME_280
#定義DHT22
//#定義DS18B20
//#define ENABLE_LOG
字符串節(jié)點(diǎn)名 = "NODE_4"; // 名稱需要唯一
浮動(dòng)溫度(NAN),嗡嗡聲(NAN),壓力(NAN);
//########################## Init_BME280 #################### #####
#ifdef BME_280
#include
#include
BME280I2C bme;
BME280::TempUnit tempUnit(BME280::TempUnit_Celsius);
BME280::PresUnit presUnit(BME280::PresUnit_Pa);
#萬(wàn)一
//__________________________ _BME280 結(jié)束 __________________________
//########################## Init_DHT22 ##################### #####
#ifdef DHT22
#include "DHT.h"
#define DHTPIN 4
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
#萬(wàn)一
//__________________________ DHT22 結(jié)束 __________________________
//######################### Init_Ds18B20 #################### #####
#ifdef DS18B20
#include
#include <達(dá)拉斯溫度.h>
常量 int oneWireBus = 4;
單線單線(oneWireBus);
DallasTemperature ds18b20(&oneWire);
#萬(wàn)一
//__________________________ DHT22 結(jié)束 __________________________
#define MESH_PREFIX "whateverYouLike"
#define MESH_PASSWORD "somethingSneaky"
#define MESH_PORT 5555
調(diào)度器用戶調(diào)度器;// 控制你的個(gè)人任務(wù)
無(wú)痛網(wǎng)眼;
JSONVar myVar;
無(wú)效發(fā)送消息(){
字符串味精 = construnct_json();
網(wǎng)格.sendBroadcast(味精);
taskSendMessage.setInterval(隨機(jī)(TASK_SECOND * 1, TASK_SECOND * 5));
}
任務(wù)taskSendMessage(TASK_SECOND * 1, TASK_FOREVER, &sendMessage);
// 無(wú)痛庫(kù)需要
無(wú)效接收回調(diào)(uint32_t來(lái)自,字符串&msg){
Serial.printf("startHere: 接收自 %u msg=%s\n", from, msg.c_str());
}
無(wú)效新連接回調(diào)(uint32_t nodeId){
Serial.printf("--> startHere: 新連接, nodeId = %u\n", nodeId);
}
無(wú)效更改連接回調(diào)(){
Serial.printf("改變的連接\n");
}
無(wú)效節(jié)點(diǎn)時(shí)間調(diào)整回調(diào)(int32_t 偏移量){
Serial.printf("調(diào)整時(shí)間 %u.Offset = %d\n", mesh.getNodeTime(), offset);
}
無(wú)效設(shè)置()
{
序列號(hào).開(kāi)始(115200);
Serial.println(nodeName);
//mesh.setDebugMsgTypes(錯(cuò)誤|啟動(dòng)|MESH_STATUS|連接|同步|通信|一般|MSG_TYPES|遠(yuǎn)程); // 所有類型開(kāi)啟
網(wǎng)格.setDebugMsgTypes(錯(cuò)誤|啟動(dòng));// 在 init() 之前設(shè)置,以便您可以看到啟動(dòng)消息
mesh.init(MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT);
網(wǎng)格.onReceive(&receivedCallback);
網(wǎng)格.onNewConnection(&newConnectionCallback);
網(wǎng)格.onChangedConnections(&changedConnectionCallback);
mesh.onNodeTimeAdjusted(&nodeTimeAdjustedCallback);
userScheduler.addTask(taskSendMessage);
taskSendMessage.enable();
#ifdef BME_280
Wire.begin();
而(!bme.begin())
{
Serial.println("找不到 BME280 傳感器!");
延遲(1000);
}
// bme.chipID(); // 已棄用。請(qǐng)參閱芯片模型()。
開(kāi)關(guān) (bme.chipModel())
{
案例 BME280::ChipModel_BME280:
Serial.println("找到 BME280 傳感器!成功。");
休息;
案例 BME280::ChipModel_BMP280:
Serial.println("找到 BMP280 傳感器!沒(méi)有可用的濕度。");
休息;
默認(rèn):
Serial.println("發(fā)現(xiàn)未知傳感器!錯(cuò)誤!");
}
#萬(wàn)一
#ifdef DHT22
Serial.println(F("DHTxx 測(cè)試!"));
dht.begin();
#萬(wàn)一
#ifdef DS18B20
ds18b20.begin();
#萬(wàn)一
}
無(wú)效循環(huán)()
{
網(wǎng)格。更新();
// construnct_json();
}
字符串 construnct_json()
{
#ifdef BME_280
bme.read(pres, temp, hum, tempUnit, presUnit); // 用新值更新
壓力 = 壓力 / 100;
myVar["傳感器類型"] = "BME280";
myVar["節(jié)點(diǎn)名稱"] = nodeName;
myVar["Temperature"] = serialized(String(temp, 2)); // 序列化需要轉(zhuǎn)換浮點(diǎn)值
myVar["pres"] = serialized(String(pres, 2));// 序列化需要轉(zhuǎn)換flot值
#ifdef ENABLE_LOG
Serial.println(JSON.stringify(myVar)); //stringify 將數(shù)組轉(zhuǎn)換為字符串
#萬(wàn)一
返回 JSON.stringify(myVar);
#萬(wàn)一
#ifdef DHT22
temp = dht.readTemperature();
嗡嗡聲 = dht.readHumidity();
myVar["傳感器類型"] = "DHT22";
myVar["節(jié)點(diǎn)名稱"] = nodeName;
myVar["Temperature"] = 序列化(String(temp));
myVar["濕度"] = 序列化(String(hum));
#ifdef ENABLE_LOG
Serial.println(JSON.stringify(myVar));
#萬(wàn)一
返回 JSON.stringify(myVar);
#萬(wàn)一
#ifdef DS18B20
ds18b20.requestTemperatures();
temp = ds18b20.getTempCByIndex(0);
myVar["傳感器類型"] = "DS18B20";
myVar["節(jié)點(diǎn)名稱"] = nodeName;
myVar["Temperature"] = 序列化(String(temp));
#ifdef ENABLE_LOG
Serial.println(JSON.stringify(myVar));
#萬(wàn)一
返回 JSON.stringify(myVar);
#萬(wàn)一
}
評(píng)論
查看更多