friendev EtherDune TCP/IP library
HTTPServerDemo_MultipleClients.ino
Go to the documentation of this file.
1 // EtherDune HTTP Server demo supporting simultaneous connections
2 // Author: Javier Peletier <jm@friendev.com>
3 // Summary: Demonstrates how to build a simple web server that is able to serve multiple clients simultaneously
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 
21 
22 #include <ACross.h>
23 #include <Checksum.h>
24 #include <TCPSocket.h>
25 
26 #include <inet.h>
27 #include <ENC28J60.h>
28 #include <FlowScanner.h>
29 #include <HTTPServer.h>
30 #include <TCPListener.h>
31 
32 #define AC_LOGLEVEL 6
33 #include <ACLog.h>
34 ACROSS_MODULE("HTTPServerDemo_MultipleClients");
35 
36 
37 static const uint8_t CS_PIN = 10; //Put here what pin you are using for your ENC28J60's chip select
38 static MACAddress_P mymac = { 0x66, 0x72, 0x69, 0x65, 0x6e, 0x64 };
39 static IPAddress_P gatewayIP = { 192, 168, 1, 1 };
40 static IPAddress_P myIP = { 192, 168, 1, 33 };
41 static IPAddress_P netmask = { 255, 255, 255, 0 };
42 
43 static const uint8_t MAX_CLIENTS = 2; // maximum number of simultaneous HTTP clients
44 
45 class HTTPServerTestMulti : public HTTPServer
46 {
47 public:
48  static const uint8_t ACTION_DIGITALREAD = 1;
49  static const uint8_t ACTION_ANALOGREAD = 2;
50 
51  void onRequest(char* queryString)
52  {
53  ACTRACE("Requested URL:%s", queryString);
54 
55  //for illustrative purposes, enforce that only a GET method is used to access this server
56  if (httpMethod != HTTP_METHOD_GET)
57  {
59  writeHeader(F("Allow"), F("GET"));
61  write(F("Use a GET request"));
62 
63  }
64  else
65  {
66 
67  if (strcmp_P(queryString, PSTR("/")) == 0)
68  {
72  String title(F("Arduino Pin Monitor"));
73 
74  write(F("<html><head><title>%</title></head><body><h1>%</h1><h2>Select pin to monitor:</h2><h3>digital</h3><ul>"), &title, &title);
75 
76  for (uint8_t pin = 2; pin < 13; pin++)
77  {
78  String pinStr(pin);
79  write(F("<li><a href=\"/digitalRead/%\">Pin %</a></li>"), &pinStr, &pinStr);
80  }
81 
82  write(F("</ul><h3>Analog</h3><ul>"));
83 
84  for (uint8_t pin = A0; pin <= A7; pin++)
85  {
86  String pinStr(pin);
87  String APinStr(pin - A0);
88  write(F("<li><a href=\"/analogRead/%\">Pin A%</a></li>"), &pinStr, &APinStr);
89 
90  }
91  write(F("</ul></html>"));
92 
93  }
94  else
95  {
96  if (strcmp_P(queryString, PSTR("/favicon.ico")) == 0)
97  {
99  writeHeader(HTTP_HEADER_LOCATION, F("http://www.iconj.com/ico/c/a/capa77m3l6.ico"));
100  }
101  else
102  {
103  uint8_t action = 0;
104  uint8_t pin;
105  char* p;
106  p = strtok(queryString, "/");
107 
108 
109  if (p != NULL)
110  {
111  if (strcmp_P(p, PSTR("digitalRead")) == 0)
112  action = ACTION_DIGITALREAD;
113  else
114  {
115  if (strcmp_P(p, PSTR("analogRead")) == 0)
116  action = ACTION_ANALOGREAD;
117  }
118  }
119 
120  if (action != 0)
121  {
122  p = strtok(NULL, "/");
123  if (p != NULL)
124  {
125  pin = atoi(p);
126  }
127 
131  String strPin(pin);
132  uint16_t val = (action == ACTION_ANALOGREAD) ? analogRead(pin) : digitalRead(pin);
133  String strVal(val);
134 
135  write(F("<html><head><meta http-equiv=\"refresh\" content=\"10\" /></head><body><h1>pin%=%</h1></body></html>"), &strPin, &strVal);
136  }
137  else
138  {
141  write(F("<html><body><h1>404 not found!</h1></body></html>"));
142  }
143  }
144  }
145  }
146 
147  endResponse();
148  }
149 
150  void onHeaderReceived(const char* headerName, const char* headerValue)
151  {
152  ACTRACE("HTTP Header: %s = '%s'", headerName, headerValue);
153  }
154 
155  void onBodyBegin()
156  {
157  ACTRACE("onBodyBegin: Content-Length = %d", contentLength);
158  }
159 
160  void onRequestEnd()
161  {
162  ACTRACE("Request ended");
163  }
164 
165 
166 
167 
168 
169 };
170 
171 
173 
174 
175 void setup()
176 {
177 
178  Serial.begin(115200);
179  ACross::init();
180 #ifdef ACROSS_ARDUINO
181  ACross::printf_serial_init();
182 #endif
183 
184  printf(PSTR("Multiple client HTTP Server EtherDune sample\n"));
185  Serial.print(F("Free RAM: ")); Serial.println(ACross::getFreeRam());
186  printf(PSTR("Press any key to start...\n"));
187 
188  while (!Serial.available());
189 
191  net::localIP = myIP;
194 
195  if (!net::begin(CS_PIN))
196  ACERROR("failed to start EtherDune");
197 
198  ACINFO("waiting for link...");
199 
200  while (!net::isLinkUp());
201 
202  ACINFO("link is up");
203 
204 
205  server.listen(80);
206 
207  Serial.print("HTTP Server listening on ");
208  Serial.print(net::localIP.toString());
209  Serial.print(":");
210  Serial.println(server.localPort);
211 }
212 
213 void loop()
214 {
215  net::loop();
216 
217 }
218 
219 /// \endcond
static const char HTTP_RESPONSE_METHOD_NOT_ALLOWED_STR[]
nint16_t localPort
local TCP or UDP port
Definition: Socket.h:54
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
void listen(uint16_t port)
Starts to listen on the specified TCP port.
Definition: TCPListener.h:83
#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 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[]
Maintains a list of available sockets, also listening and spawning sockets to serve multiple clients ...
Definition: TCPListener.h:45
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
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