1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-04-21 10:26:06 +03:00

Merge pull request #1 from esp8266/esp8266

pull changes from master
This commit is contained in:
ficeto 2015-05-01 12:28:56 +03:00
commit 517b234e2a
5 changed files with 299 additions and 278 deletions

View File

@ -154,7 +154,15 @@ extern void __detachInterrupt(uint8_t pin) {
} }
void initPins() { void initPins() {
ETS_GPIO_INTR_ATTACH(interrupt_handlers, &interrupt_reg); for (int i = 0; i <= 5; ++i) {
pinMode(i, INPUT);
}
// pins 6-11 are used for the SPI flash interface
for (int i = 12; i <= 16; ++i) {
pinMode(i, INPUT);
}
ETS_GPIO_INTR_ATTACH(interrupt_handler, &interrupt_reg);
ETS_GPIO_INTR_ENABLE(); ETS_GPIO_INTR_ENABLE();
} }

View File

@ -9,24 +9,23 @@ MDNSResponder mdns;
ESP8266WebServer server(80); ESP8266WebServer server(80);
void handle_root() { void handleRoot() {
server.send(200, "text/plain", "hello from esp8266!"); server.send(200, "text/plain", "hello from esp8266!");
} }
bool handle_not_found(){ void handleNotFound(){
String message = "URI: "; String message = "URI: ";
message += server.uri(); message += server.uri();
message += "\nMethod: "; message += "\nMethod: ";
message += (server.method() == HTTP_GET)?"GET":"POST"; message += (server.method() == HTTP_GET)?"GET":"POST";
message += "\nNot Found!\n\n";
message += "\nArguments: "; message += "\nArguments: ";
message += server.args(); message += server.args();
message += "\n"; message += "\n";
for (uint8_t i=0; i<server.args(); i++){ for (uint8_t i=0; i<server.args(); i++){
message += " " + server.argName(i) + ": " + server.arg(i) + "\n"; message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
} }
message += "\nNotFound!";
server.send(404, "text/plain", message); server.send(404, "text/plain", message);
return true;
} }
void setup(void){ void setup(void){
@ -45,15 +44,17 @@ void setup(void){
Serial.print("IP address: "); Serial.print("IP address: ");
Serial.println(WiFi.localIP()); Serial.println(WiFi.localIP());
if (mdns.begin("esp8266", WiFi.localIP())) Serial.println("MDNS responder started"); if (mdns.begin("esp8266", WiFi.localIP())) {
Serial.println("MDNS responder started");
}
server.on("/", handle_root); server.on("/", handleRoot);
server.on("/inline", [](){ server.on("/inline", [](){
server.send(200, "text/plain", "this works as well"); server.send(200, "text/plain", "this works as well");
}); });
server.onNotFound(handle_not_found); server.onNotFound(handleNotFound);
server.begin(); server.begin();
Serial.println("HTTP server started"); Serial.println("HTTP server started");

View File

@ -21,6 +21,10 @@ method KEYWORD2
client KEYWORD2 client KEYWORD2
send KEYWORD2 send KEYWORD2
arg KEYWORD2 arg KEYWORD2
argName KEYWORD2
args KEYWORD2
hasArg KEYWORD2
onNotFound KEYWORD2
####################################### #######################################
# Constants (LITERAL1) # Constants (LITERAL1)

View File

@ -28,18 +28,18 @@
// #define DEBUG // #define DEBUG
struct ESP8266WebServer::RequestHandler { struct ESP8266WebServer::RequestHandler {
RequestHandler(ESP8266WebServer::THandlerFunction fn, const char* uri, HTTPMethod method) RequestHandler(ESP8266WebServer::THandlerFunction fn, const char* uri, HTTPMethod method)
: fn(fn) : fn(fn)
, uri(uri) , uri(uri)
, method(method) , method(method)
, next(NULL) , next(NULL)
{ {
} }
ESP8266WebServer::THandlerFunction fn; ESP8266WebServer::THandlerFunction fn;
String uri; String uri;
HTTPMethod method; HTTPMethod method;
RequestHandler* next; RequestHandler* next;
}; };
@ -54,302 +54,309 @@ ESP8266WebServer::ESP8266WebServer(int port)
ESP8266WebServer::~ESP8266WebServer() ESP8266WebServer::~ESP8266WebServer()
{ {
if (!_firstHandler) if (!_firstHandler)
return; return;
RequestHandler* handler = _firstHandler; RequestHandler* handler = _firstHandler;
while (handler) { while (handler) {
RequestHandler* next = handler->next; RequestHandler* next = handler->next;
delete handler; delete handler;
handler = next; handler = next;
} }
} }
void ESP8266WebServer::begin() { void ESP8266WebServer::begin() {
_server.begin(); _server.begin();
} }
void ESP8266WebServer::on(const char* uri, ESP8266WebServer::THandlerFunction handler) void ESP8266WebServer::on(const char* uri, ESP8266WebServer::THandlerFunction handler)
{ {
on(uri, HTTP_ANY, handler); on(uri, HTTP_ANY, handler);
} }
void ESP8266WebServer::on(const char* uri, HTTPMethod method, ESP8266WebServer::THandlerFunction fn) void ESP8266WebServer::on(const char* uri, HTTPMethod method, ESP8266WebServer::THandlerFunction fn)
{ {
RequestHandler* handler = new RequestHandler(fn, uri, method); RequestHandler* handler = new RequestHandler(fn, uri, method);
if (!_lastHandler) { if (!_lastHandler) {
_firstHandler = handler; _firstHandler = handler;
_lastHandler = handler; _lastHandler = handler;
} }
else { else {
_lastHandler->next = handler; _lastHandler->next = handler;
_lastHandler = handler; _lastHandler = handler;
} }
} }
void ESP8266WebServer::handleClient() void ESP8266WebServer::handleClient()
{ {
WiFiClient client = _server.available(); WiFiClient client = _server.available();
if (!client) { if (!client) {
return; return;
} }
#ifdef DEBUG #ifdef DEBUG
Serial.println("New client"); Serial.println("New client");
#endif #endif
// Wait for data from client to become available // Wait for data from client to become available
while(client.connected() && !client.available()){ while(client.connected() && !client.available()){
delay(1); delay(1);
} }
// Read the first line of HTTP request // Read the first line of HTTP request
String req = client.readStringUntil('\r'); String req = client.readStringUntil('\r');
client.readStringUntil('\n'); client.readStringUntil('\n');
HTTPMethod method = HTTP_GET; HTTPMethod method = HTTP_GET;
if (req.startsWith("POST")) { if (req.startsWith("POST")) {
method = HTTP_POST; method = HTTP_POST;
} }
// First line of HTTP request looks like "GET /path HTTP/1.1"
// First line of HTTP request looks like "GET /path HTTP/1.1" // Retrieve the "/path" part by finding the spaces
// Retrieve the "/path" part by finding the spaces int addr_start = req.indexOf(' ');
int addr_start = req.indexOf(' '); int addr_end = req.indexOf(' ', addr_start + 1);
int addr_end = req.indexOf(' ', addr_start + 1); if (addr_start == -1 || addr_end == -1) {
if (addr_start == -1 || addr_end == -1) {
#ifdef DEBUG #ifdef DEBUG
Serial.print("Invalid request: "); Serial.print("Invalid request: ");
Serial.println(req); Serial.println(req);
#endif #endif
return; return;
} }
req = req.substring(addr_start + 1, addr_end); req = req.substring(addr_start + 1, addr_end);
String formData; String formData;
if (method == HTTP_POST) if (method == HTTP_POST) {
{ int contentLength = -1;
int contentLength = -1; int headerCount = 0;
int headerCount = 0; while(headerCount < 1024) { // there shouldn't be that much really
while(headerCount < 1024) { // there shouldn't be that much really String line = client.readStringUntil('\r');
String line = client.readStringUntil('\r'); client.readStringUntil('\n');
client.readStringUntil('\n');
if (line.length() > 0) { // this is a header if (line.length() > 0) { // this is a header
++headerCount; ++headerCount;
if (contentLength < 0 && line.startsWith("Content-Length")) { if (contentLength < 0 && line.startsWith("Content-Length")) {
// get content length from the header // get content length from the header
int valuePos = line.indexOf(' ', 14); int valuePos = line.indexOf(' ', 14);
if (valuePos > 0) { if (valuePos > 0) {
String valueStr = line.substring(valuePos+1); String valueStr = line.substring(valuePos+1);
contentLength = valueStr.toInt(); contentLength = valueStr.toInt();
#ifdef DEBUG #ifdef DEBUG
Serial.print("Content-Length: "); Serial.print("Content-Length: ");
Serial.println(contentLength); Serial.println(contentLength);
#endif #endif
} }
} }
} }
else { else {
break; break;
} }
} }
#ifdef DEBUG #ifdef DEBUG
Serial.print("headerCount="); Serial.print("headerCount=");
Serial.println(headerCount); Serial.println(headerCount);
#endif #endif
if (contentLength >= 0) { if (contentLength >= 0) {
formData = ""; formData = "";
int n = 0; // timeout counter int n = 0; // timeout counter
while (formData.length() < contentLength && ++n < 3) while (formData.length() < contentLength && ++n < 3)
formData += client.readString(); formData += client.readString();
} }
else { else {
formData = client.readStringUntil('\r'); // will return after timing out once formData = client.readStringUntil('\r'); // will return after timing out once
} }
// read form data }
// formData = else if (method == HTTP_GET) {
} int args_start = req.indexOf('?');
else if (method == HTTP_GET) if (args_start != -1) {
{ formData = req.substring(args_start + 1);
int args_start = req.indexOf('?'); req = req.substring(0, args_start);
if (args_start != -1) }
{ }
formData = req.substring(args_start + 1);
req = req.substring(0, args_start);
}
}
client.flush(); client.flush();
#ifdef DEBUG #ifdef DEBUG
Serial.print("Request: "); Serial.print("Request: ");
Serial.println(req); Serial.println(req);
Serial.print("Args: "); Serial.print("Args: ");
Serial.println(formData); Serial.println(formData);
#endif #endif
_parseArguments(formData); _parseArguments(formData);
_handleRequest(client, req, method); _handleRequest(client, req, method);
} }
void ESP8266WebServer::send(int code, const char* content_type, String content) { void ESP8266WebServer::send(int code, const char* content_type, String content) {
String response = "HTTP/1.1 "; String response = "HTTP/1.1 ";
response += String(code); response += String(code);
response += " "; response += " ";
if (code == 200) response += _responseCodeToString(code);
response += "OK"; response += "\r\n";
else if (code == 404)
response += "Not found"; if (!content_type)
response += "\r\n"; content_type = "text/html";
if (!content_type) _appendHeader(response, "Content-Type", content_type);
content_type = "text/html";
response += "Content-Type: "; response += "\r\n";
response += content_type; response += content;
response += "\r\n\r\n"; _currentClient.print(response);
response += content;
_currentClient.print(response);
} }
String ESP8266WebServer::arg(const char* name) String ESP8266WebServer::arg(const char* name) {
{ for (int i = 0; i < _currentArgCount; ++i) {
for (int i = 0; i < _currentArgCount; ++i) { if (_currentArgs[i].key == name)
if (_currentArgs[i].key == name) return _currentArgs[i].value;
return _currentArgs[i].value; }
} return String();
return String();
} }
String ESP8266WebServer::arg(int i) String ESP8266WebServer::arg(int i) {
{ if (i < _currentArgCount)
if (i < _currentArgCount) return _currentArgs[i].value;
return _currentArgs[i].value; return String();
return String();
} }
String ESP8266WebServer::argName(int i) String ESP8266WebServer::argName(int i) {
{ if (i < _currentArgCount)
if (i < _currentArgCount) return _currentArgs[i].key;
return _currentArgs[i].key; return String();
return String();
} }
int ESP8266WebServer::args(){ int ESP8266WebServer::args() {
return _currentArgCount; return _currentArgCount;
} }
bool ESP8266WebServer::hasArg(const char* name) bool ESP8266WebServer::hasArg(const char* name) {
{ for (int i = 0; i < _currentArgCount; ++i) {
for (int i = 0; i < _currentArgCount; ++i) { if (_currentArgs[i].key == name)
if (_currentArgs[i].key == name) return true;
return true; }
} return false;
return false;
} }
void ESP8266WebServer::_parseArguments(String data) void ESP8266WebServer::_parseArguments(String data) {
{ if (_currentArgs)
if (_currentArgs) delete[] _currentArgs;
delete[] _currentArgs; _currentArgs = 0;
_currentArgs = 0; if (data.length() == 0) {
if (data.length() == 0) { _currentArgCount = 0;
_currentArgCount = 0; return;
return; }
} _currentArgCount = 1;
_currentArgCount = 1;
for (int i = 0; i < data.length(); ) { for (int i = 0; i < data.length(); ) {
i = data.indexOf('&', i); i = data.indexOf('&', i);
if (i == -1) if (i == -1)
break; break;
++i; ++i;
++_currentArgCount; ++_currentArgCount;
} }
#ifdef DEBUG #ifdef DEBUG
Serial.print("args count: "); Serial.print("args count: ");
Serial.println(_currentArgCount); Serial.println(_currentArgCount);
#endif #endif
_currentArgs = new RequestArgument[_currentArgCount]; _currentArgs = new RequestArgument[_currentArgCount];
int pos = 0; int pos = 0;
int iarg; int iarg;
for (iarg = 0; iarg < _currentArgCount;) { for (iarg = 0; iarg < _currentArgCount;) {
int equal_sign_index = data.indexOf('=', pos); int equal_sign_index = data.indexOf('=', pos);
int next_arg_index = data.indexOf('&', pos); int next_arg_index = data.indexOf('&', pos);
#ifdef DEBUG #ifdef DEBUG
Serial.print("pos "); Serial.print("pos ");
Serial.print(pos); Serial.print(pos);
Serial.print("=@ "); Serial.print("=@ ");
Serial.print(equal_sign_index); Serial.print(equal_sign_index);
Serial.print(" &@ "); Serial.print(" &@ ");
Serial.println(next_arg_index); Serial.println(next_arg_index);
#endif #endif
if ((equal_sign_index == -1) || ((equal_sign_index > next_arg_index) && (next_arg_index != -1))) { if ((equal_sign_index == -1) || ((equal_sign_index > next_arg_index) && (next_arg_index != -1))) {
#ifdef DEBUG #ifdef DEBUG
Serial.print("arg missing value: "); Serial.print("arg missing value: ");
Serial.println(iarg); Serial.println(iarg);
#endif #endif
if (next_arg_index == -1) if (next_arg_index == -1)
break; break;
pos = next_arg_index + 1; pos = next_arg_index + 1;
continue; continue;
} }
RequestArgument& arg = _currentArgs[iarg]; RequestArgument& arg = _currentArgs[iarg];
arg.key = data.substring(pos, equal_sign_index); arg.key = data.substring(pos, equal_sign_index);
arg.value = data.substring(equal_sign_index + 1, next_arg_index); arg.value = data.substring(equal_sign_index + 1, next_arg_index);
#ifdef DEBUG #ifdef DEBUG
Serial.print("arg "); Serial.print("arg ");
Serial.print(iarg); Serial.print(iarg);
Serial.print(" key: "); Serial.print(" key: ");
Serial.print(arg.key); Serial.print(arg.key);
Serial.print(" value: "); Serial.print(" value: ");
Serial.println(arg.value); Serial.println(arg.value);
#endif #endif
++iarg; ++iarg;
if (next_arg_index == -1) if (next_arg_index == -1)
break; break;
pos = next_arg_index + 1; pos = next_arg_index + 1;
} }
_currentArgCount = iarg; _currentArgCount = iarg;
#ifdef DEBUG #ifdef DEBUG
Serial.print("args count: "); Serial.print("args count: ");
Serial.println(_currentArgCount); Serial.println(_currentArgCount);
#endif #endif
} }
void ESP8266WebServer::onNotFound(TNotFoundHandlerFunction fn){ void ESP8266WebServer::onNotFound(THandlerFunction fn) {
_notFoundHandler = fn; _notFoundHandler = fn;
} }
void ESP8266WebServer::_handleRequest(WiFiClient& client, String uri, HTTPMethod method) { void ESP8266WebServer::_handleRequest(WiFiClient& client, String uri, HTTPMethod method) {
_currentClient = client; _currentClient = client;
_currentUri = uri; _currentUri = uri;
_currentMethod = method; _currentMethod = method;
RequestHandler* handler; RequestHandler* handler;
for (handler = _firstHandler; handler; handler = handler->next) for (handler = _firstHandler; handler; handler = handler->next)
{ {
if (handler->method != HTTP_ANY && handler->method != method) if (handler->method != HTTP_ANY && handler->method != method)
continue; continue;
if (handler->uri != uri) if (handler->uri != uri)
continue; continue;
handler->fn(); handler->fn();
break; break;
} }
if (!handler){ if (!handler){
#ifdef DEBUG #ifdef DEBUG
Serial.println("request handler not found"); Serial.println("request handler not found");
#endif #endif
if(!_notFoundHandler || !_notFoundHandler())
send(404, "text/plain", String("Not found: ") + uri);
}
_currentClient = WiFiClient(); if(_notFoundHandler) {
_currentUri = String(); _notFoundHandler();
}
else {
send(404, "text/plain", String("Not found: ") + uri);
}
}
_currentClient = WiFiClient();
_currentUri = String();
}
const char* ESP8266WebServer::_responseCodeToString(int code) {
switch (code) {
case 200: return "OK";
case 404: return "Not found";
default: return "";
}
}
void ESP8266WebServer::_appendHeader(String& response, const char* name, const char* value) {
response += name;
response += ": ";
response += value;
response += "\r\n";
} }

View File

@ -32,56 +32,57 @@ class ESP8266WebServer
{ {
public: public:
ESP8266WebServer(int port = 80); ESP8266WebServer(int port = 80);
~ESP8266WebServer(); ~ESP8266WebServer();
void begin(); void begin();
void handleClient(); void handleClient();
typedef std::function<void(void)> THandlerFunction; typedef std::function<void(void)> THandlerFunction;
typedef std::function<bool(void)> TNotFoundHandlerFunction; void on(const char* uri, THandlerFunction handler);
void on(const char* uri, THandlerFunction handler); void on(const char* uri, HTTPMethod method, THandlerFunction fn);
void on(const char* uri, HTTPMethod method, THandlerFunction fn); void onNotFound(THandlerFunction fn); //called when handler is not assigned
void onNotFound(TNotFoundHandlerFunction fn);//called when handler is not assigned
String uri() { return _currentUri; } String uri() { return _currentUri; }
HTTPMethod method() { return _currentMethod; } HTTPMethod method() { return _currentMethod; }
WiFiClient client() { return _currentClient; } WiFiClient client() { return _currentClient; }
String arg(const char* name);// get request argument value
String arg(int i);// get request argument value buy number
String argName(int i);// get request argument name buy number
int args();//get arguments count
bool hasArg(const char* name);//check if argument exists
// send response to the client String arg(const char* name); // get request argument value by name
// code - HTTP response code, can be 200 or 404 String arg(int i); // get request argument value by number
// content_type - HTTP content type, like "text/plain" or "image/png" String argName(int i); // get request argument name by number
// content - actual content body int args(); // get arguments count
void send(int code, const char* content_type = NULL, String content = String("")); bool hasArg(const char* name); // check if argument exists
// send response to the client
// code - HTTP response code, can be 200 or 404
// content_type - HTTP content type, like "text/plain" or "image/png"
// content - actual content body
void send(int code, const char* content_type = NULL, String content = String(""));
protected: protected:
void _handleRequest(WiFiClient& client, String uri, HTTPMethod method); void _handleRequest(WiFiClient& client, String uri, HTTPMethod method);
void _parseArguments(String data); void _parseArguments(String data);
static const char* _responseCodeToString(int code);
static void _appendHeader(String& response, const char* name, const char* value);
struct RequestHandler;
struct RequestArgument {
String key;
String value;
};
struct RequestHandler; WiFiServer _server;
struct RequestArgument {
String key;
String value;
};
WiFiServer _server; WiFiClient _currentClient;
HTTPMethod _currentMethod;
String _currentUri;
WiFiClient _currentClient; size_t _currentArgCount;
HTTPMethod _currentMethod; RequestArgument* _currentArgs;
String _currentUri;
size_t _currentArgCount; RequestHandler* _firstHandler;
RequestArgument* _currentArgs; RequestHandler* _lastHandler;
THandlerFunction _notFoundHandler;
RequestHandler* _firstHandler;
RequestHandler* _lastHandler;
TNotFoundHandlerFunction _notFoundHandler;
}; };