簡體   English   中英

在 ESP32 客戶端和服務器之間發送數據

[英]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);
}

作為參考,這是我的客戶端的樣子: esp客戶端

為了處理您從客戶端發送的 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM