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