6

我在使用 ESP8266WebServer 时遇到了一些问题。我的 WebServer{} 类包裹在 ESP8266WebServer 对象周围,如下所示:

头文件:

#include <WiFiClient.h>

#ifndef WebServer_h
#define WebServer_h

#include "Arduino.h"

class WebServer {
    public:
        WebServer();
        void begin();
        void handleClient();
        void finishedProcessingData(String clientReply);
        String queryString;
    private:
        // page/url handlers
        friend void handleSomeData();
};

#endif

cp文件:

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>

#include "Arduino.h"
#include "WebServer.h"

ESP8266WebServer server(80);

int aNumberHere = 0;
String queryString = "";

WebServer::WebServer(){
}

void handleSomeData(){
    aNumberHere++;
    queryString = "";

    // this loop appends all the queries fro the query string back into a query string
    // (not sure if there is an easier way to grab this directly from the server api)
    int totalArgs = server.args();
    for (int counter = 0; counter < totalArgs; counter++){
        queryString += server.argName(counter) +"="+ server.arg(counter);
        if(counter < (totalArgs - 1)){
            queryString += "&";
        }
    }
    Serial.println(queryString);
    Serial.println(aNumberHere);
}

void WebServer::handleClient(){
    server.handleClient();
}

void WebServer::begin(){
    server.on("/data.html", handleSomeData);
    server.begin();
}

void WebServer::finishedProcessingData(String clientReply){
    // empty the string so it isn't cached (just in case)
    Serial.print("Sending reply back to client: ");
    Serial.println(clientReply);
    queryString = "";
    server.send(200, "text/plain", clientReply);
}

这个想法是从 http 请求中获取查询字符串,进行一些处理,然后返回响应。

从外部调用它的方式是:

WebServer webServer;
String processingResult;

void setup(){
    webServer.begin();
}

void loop(){
    delay(10);
    webServer.handleClient();

    // check if the query string has stuff in it, if it doesn't then WebServer.handleSomeData() never fired, thus no request yet
    if(webServer.queryString != ""){
        // do stuff that results in a string being returned
       processingResult = handWavyMagic();
        // then respond back to client
        webServer.finishedProcessingData(processingResult);
    }
}

我的问题是,从我的外部循环(在我的主草图中),“webServer.queryString”总是等于一个空字符串。如果我从 handleSomeData() 中打印出“queryString”,我可以从“handleSomeData()”中看到打印的结果(这是正确的),但它似乎无法将其设置为“外部”该方法。我确实检查了它是否能够访问和修改变量(这就是打印“aNumberHere”的原因)并且似乎没有问题;每次我转到相应的网址时,“aNumberHere”都会按预期递增。

我唯一的怀疑是“queryString”是一个 String 对象,由于某种原因无法设置,而“aNumberHere”是一个原始 int 很好。这是正确的还是这里发生了其他事情?

我也尝试过将“queryString”设为静态变量,但没有运气——要么我做错了,要么它也不能那样工作。

我是朋友函数的新手(好吧,实际上是 c/c++ 的新手——欢迎任何建议),尽管我读到它应该能够很好地访问类的私有属性,所以我不知道如何修复这。

有任何想法吗?

4

2 回答 2

6

我知道,对于 OP 来说帮助解决他的问题有点晚了,但也许其他读者会发现这很有用。

为了避免在类内部和外部拆分部分逻辑/数据,将所有内容都放在里面会更优雅。对类实例的非静态方法使用回调有点棘手(我在当前项目中很难学会),但这里有替代方法:

void WebServer::begin()
{
    // instead of server.on("/data.html", handleSomeData);
    server.on("/data.html", std::bind(&WebServer::handleSomeData, this));
    server.begin();
}

void WebServer::handleSomeData()
{
    // do whatever you need
}

这使用 std:bind() 将实例方法及其this指针绑定到回调。因此,所有内容都包含在 Web 服务器实例中,这是一种更简洁的方法。

于 2016-04-22T11:55:07.720 回答
1

有 2 个不同的变量称为queryString

  • 全球宣布的WebServer.cpp
  • 中声明的 WebServer 的成员WebServer.h

在回调中您设置了全局之一,handleSomeData但在您访问 WebServer 的成员时。loopfinishedProcessingData

为了使代码正常工作,您可以删除 WebServer 的成员并使用全局成员(就像您对 aNumberHere 所做的那样),如下所示:

extern String queryString;

void loop(){
    delay(10);
    webServer.handleClient();

    // check if the query string has stuff in it, if it doesn't then WebServer.handleSomeData() never fired, thus no request yet
    if(queryString != ""){
        // do stuff that results in a string being returned
        processingResult = handWavyMagic();
        // then respond back to client
        webServer.finishedProcessingData(processingResult);
        queryString = "";
    }
}
于 2015-10-04T07:38:04.503 回答