I have a basic webserver configured on my Ethernet Shield 2 (W5500). The sever, implemented using Ethernet.h, serves an html page that shows a set of random values. That works perfectly.
What I would like to understand is how to “name” that page? For example I might like to call it values.html or suchlike.
Ultimately I need a route or routes so that the server knows which pages to return, but how is that done?
I have seen reference to server.on() but that only seems to be used with WiFi – Is that just a coincidence? If not is there any documentation?
/*
Web Server
A simple web server that shows the value of the analog input pins.
using an Arduino Wiznet Ethernet shield.
Circuit:
* Ethernet shield attached to pins 10, 11, 12, 13
* Analog inputs attached to pins A0 through A5 (optional)
created 18 Dec 2009
by David A. Mellis
modified 9 Apr 2012
by Tom Igoe
modified 02 Sept 2015
by Arturo Guadalupi
*/
#include <SPI.h>
#include <Ethernet.h>
// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
0xA8, 0x61, 0x0A, 0xAE, 0xBF, 0x00
};
IPAddress ip(192, 168, 1, 42);
EthernetServer server(80);
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
Serial.println("Ethernet WebServer Example");
// start the Ethernet connection and the server:
Ethernet.begin(mac, ip);
// Check for Ethernet hardware present
if (Ethernet.hardwareStatus() == EthernetNoHardware) {
Serial.println("Ethernet shield was not found. Sorry, can't run without hardware. :(");
while (true) {
delay(1); // do nothing, no point running without Ethernet hardware
}
}
if (Ethernet.linkStatus() == LinkOFF) {
Serial.println("Ethernet cable is not connected.");
}
// start the server
server.begin();
Serial.print("server is at ");
Serial.println(Ethernet.localIP());
}
void loop() {
// listen for incoming clients
EthernetClient client = server.available();
if (client) {
Serial.println("new client");
// an http request ends with a blank line
boolean currentLineIsBlank = true;
while (client.connected()) {
if (client.available()) {
char c = client.read();
Serial.write(c);
// if you've got to the end of the line (received a newline
// character) and the line is blank, the http request has ended,
// so you can send a reply
if (c == '\n' && currentLineIsBlank) {
// send a standard http response header
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: close"); // the connection will be closed after completion of the response
client.println("Refresh: 5"); // refresh the page automatically every 5 sec
client.println();
client.println("<!DOCTYPE HTML>");
client.println("<html>");
// output the value of each analog input pin
for (int analogChannel = 0; analogChannel < 6; analogChannel++) {
int sensorReading = analogRead(analogChannel);
client.print("analog input ");
client.print(analogChannel);
client.print(" is ");
client.print(sensorReading);
client.println("<br />");
}
client.println("</html>");
break;
}
if (c == '\n') {
// you're starting a new line
currentLineIsBlank = true;
} else if (c != '\r') {
// you've got a character on the current line
currentLineIsBlank = false;
}
}
}
// give the web browser time to receive the data
delay(1);
// close the connection:
client.stop();
Serial.println("client disconnected");
}
}
#include <SPI.h>
#include <Ethernet.h>
// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
0xA8, 0x61, 0x0A, 0xAE, 0xBF, 0x00
};
IPAddress ip(192, 168, 1, 42);
EthernetServer server(80);
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
Serial.println("Ethernet WebServer Example");
// start the Ethernet connection and the server:
Ethernet.begin(mac, ip);
// Check for Ethernet hardware present
if (Ethernet.hardwareStatus() == EthernetNoHardware) {
Serial.println("Ethernet shield was not found. Sorry, can't run without hardware. :(");
while (true) {
delay(1); // do nothing, no point running without Ethernet hardware
}
}
if (Ethernet.linkStatus() == LinkOFF) {
Serial.println("Ethernet cable is not connected.");
}
// start the server
server.begin();
Serial.print("server is at ");
Serial.println(Ethernet.localIP());
}
void loop() {
// listen for incoming clients
EthernetClient client = server.available();
if (client) {
Serial.println("new client");
// an http request ends with a blank line
boolean currentLineIsBlank = true;
string PageRequested = "";
while (client.connected()) {
if (client.available()) {
char c = client.read();
Serial.write(c);
//if not newline and return add char to PageRequested..
if ((c != '\n') && (c != '\r')) {PageRequested = PageRequested + c;}
// if you've got to the end of the line (received a newline
// character) and the line is blank, the http request has ended,
// so you can send a reply
if (c == '\n' && currentLineIsBlank) {
//debug show the request
Serial.println();
Serial.println("Page: "+PageRequested);
// send a standard http response header
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: close"); // the connection will be closed after completion of the response
client.println("Refresh: 5"); // refresh the page automatically every 5 sec
client.println();
client.println("<!DOCTYPE HTML>");
client.println("<html>");
// output the value of each analog input pin
for (int analogChannel = 0; analogChannel < 6; analogChannel++) {
int sensorReading = analogRead(analogChannel);
client.print("analog input ");
client.print(analogChannel);
client.print(" is ");
client.print(sensorReading);
client.println("<br />");
}
client.println("</html>");
break;
}
if (c == '\n') {
// you're starting a new line
currentLineIsBlank = true;
PageRequested = "";//get ready for the next
} else if (c != '\r') {
// you've got a character on the current line
currentLineIsBlank = false;
}
}
}
// give the web browser time to receive the data
delay(1);
// close the connection:
client.stop();
Serial.println("client disconnected");
}
}
You must save all the caracters of the first line, to have the request and the name of the HML page.
ex:
GET /test.html HTTP/1.1
or
GET /logo.jpg HTTP/1.1
In the example, the request is not used and the same HTML page is responsed. regardless the contained of the HTTP request.
That's ok, had a typo in there anyways. didn't capitalize string.
got tired of waiting, so threw my ethernet shield on my zero and played a bit.
try this..
#include <SPI.h>
#include <Ethernet2.h>
// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
};
IPAddress ip(192, 168, 0, 200);
// Initialize the Ethernet server library
// with the IP address and port you want to use
// (port 80 is default for HTTP):
EthernetServer server(80);
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
// start the Ethernet connection and the server:
Ethernet.begin(mac, ip);
server.begin();
Serial.print("server is at ");
Serial.println(Ethernet.localIP());
}
word GetPage(String FullRequest)
{
int StartHere = FullRequest.indexOf("GET");
int EndHere = FullRequest.indexOf("HTTP/");
Serial.print("Start:");
Serial.println(StartHere,DEC);
Serial.print("End:");
Serial.println(EndHere,DEC);
word bRet = 404;
if (StartHere>-1)
{//have a get
String tmpStr = FullRequest.substring(StartHere+3,EndHere);
tmpStr.trim();
Serial.println(tmpStr);
if (tmpStr=="/" || tmpStr=="/index.html" || tmpStr=="/index.htm" || tmpStr=="/home.htm" || tmpStr=="/home.html"){bRet=0;} else
if (tmpStr=="/page2.html" || tmpStr == "/page2.htm"){bRet=1;} else
if (tmpStr=="/page3.html" || tmpStr == "/page3.htm"){bRet=2;}
}
return bRet;
}
void loop() {
// listen for incoming clients
EthernetClient client = server.available();
if (client) {
Serial.println("new client");
// an http request ends with a blank line
boolean currentLineIsBlank = true;
String PageRequested = "";
while (client.connected()) {
if (client.available()) {
char c = client.read();
Serial.write(c);
// if you've gotten to the end of the line (received a newline
// character) and the line is blank, the http request has ended,
// so you can send a reply
if ((c != '\n') && (c != '\r')) {PageRequested = PageRequested + c;}
if (c == '\n' && currentLineIsBlank) {
// send a standard http response header
word newpage = GetPage(PageRequested);
Serial.println();
Serial.println("Page: "+PageRequested);
Serial.println(newpage,DEC);
switch (newpage){
case 0:SendRoot(client);break;
case 1:SendPage2(client);break;
case 2:SendPage3(client);break;
case 404:Send404(client);break;
}
break;
}
if (c == '\n') {
// you're starting a new line
currentLineIsBlank = true;
}
else if (c != '\r') {
// you've gotten a character on the current line
currentLineIsBlank = false;
}
}
}
// give the web browser time to receive the data
delay(1);
// close the connection:
client.stop();
Serial.println("client disconnected");
}
}
void SendRoot(EthernetClient client)
{
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: close"); // the connection will be closed after completion of the response
client.println("Refresh: 5"); // refresh the page automatically every 5 sec
client.println();
client.println("<!DOCTYPE HTML>");
client.println("<html>");
client.println("Page 1<br>");
// output the value of each analog input pin
for (int analogChannel = 0; analogChannel < 6; analogChannel++) {
int sensorReading = analogRead(analogChannel);
client.print("analog input ");
client.print(analogChannel);
client.print(" is ");
client.print(sensorReading);
client.println("<br />");
}
client.println("</html>");
}
void SendPage2(EthernetClient client)
{
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: close"); // the connection will be closed after completion of the response
client.println("Refresh: 5"); // refresh the page automatically every 5 sec
client.println();
client.println("<!DOCTYPE HTML>");
client.println("<html>");
client.println("Page 2<br>");
// output the value of each analog input pin
for (int analogChannel = 0; analogChannel < 6; analogChannel++) {
int sensorReading = analogRead(analogChannel);
client.print("analog input ");
client.print(analogChannel);
client.print(" is ");
client.print(sensorReading);
client.println("<br />");
}
client.println("</html>");
}
void SendPage3(EthernetClient client)
{
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: close"); // the connection will be closed after completion of the response
client.println("Refresh: 5"); // refresh the page automatically every 5 sec
client.println();
client.println("<!DOCTYPE HTML>");
client.println("<html>");
client.println("Page 3<br>");
// output the value of each analog input pin
for (int analogChannel = 0; analogChannel < 6; analogChannel++) {
int sensorReading = analogRead(analogChannel);
client.print("analog input ");
client.print(analogChannel);
client.print(" is ");
client.print(sensorReading);
client.println("<br />");
}
client.println("</html>");
}
void Send404(EthernetClient client)
{
client.println("HTTP/1.1 404 Not Found");
client.println("Content-Type: text/html");
client.println("Connection: close"); // the connection will be closed after completion of the response
client.println();
client.println("Not Found");
}
I have another proposal which doesn't uses Arduino Strings. It's based on the webserver example of the Arduino IDE and shows how to read the HTTP header fields and split them in parts so you can Identify which URL was called. Furthermore it shows how to read parameters from the HTTP Body (transmitted via POST).
Hey @qubits-us thanks so much for this! It works exactly as expected!!
One question, I see that you used the Ethernet2.h library, I understood that the library is now "Depreciated" was it just habit to use that library or was there a clear reason? I changed to the standard Ethernet.h library and it worked perfectly.
old lib, mistake, change it, no worries..
only does "gets" and yes using strings and maybe there's some issues with ards string type, new to ard myself, so still discovering all its quirks..
could take strings out use chr arrays, but then need replacements for substring, trim and indexOf.
pretty simple when we use string type as you see and you should be able to expand on this pretty easy. @desp166 proposal looks quite nice too but haven't played with it yet.
@noiasca I've spent a considerable amount of time going through your code and I think I'm getting there
What would be really helpful would be if you could point me to some further reading about the state-machine control that you use. I keep thinking that I understand it but then realise, that I'm just missing some detail ... Thanks
status is of type Status (from the enum class), and the initial value is REQUEST.
The nice thing is you can't assign "wrong" values to status. When you have a state control like switch/case you get a warning when you forget one state etc. And enum classes are scoped, so you can have several enumerations in parallel without messing up the values (hence the :: )