Looked like a lot of fun, so I decided to experiment with it myself. What I wanted in a web server was something that was able to handle fairly complex websites, but still light weight. I feel that I was able to strike that balance with this web server.

Creating the Web Server:

So, first things first, let’s create a socket for the server to listen on for connections:

The above code creates a new socket and then binds that socket to a port. As far as the port goes, you just need to find an open one. On the netduino, this should be easy, because all of them should be open and available to be used (0 – 65535). If you are doing prototyping on a PC prior to deploying it to the netduino (highly recommended), finding an open port is a little more challenging. Usually ports larger than 1024 are open with ports larger than 49151 having an even higher probability of being open.

I always like doing any blocking socket calls on another thread, so that application has a chance to do something else while it is waiting, if it wants to:

_thread = newThread(newThreadStart(ListenForClients));

_thread.Start();

So, it is pretty easy to create a new thread and point it to a function to execute when it runs (ListenForClients).

Putting it together gives us a constructor that looks something like this:

Now, I haven’t mentioned the location argument yet, because we haven’t needed it yet, but we will. It is basically the location of the web pages on the micro SD that we are going to be returning to anyone who requests them.

Listening For Connections:

Now we need to listen for clients to connect to our web server and request web pages:

First, we tell the socket to accept an incoming connection. This is a blocking call. By that I mean that the program will stop there on that line and wait until someone comes and connects to the socket. Once the client connects to the socket, we then wait for the client to request something before we move on. That’s what the while loop does where we poll the client. (Polling is basically asking repeated, and in this case we keep asking whether or not data is available until we get the answer that we want. Much like a kid wanting candy, except that we ask every 10 microseconds.)

Once there is data available, then we allocate a buffer to store the request in and receive the data that the client sends to us. HTTP requests are strings that are encoded into bytes using the UTF8 standard. So, we have to decode the byte array that we are sent and recover the string that contains the client’s request. We then print out the request, for debugging purposes and then respond to the client’s request.

The part that we are most concerned about is the file that is being requested (index.html). The rest of it gives more details about the requestor so that the response can be tailored for them. For this web server, we aren’t going to worry about this, we are just going to return the file that they want. In order to do this, we need to do some parsing to determine which file they want:

Before we send the file that the client is requesting, we need to send them some information about what they are about to get. Here is a typical response:

HTTP/1.0 200 OK

Content-Type: text; charset=utf-8

Content Length: 1024

Connection: close

The major piece of information that we need to tell the client is the length of our response, in bytes (1024). The rest of it is hard coded in a response string, and then the response length is inserted into the middle of it.

After we tell the client how much data we are going to be sending them, we go about reading the data from the SD card and then sending it to the client in small manageable chunks. The small chunks are so that we don’t overload the netduino’s buffer and lose data.

Error Checking:

There is also some error checking in there to make sure that the file that the client wants is a file that we have. If it is not, then we send them back an error response. There are a couple of options on how to do this. We could send an error message back in the initial response, telling the browser that the file was not found, or we could tell the browser that everything is fine and send back a webpage to the client that informs them that the file could not be found. I’m going to do the latter because it makes for a prettier web page when something goes wrong. So, here’s the code that sends back an error web page when the requested file could not be found:

We are still using the same header, but we are returning a webpage that simply states “Content Not Found”. Which should look something like this:

Cleaning Up:

Finally, we need to do some clean up when the web server class is no longer needed. If you remember back from the definition of the class, it said that it was going to implement the IDisposable interface, which is the standard way to clean up resources when you are done with them. Here’s the code:

#region IDisposable

publicvoid Dispose()

{

Dispose(true);

GC.SuppressFinalize(this);

}

privatebool _disposed = false;

protectedvirtualvoid Dispose(bool disposing)

{

if (!_disposed)

{

if (disposing)

{

_socket.Close();

_thread.Abort();

}

_disposed = true;

}

}

~WebServer()

{

Dispose(false);

}

#endregion

This piece of code closes the socket and aborts the thread when we are done with the web server.

Main Program:

Now all we need to do is start up our web server and wait for clients to connect:

publicclassProgram

{

privateconststring WebsiteFilePath = @"\SD\";

publicstaticvoid Main()

{

using (WebServer server = newWebServer(WebsiteFilePath, 1554))

{

while (true)

{

}

}

}

}

After we create the web server, we go into an infinite loop. This is because since the web server runs on a separate thread, the call to create the web server will return almost immediately. Since, we don’t have anything that we need to do, we just loop forever.

The port number choice is arbitrary. I picked 1554 after the New Belgium beer.

Adding a Temperature Sensor:

All of the web page content that we have been talking about so far has been static content. Meaning that all the webserver does is grab a file from the SD card and hand it to the user. I wanted to go one small step further and incorporate some dynamic content to the website. By this I mean that I wanted to do some preprocessing on the files that I retrieve from the SD card, before I send them to the client. (Think PHP.)

A common netduino project seems to be home automation and common task within that is to take a temperature measurement. So, I thought it would be neat to add some preprocessing code into the html file that tells the netduino to read the current temperature in the room and embed that in the html response.

So, here is the circuit that I wired up to the A0 pin of the netduino:

Then I wrote the following class that takes a temperature measurement:

The conversion from voltage to temperature is right out of the data sheet. The only interesting part of this code is that I take 5 measurements, spaced 100 milliseconds apart, and averages the results. This yielded a more consistent temperature measurement.

Integrating the Temperature Sensor:

To tie it all together, I decided to create my own file type (a .sme file), and define a html tag (<?sme … ?>) that told my preprocessor that the text between it needed to be interpreted. By creating my own file type, only files of that type have to be read in and checked for the magic tag that I created.

In order to keep it simple, my preprocessor language only has one command ($a0), which reads the value from A0 analog input pin and returns its current value. This was done in the interest of keeping the code simple and straight-forward. Hopefully in the future I’ll expand on this as I need more features, but this is good enough for now.

Summary:

In this post I described creating a web server using a netduino plus and an sd card. The web server was capable of handling text and images, along with some minimal preprocessing. I also demonstrated how to use a temperature sensor with the netduino and report the current temperature in the server room.

Cookies on the element14 Community website

We use cookies to ensure that we give you the best experience on our website. If you continue to use the site without changing your settings, we'll assume that you are happy to receive all cookies on the site. You can find out more about cookies and how to manage your cookie settings at any time by clicking here.