本文旨在補充《超圖解物聯網IoT實作入門》第十二章「使用ESP8266WebServer程式庫建立HTTP伺服器」,示範運用C語言的snprint()函式,將動態字串轉換成字元陣列,在ESP8266控制板(如:NodeMCU或Wemos D1 mini)輸出HTML網頁。
底下是本文的靜態HTML網頁內容,它將在瀏覽器上顯示虛構的溫度和濕度值:
HTML裡的溫度和濕度數字,實際將由程式動態填入DHT11感測器的感測值。程式首先設置一個空白的字元陣列,預備填入HTML內容,提供給ESP8266WebServer的send()方法傳給用戶端。
筆者假設網頁內容約佔700字元(含字串結尾的’\0’):
char htmlStr[700];
snprintf()函式語法
假設DHT11感測的溫度和濕度值,分別存在temp與humid變數。那麼,整合上面的HTML網頁文字和temp, humid變數,並轉存成字元陣列的snprintf()函式語法格式,以及程式片段如下:
snprintf()函式的「字元數」參數,請設定成和「字元陣列」的元素數量相同;「字串」參數內容若要分成數行,則每一行的結尾都要加上「行結尾符號」。
「字串」參數值相當於「樣板」,其中要被替換動態內容,必需用「格式字元」標示。格式字元用%符號開頭,後面加上資料類型代碼,例如,%d代表「此處將填入整數資料」。
下表列舉幾個常見的格式字元,受限於微控板的記憶體容量,Arduino版的snprintf()函式無法實現個人電腦版本的所有功能,像Arduino版並不支援%f浮點數字格式字元。
格式字元 | 說明 |
---|---|
d或i | 帶正負號的整數 |
u | 無正負號的整數 |
c | 字元 |
s | 字串 |
f | 浮點數字 |
若需要把浮點數字轉換成字串,請使用dtostr()函式(參閱《超圖解Arduino 互動設計入門》16-15頁)。
ESP8266控制板設置AP模式、顯示溫濕度網頁
本文的ESP8266完整程式碼如下,DHT11感測器的數位輸出接第5腳(D1):
#include <ESP8266WiFi.h> #include <ESP8266WebServer.h> #include <dht11.h> #define DHT11PIN 5 // DHT11輸出接第5腳 ESP8266WebServer server(80); // HTTP伺服器物件 dht11 DHT11; // DHT11感測器物件 IPAddress apIP(192, 168, 4, 3); // 設定AP模式的IP位址;預設是192.168.4.1。 const char *ssid = "ESP8266"; // AP模式的Wi-Fi熱點名稱 const char *password = "12345678"; // Wi-Fi密碼 int humid = 0; // 溫度整數 int temp = 0; // 濕度整數 void rootRouter() { server.send(200, "text/html", "<p>Hello from <b>ESP8266</b>!</p>"); } void setup() { WiFi.mode(WIFI_AP); // 啟用AP模式 WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0)); // 設定微控器的IP位址 WiFi.softAP(ssid, password); // 設定Wi-Fi的識別名稱和密碼 Serial.begin(9600); Serial.println(); pinMode(DHT11PIN, INPUT); server.on("/temp", []() { // 設定 '/temp' 路徑的路由 int chk = DHT11.read(DHT11PIN); if (chk == 0) { char htmlStr[700]; humid = DHT11.humidity; temp = DHT11.temperature; snprintf ( htmlStr, 700, "<html>\ <head>\ <meta charset='utf-8'/>\ <meta http-equiv='refresh' content='5'/>\ <meta name='viewport' content='width=device-width;\ initial-scale=1.0;\ maximum-scale=1.0;\ user-scalable=0;'/>\ <title>溫溼度感測器</title>\ <style>\ body { font-family: '微軟正黑體', '黑體-繁', Sans-Serif;}\ </style>\ </head>\ <body>\ <h1>ESP8266溫溼度</h1>\ <p>溫度:%d </p>\ <p>濕度:%d </p>\ </body>\ </html>", temp, humid ); server.send(200, "text/html", htmlStr); } else { server.send(200, "text/html", "Sensor Error"); } }); server.on("/index.html", rootRouter); server.on("/", rootRouter); server.onNotFound ( []() { server.send ( 404, "text/plain", "File Not Found" ); } ); server.begin(); Serial.println("HTTP server started"); } void loop() { server.handleClient(); }
編譯並上傳程式碼到ESP8266控制板之後,在電腦或手機連接到ESP8266控制板的Wi-Fi熱點(名稱是ESP8266、密碼是12345678),再開啟瀏覽器連線到192.168.4.3/temp,即可看到動態的溫濕度頁面。
老師百忙之中打擾一下
請問一下 如果是在外出
透過4G訊號連到家中路由器
再從路由器連到ESP8266
ESP8266在連到UNO上 讀取A0的訊號
請問這樣的方式
要朝什麼方向去做
謝謝
IP分享器可以設定「虛擬伺服器」,讓你指定可從網際網路連入的裝置(如ESP8266)的IP位址,每一家IP分享器的設定方式都不太一樣,請查閱廠商說明書。
thanks,
jeffrey
你必須要先做兩件事:
1.先知道你家的網路IP,如果你用的是固定ip問題就比較簡單,去問你的網路供應商就好了,如果你家是動態ip也沒關係,如果你在台灣,就用瀏覽器”連到https://myip.com.tw/”這個網站就可以看到你家網路的ip了!
2.如果你是想用一般的瀏覽器功能去讀取的話,會使用到port:80,這時就必須用WiFi路由器中的”Port forward”設定功能,把Port:80對應到你路由器內部的IP位址,例如192.168.0.100,然後把你的ESP8266以固定IP的方式連接到路由器的這個內部IP,再來就是把ESP8266設定成伺服器的角色就可以了!
不過不是每一款的WIFI路由器都有”Port Forward”功能,要先去查清楚你手上的路由器是否有?如果沒有就必須買過了!
非常感謝TC Huand的補充說明。
thanks,
jeffrey
好像不能哦,您现在仅用AP模式是不可以的从外网接入的,只有采用WiFi.mode(WIFI_AP_STA),将模块同时作为station接入路由才可以:)
感謝提醒~
thanks,
jeffrey
老師您好 :
我給了mosquitto一個固定ip,也開啟port:1883,但是仍然無法由外網連入
Broker安裝在CentOS 7環境下
我有幾個疑問
1. server.on() 這函數的意義是?和他括號填的值是要甚麼?
2. 溫度:%d \
濕度:%d \
所以說濕度跟溫度的值是填到那兒?這一段只有提到%d是整數,那temp這個變數值用到那兒了?
server.on()相當於事件處理程式,在此偵測用戶端的請求:temp和humid會被填入%d的位置,這些在書本裡面都有寫。
thanks,
jeffrey