friendev EtherDune TCP/IP library
HTTPServerDemo.ino
Go to the documentation of this file.
1 // EtherDune HTTP Server demo
2 // Author: Javier Peletier <jm@friendev.com>
3 // Summary: Demonstrates how to build a simple web server
4 //
5 // Copyright (c) 2015 All Rights Reserved, http://friendev.com
6 //
7 // This source is subject to the GPLv2 license.
8 // Please see the License.txt file for more information.
9 // All other rights reserved.
10 //
11 // THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
12 // KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
13 // IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
14 // PARTICULAR PURPOSE.
15 
20 
21 #include <ACross.h>
22 #include <Checksum.h>
23 #include <TCPSocket.h>
24 
25 #include <inet.h>
26 #include <ENC28J60.h>
27 #include <FlowScanner.h>
28 #include <HTTPServer.h>
29 
30 #define AC_LOGLEVEL 6
31 #include <ACLog.h>
32 ACROSS_MODULE("HTTPServerDemo");
33 
34 
35 static const uint8_t CS_PIN = 10; //Put here what pin you are using for your ENC28J60's chip select
36 static MACAddress_P mymac = { 0x66, 0x72, 0x69, 0x65, 0x6e, 0x64 };
37 static IPAddress_P gatewayIP = { 192, 168, 1, 1 };
38 static IPAddress_P myIP = { 192, 168, 1, 33 };
39 static IPAddress_P netmask = { 255, 255, 255, 0 };
40 
41 class HTTPServerTest : public HTTPServer
42 {
43 public:
44  static const uint8_t ACTION_DIGITALREAD = 1;
45  static const uint8_t ACTION_ANALOGREAD = 2;
46 
47  void onRequest(char* queryString)
48  {
49  ACTRACE("Requested URL:%s", queryString);
50 
51  //for illustrative purposes, enforce that only a GET method is used to access this server
52  if (httpMethod != HTTP_METHOD_GET)
53  {
55  writeHeader(F("Allow"), F("GET"));
57  write(F("Use a GET request"));
58 
59  }
60  else
61  {
62 
63  if (strcmp_P(queryString, PSTR("/")) == 0)
64  {
68  String title(F("Arduino Pin Monitor"));
69 
70  write(F("<html><head><title>%</title></head><body><h1>%</h1><h2>Select pin to monitor:</h2><h3>digital</h3><ul>"), &title, &title);
71 
72  for (uint8_t pin = 2; pin < 13; pin++)
73  {
74  String pinStr(pin);
75  write(F("<li><a href=\"/digitalRead/%\">Pin %</a></li>"), &pinStr, &pinStr);
76  }
77 
78  write(F("</ul><h3>Analog</h3><ul>"));
79 
80  for (uint8_t pin = A0; pin <= A7; pin++)
81  {
82  String pinStr(pin);
83  String APinStr(pin - A0);
84  write(F("<li><a href=\"/analogRead/%\">Pin A%</a></li>"), &pinStr, &APinStr);
85 
86  }
87  write(F("</ul></html>"));
88 
89  }
90  else
91  {
92  if (strcmp_P(queryString, PSTR("/favicon.ico")) == 0)
93  {
95  writeHeader(HTTP_HEADER_LOCATION, F("http://www.iconj.com/ico/c/a/capa77m3l6.ico"));
96  }
97  else
98  {
99  uint8_t action=0;
100  uint8_t pin;
101  char* p;
102  p = strtok(queryString, "/");
103 
104 
105  if (p != NULL)
106  {
107  if (strcmp_P(p, PSTR("digitalRead")) == 0)
108  action = ACTION_DIGITALREAD;
109  else
110  {
111  if (strcmp_P(p, PSTR("analogRead")) == 0)
112  action = ACTION_ANALOGREAD;
113  }
114  }
115 
116  if (action != 0)
117  {
118  p = strtok(NULL, "/");
119  if (p != NULL)
120  {
121  pin = atoi(p);
122  }
123 
127  String strPin(pin);
128  uint16_t val = (action == ACTION_ANALOGREAD) ? analogRead(pin) : digitalRead(pin);
129  String strVal(val);
130 
131  write(F("<html><head><meta http-equiv=\"refresh\" content=\"10\" /></head><body><h1>pin%=%</h1></body></html>"), &strPin, &strVal);
132  }
133  else
134  {
137  write(F("<html><body><h1>404 not found!</h1></body></html>"));
138  }
139  }
140  }
141  }
142 
143  endResponse();
144  }
145 
146  void onHeaderReceived(const char* headerName, const char* headerValue)
147  {
148  ACTRACE("HTTP Header: %s = '%s'", headerName, headerValue);
149  }
150 
151  void onBodyBegin()
152  {
153  ACTRACE("onBodyBegin: Content-Length = %d", contentLength);
154  }
155 
156  void onRequestEnd()
157  {
158  ACTRACE("Request ended");
159  }
160 
161  void onTerminate()
162  {
163  ACTRACE("Listening again");
164  listen(); // listen again for the next request.
165  }
166 
167 
168 
169 }server;
170 
171 
172 
173 
174 void setup()
175 {
176 
177  Serial.begin(115200);
178  ACross::init();
179 #ifdef ACROSS_ARDUINO
180  ACross::printf_serial_init();
181 #endif
182 
183  printf(PSTR("HTTP Server EtherDune sample\n"));
184  Serial.print(F("Free RAM: ")); Serial.println(ACross::getFreeRam());
185  printf(PSTR("Press any key to start...\n"));
186 
187  while (!Serial.available());
188 
190  net::localIP = myIP;
193 
194  if (!net::begin(CS_PIN))
195  ACERROR("failed to start EtherDune");
196 
197  ACINFO("waiting for link...");
198 
199  while (!net::isLinkUp());
200 
201  ACINFO("link is up");
202 
203 
204  server.listen();
205 
206  Serial.print("HTTP Server listening on ");
207  Serial.print(net::localIP.toString());
208  Serial.print(":");
209  Serial.println(server.localPort);
210 }
211 
212 void loop()
213 {
214  net::loop();
215 
216 }
217 
218 /// \endcond
static const char HTTP_RESPONSE_METHOD_NOT_ALLOWED_STR[]
void writeHeader(const String &headerName, const String &headerValue)
Writes an HTTP header to the ongoing response stream.
Definition: HTTPServer.cpp:225
void beginResponse(uint16_t statusCode, const String &message="")
Sends out the response line, e.g.
Definition: HTTPServer.cpp:203
#define MACAddress_P
Definition: inet.h:242
#define IPAddress_P
helper macro to store an IP address in PROGMEM
Definition: inet.h:170
virtual void onBodyBegin()
Called when all HTTP headers have been received and the body of the request is about to arrive...
Definition: HTTPServer.cpp:49
uint16_t write(uint16_t len, const byte *data)
In the case of TCP, writes the given data buffer to the socket.
Definition: Socket.cpp:54
static IPAddress_P gatewayIP
void listen()
Starts listening on the local port indicated by the localPort property.
Definition: TCPSocket.cpp:91
void beginResponse_P(uint16_t statusCode, PGM_P message)
Sends out the response line, e.g.
Definition: HTTPServer.cpp:214
static const uint8_t HTTP_METHOD_GET
Definition: HTTPConstants.h:40
static bool begin(uint8_t cspin)
Initializes EtherDune and the underlying hardware
static const char HTTP_RESPONSE_FOUND_STR[]
static IPAddress netmask
Subnet mask.
static IPAddress gatewayIP
IP address of the gateway in this network.
ACROSS_MODULE("ARP")
static const uint8_t CS_PIN
virtual void onHeaderReceived(const char *headerName, const char *headerValue)
Called once for each header in the request, as they arrive.
Definition: HTTPServer.cpp:43
static const uint16_t HTTP_RESPONSE_FOUND
This response code means that URI of requested resource has been changed temporarily.
Definition: HTTPConstants.h:86
static const char HTTP_HEADER_LOCATION[]
Used in redirection, or when a new resource has been created.
void beginResponseBody()
Indicates to the client that all headers have been written and that the response body follows...
Definition: HTTPServer.cpp:266
static MACAddress_P mymac
static const char HTTP_RESPONSE_NOT_FOUND_STR[]
static bool isLinkUp()
Determines whether the network link is ready
Definition: ENC28J60.cpp:306
static const uint16_t HTTP_RESPONSE_OK
The request has succeeded.
Definition: HTTPConstants.h:77
void setup()
void writeContentTypeHeader_P(PGM_P contentType)
Convenient function to write the Content-Type header.
Definition: HTTPServer.cpp:257
static const char HTTP_RESPONSE_OK_STR[]
static MACAddress localMAC
Ethernet MAC address.
static IPAddress_P myIP
Base data structures for Internet communication.
Provides an easy way to build a web server.
Definition: HTTPServer.h:57
virtual void onRequestEnd()
Called after all the body has been received
Definition: HTTPServer.cpp:59
void endResponse()
Ends the connection and finalizes the response.
Definition: HTTPServer.cpp:275
static const uint16_t HTTP_RESPONSE_NOT_FOUND
Server can not find requested resource.
Definition: HTTPConstants.h:97
static void loop()
Gives processing time to EtherDune so that it can check for incoming packets or send queued packets...
virtual void onRequest(char *queryString)
Called immediately after the first line that contains the HTTP method and query string is received ...
Definition: HTTPServer.cpp:55
virtual void onTerminate()
Called when the socket is ready to be reused.
Definition: TCPSocket.cpp:54
static IPAddress localIP
IP address of this application.
static const uint16_t HTTP_RESPONSE_METHOD_NOT_ALLOWED
The request method is known by the server but has been disabled and cannot be used.
Definition: HTTPConstants.h:98
static IPAddress_P netmask
void loop()
static const char CONTENT_TYPE_TEXT_HTML[]
Definition: HTTPConstants.h:30