[英]Sending Data Between ESP32 Client and Server
我正在嘗試創建一個簡單的 Web 界面來控制來自通過接入點托管客戶端的 ESP32 的 NeoPixel 條帶。 到目前為止,我在網上找到的每個示例都演示了如何通過將狀態附加到 URL 標頭然后在服務器端使用該信息來調用切換物理 LED 的函數來切換 LED 的開/關,然而,我正在嘗試做一些更獨特的事情。
我找不到將通過 HTTP 從我的 HTML 顏色選擇器檢索到的 #hex 值傳遞回服務器並使用它來設置 NEOPIXEL 顏色的方法。
我做的一件事與許多示例不同的是,我讓服務器通過使用此函數發送 HTML 頁面來處理客戶端,據我所知,該函數獲取包含 HTML 代碼的 index.h 文件並將其發送到服務器到客戶端。 但我不確定如何“逆轉”這個過程,尤其是對於“文本/變量”
這是我的服務器代碼:
#include <WiFi.h>
#include <WiFiClient.h>
#include <WebServer.h>
#include <Adafruit_NeoPixel.h>
//HTML code header for the web page
#include "index.h"
#define PIN 13
//Initialize the web client server
WebServer server(80);
//Initialize NeoPixels
Adafruit_NeoPixel strip = Adafruit_NeoPixel(12, PIN, NEO_GRB + NEO_KHZ800);
const char* ssid = "ESP32NeoPixelInterface";
const char* password = "password";
//temporary string to hold the HEX value of the color picker received from the web client
String header = "";
//Current time
unsigned long currentTime = millis();
//Previous time
unsigned long previousTime = 0;
//Define timeout time in milliseconds (example: 2000ms = 2s)
const long timeoutTime = 2000;
//===============================================================
// This routine is executed when you open its IP in browser
//===============================================================
void handleRoot() {
String s = MAIN_page; //Read HTML contents
server.send(200, "text/html", s); //Send web page
}
void UpdateNeoPixels() {
}
void setup(void) {
Serial.begin(115200);
Serial.println();
Serial.println("Booting Sketch...");
strip.begin();
strip.setBrightness(25);
//Connect to Wi-Fi network with SSID and password
Serial.print("Setting AP (Access Point)…");
//Remove the password parameter, if you want the AP (Access Point) to be open
WiFi.softAP(ssid, password);
IPAddress IP = WiFi.softAPIP();
Serial.print("AP IP address: ");
Serial.println(IP);
//Start server
server.on("/", handleRoot); //This is display page
server.begin();
Serial.println("HTTP server started");
//Set pixel #1 to green to show that an active access point connection has been made
strip.setPixelColor(1, 100, 0, 0);
strip.show();
}
//===============================================================
// This routine is executed when you open its IP in browser
//===============================================================
void loop(void) {
server.handleClient();
}
這是客戶端的頭文件:
const char MAIN_page[] PROGMEM = R"=====(
<!DOCTYPE html>
<html>
<head>
<title>ESP32 NeoPixel Web Control</title>
</head>
<style>
.button {
display: inline;
padding: 10px 10px;
font-size: 2em;
cursor: pointer;
text-align: center;
text-decoration: none;
outline: none;
color: #fff;
background-color: #4CAF50;
border: none;
border-radius: 10px;
box-shadow: 0px 2px 10px -2px rgba(0,0,0,0.5);
}
.button:hover {background-color: #3e8e41}
.button:active {
background-color: #3e8e41;
box-shadow: 0px 2px 15px -2px rgba(0,0,0,0.75);
transform: translateY(2px);
}
.p1 {
font-family: "Monaco", monospace;
color: white;
font-size: 1em;
}
.container{
position: absolute;
}
.center1{
margin: auto;
position: absolute;
top: 50%;
left: 50%;
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
.center2{
margin: auto;
position: absolute;
top: 60%;
left: 50%;
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
</style>
<body bgcolor="#282c34">
<h1 class="p1">This web page is hosted remotley by an ESP32 server, change the color of the LED NeoPixels using the color picker and press "SUBMIT".</STYLE></h1>
<hr height="10px"/>
<div class="containter">
<div class="center1">
<input type="color" id="myColor" value="#ff0080">
</div>
<div class="center2">
<button class="button button1" align="center" onclick=SendColorValue()>SUBMIT</button>
</div>
</div>
<script>
function SendColorValue() {
var x = document.getElementById("myColor");
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
};
//Send a request from client to server saying "hey update the color of the NeoPixels!"
xhttp.open("POST", "ColorValue", true);
xhttp.send(x.value);
}
</script>
</body>
</html>
)=====";
我基本上需要找到一種方法將 x.value (即從顏色選擇器框中檢索到的顏色值)發送回服務器,並使用該值來設置 neopixel 顏色。
我見過的大多數示例只處理從客戶端向服務器發送“布爾”類型的數據,例如:
// turns the GPIOs on and off
if (header.indexOf("GET /26/on") >= 0) {
Serial.println("GPIO 26 on");
output26State = "on";
digitalWrite(output26, HIGH);
} else if (header.indexOf("GET /26/off") >= 0) {
Serial.println("GPIO 26 off");
output26State = "off";
digitalWrite(output26, LOW);
}
為了處理您從客戶端發送的 POST 路由,您需要在服務器上安裝一些東西,例如:
server.on("/ColorValue", HTTP_POST, []() { ... });
那么你必須處理參數(十六進制值)
String newColorValue = server.arg("ColorValue");
將其交給一個例程來拆分十六進制並設置 LED
setLedColor(newColorValue);
並像回復客戶一樣
server.send(200, "text/plain", "Color changed");
所以整個事情看起來像:
server.on("/ColorValue", HTTP_POST, []() {
String newColorValue = server.arg("ColorValue");
setLedColor(newColorValue);
server.send(200, "text/plain", "Color changed");
});
子例程 setLedColor 看起來像
void setLedColor (String rgbHexValue) {
char hexValue[3] = {'\0'};
uint8_t tenV;
uint8_t oneV;
// split and convert the String to uint8_t
// code -> get first two letters via substring, process and convert to uint8_t
rgbHexValue.substring(0, 2).toCharArray(hexValue, 2);
tenV = (hexValue[0] <= '9') ? hexValue[0] - '0' : hexValue[0] - '7';
oneV = (hexValue[1] <= '9') ? hexValue[1] - '0' : hexValue[1] - '7';
uint8_t greenValue = (16 * tenV) + oneV;
//pseudocode pretty much the same as above changes in the comments
uint8_t redValue = ... //pseudocode -> second two letters via rgbHexValue.substring(2, 4) and from hex to uint see above
uint8_t blueValue = ... //pseudocode -> last two letters via rgbHexValue.substring(4) and from hex to uint see above
// Set pixel #1 to new color
strip.setPixelColor(1, greenValue, redValue, blueValue); // check if correct
strip.show();
}
評論(也適用於其他讀者):我個人不使用ESP8266/ESP32 的 String 類,因為從長遠來看(有時是幾分鍾)它會整理內存並使設備崩潰。 所以你應該從一開始就學習使用 char 數組和 char 處理來穩定使用,所以我建議以下代碼:
在 setup() 之前定義一個全局字符數組:
static char newColorValue[7] = {'\0'};
並從客戶那里獲得價值
strcpy(newColorValue, webServer.arg("ColorValue").c_str());
這導致以下路線:
server.on("/ColorValue", HTTP_POST, []() {
strcpy(newColorValue, webServer.arg("ColorValue").c_str());
setLedColor(newColorValue);
server.send(200, "text/plain", "Color changed");
});
然后 setLedColor 定義如下:
void setLedColor () { // Convert routine for rgbHex to uint values
char hexValue[3] = {'\0'}; // holds a 2 digit hex value eg A9
uint8_t tenV; // first digit value eg A
uint8_t oneV; // second digit value eg 9
// split and process the char array newColorValue
// split and convert the first two digits
strncpy(hexValue,newColorValue, 2);
tenV = (hexValue[0] <= '9') ? hexValue[0] - '0' : hexValue[0] - '7';
oneV = (hexValue[1] <= '9') ? hexValue[1] - '0' : hexValue[1] - '7';
uint8_t greenValue = (16 * tenV) + oneV;
// second two digits
strncpy(hexValue,newColorValue + 2, 2);
...
uint8_t redValue = ...
// Last two digits
strncpy(hexValue,newColorValue + 4, 2);
...
uint8_t blueValue = ...
}
希望這個解決方案對您的項目有所幫助 - 並記住“字符串是邪惡的”;-)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.