Written by: Kurt Furlong and Ryan Erickson
Kurt is a Software Engineer at LSR. Kurt graduated from Milwaukee School of Engineering with a BSEE in 2010. Kurt has been involved in a wide range of wireless and wired software projects in his short career and also serves as the company’s IT and website resource.
Ryan is a RF Products Engineer at LSR. He graduated in 2009, with a Bachelor’s degree in Computer Science, from the Milwaukee School of Engineering.
In today's electronic age, the Internet has become the unofficial standard for transferring data around the world. As technology advances and more users rely on mobile devices, the ability to access information from any location becomes vital.
Most mobile phones can access the Internet over a Wi-Fi (802.11) connection or through a 3G/4G data connection. These devices are great for everyday use when acceptable battery life would be in the range of one to three days. But what about industrial and commercial wireless applications with battery lifetime requirements on the order of months or years? Is 802.11 really the answer to keep these types of devices connected to an IP infrastructure?
For low-power wireless applications, 802.15.4 is a much better solution. Here is a quick look at pros and cons of 802.15.4 and Wi-Fi (802.11).
802.11 networks and 802.15.4 networks, for the most part, have the same type of structure. They are usually star or point-to-point networks. A star network might have many end devices communicating to one gateway or network bridge.
Figure 1: 802.11 Network Configuration
Figure 2: 802.15.4 Network Configuration
When comparing the network topology of an 802.11 system (Figure 1) with an 802.15.4 network (Figure 2), we see that the 802.15.4 IP network needs an extra bridge device or gateway to convert 802.15.4 wireless messages into IP-based messages, whereas the 802.11 network connects directly to the IP infrastructure.
So if an 802.11 device can connect directly to the IP network, why even consider using 802.15.4 technology that requires an extra bridge? The reasons are cost, power consumption, and complexity.
Cost Using embedded Wi-Fi usually requires a higher-end microcontroller or microprocessor to avoid a bottleneck of messages in 802.11 traffic. Bigger, better processors are more costly.
Power consumption An 802.11 system needs a constant connection to allow data to get through, and this involves much more power consumption. Although 802.11 systems can be designed to shut down their connections when they aren’t being used, whenever any communication needs to be done, the system must take the time to reconnect; this reconnection uses precious energy.
Complexity Because an 802.11 connection is a constant wireless link, more complex software is required to handle cases in which the connection is dropped. With 802.15.4 there is no connection that needs to stay open – the end device can just wake up, send its message, wait for an acknowledgment, and then go back to sleep. This allows the device to transmit at higher power levels (which means a longer range) and save more power by spending less time with an active RF connection. This simple wake up / send a message / go back to sleep technique allows for a much simpler system. And the simpler the system, the smaller the processor needed to make the system work, which means a savings in cost.
Let’s take a look at what’s required for a reliable 802.15.4-to-Ethernet device to function as a gateway for all 802.15.4 traffic. The first requirement is an Ethernet-enabled microcontroller. Several companies make small, cost-effective microcontrollers that can handle 802.15.4-to-Ethernet bridging. The ARM Cortex-M3 microcontroller family provides a great solution, and manufacturers provide these with a built-in Ethernet MAC and PHY. The microcontroller also needs a UART, SPI, or I2C interface to communicate to an 802.15.4 wireless module or IC. Once the hardware has been picked, it’s all up to the firmware to do the job of bridging the 802.15.4 messages to the Ethernet interface.
Running Ethernet on an embedded system requires a TCP/IP stack to handle all low-level Ethernet data. The TCP/IP stack provides an easy-to-use interface for sending and receiving TCP or UDP messages without having to understand or develop the low-level Internet protocol messages. A great reliable TCP/IP stack that can be used on embedded systems is lwIP1. lwIP features full TCP, UDP, and DHCP functionality. Best of all, it is an open source project and, being licensed under BSD, it is free to use. It is written in standard C, and the user is only required to provide the low-level functions to initialize and use the Ethernet interface on the specific processor. lwIP provides a very easy-to-use socket-based API to send and receive IP messages.
The following example shows how to create a UDP connection and send UDP data in lwIP.
Once the device has an operational Ethernet port and communication to the 802.15.4 module or IC is working, the message flow must be tied together with some sort of task scheduler or simple operating system. FreeRTOS2 is a free open source real-time operating system designed for embedded processors. It has a great task and queue system for managing the flow of data on an embedded system. There are also many ports for a variety of processors already available to get FreeRTOS up and running fast.
In FreeRTOS, tasks are used to accomplish work by the OS. The tasks (or threads) can run independently of each other in a parallel fashion to complete separate goals of the system. Even though the tasks seem to run at the same time, they are really executing one at a time, but the OS switches back and forth between the tasks at high speed so each task can do its work. This is known as context switching.
The following example shows how to create a task in FreeRTOS:
To easily pass data between different tasks, FreeRTOS uses message queues that allow data to be sent safely between tasks. The queues act as a first in / first out buffer system. Any data in a queue is placed there as a copy, not by reference. If large amounts of data need to be transferred between tasks, the queues should contain pointers to the data instead of the data itself. This will allow for much better performance, but the user’s application must keep track of what task is using the data to make sure it isn’t accessed by two separate tasks at the same time.
The following example shows how to create queues in FreeRTOS:
Remote Connectivity for Your Wireless Device with HTTP
As described above, bringing the power of Ethernet into your next 802.15.4 wireless design can be a cost-effective way to bridge the wireless world with the wired. Using Ethernet, developers can utilize the vast and proven IP infrastructure with their embedded designs and not be required to use high-end ARM processors. Advancing microprocessor design has enabled many low-end 8-bit and 16-bit microprocessors to handle this task.
So you decide to go with a low-end microprocessor and an IP stack. Now what? The whole purpose of putting an Ethernet stack on the device is to connect to it via Ethernet, but how? That is where HTTP (Hyper-Text Transfer Protocol) comes in.
HTTP can easily give your device the remote status, configuration, and control of your application that you desire. You can access your device from anything with a web browser, whether it is a PC, laptop, or phone, and you can access your device from anywhere in the world, check alarm status or up-time, or modify configuration settings. All of this may be easier than you thought to implement on low-end microprocessors.
How HTTP Works
In its simplest form, the HTTP 1.0 protocol is a request and response protocol between a client and server for data – usually web pages. The client sends HTTP request headers in ASCII form to the server, and the server responds with an HTTP response consisting of headers and possible data. Let’s take a look at an example:
An embedded Ethernet device is connected to your network and has completed the DHCP process to obtain an IP address: 192.168.1.50. You, the client, open up a web browser (Internet Explorer, Chrome, Firefox, etc.) and in the URL navigator type "http://192.168.1.50". Your browser automatically performs the TCP connection and sends an HTTP request to your embedded device for "/", the root default file. This is what that request may look like:
The server receives this request, searches for the requested file, and returns HTTP request response headers to the client. If the file is found, the contents of the file are also returned after the headers. This is what the response from the server may look like:
Your browser processes this data and displays the HTML. The headers are not displayed, although they can be viewed via many third-party browser add-ons, plug-ins, or developer tools. The TCP connection is then closed by the server.
This is a very simple description of how HTTP works. Many details have been left out. Most modern browsers today use HTTP 1.1, which introduces the use of options requests, advanced cacheing, pipe-lining and persistent connections, to name a few, but for a simple embedded server, none of this is needed, and HTTP 1.0 can be used.
Additionally, even with HTTP 1.0, clients will often send a “Keep-alive” header to tell the server to keep its connection open. For embedded designs, this header is best ignored and the “Connection: close” header returned. In this way, the embedded server – which has limited TCP connections available – can better handle connections from multiple clients.
Requirements of an Embedded HTTP Server
As mentioned, advancements in 8- and 16-bit microprocessors have brought the possibility of running an HTTP server on an embedded device to the surface of many new designs. Picking out a microprocessor for any application can be a tedious process, so the following will attempt to break down the minimum requirements needed for various applications.
Since HTTP usually uses TCP as its transport protocol, the TCP/IP stack is the single most important requirement of an embedded server. Two notable open-source options are lwIP and uIP, but there are numerous others available.
Since the server is required to serve up files to the client, it must have a repository of files somewhere. For most basic applications, the files can be compiled and saved directly in Flash.
Application logic must exist on the server to accept incoming connections, process the received HTTP request headers, and return the contents of the requested file. The most basic processing logic must handle HTTP “GET” requests to serve up static (non-changing) content.
To provide dynamic status and configuration of the embedded device, support for SSI (server-side includes) and CGI (common gateway interface) becomes necessary. To summarize, SSI provides a way to insert dynamically changing data (i.e., application variable values) into an HTML page, and CGI allows a client to request the server to execute a specific parameterized function.
The optional requirements of an embedded HTTP server are endless and can be extended as far as required. For a better user experience, Comet could be implemented to provide a more “real-time” feel. If security is a concern, SSL or TLS can be implemented to ensure that your data transfer is private. The options are there; only the microprocessor limits the implementation.
Determining which HTTP server features you need is a process that’s specific to the application. The following attempts to detail three common applications for an embedded HTTP server and their requirements.
Device Status: Basic
|information, and library build details. Basic device status requires TCP/IP stack, internal or external file system, and static file processing logic.||Device Status: Advanced Advanced device status provides a means to display dynamically changing data to client. This allows display of real-time application status, errors, statistics, and configuration
|Advanced device status requires TCP/IP stack, internal or external file system, and dynamic file processing logic for SSI.||Device Configuration and Control Device configuration enables a client to remotely control the embedded device and change its settings or||command it to carry out various tasks This requires TCP/IP stack, internal or external file system, and dynamic file processing logic for SSI and CGI.|
Embedded HTTP Server Design
Once the HTTP server requirements are known, the design can begin. For simplicity, the simplest of the three server applications is diagrammed below at a high level – the embedded server for basic device status.
The high-level design is very straightforward. The following sections provide details on each wireless module.
Handling the incoming connection involves a few steps. Upon initialization of the server, a listening connection needs to be opened on TCP port 80. Port 80 is the port defined by the IANA as the standard for HTTP traffic. The server does not know what IP address the client is using, so it should listen for any IP address on the port.
One thing to keep in mind in designing an embedded HTTP server is that care must be taken to properly manage the number of simultaneous TCP connections. For example, an embedded device may have its IP stack configured to allow a total of 10 TCP connections at any one time. If two connections are reserved for a direct host connection, then the server logic needs to make sure it doesn’t use more than 8 simultaneous connections.
Receive / Buffer Data
The actual receiving and buffering of incoming data on port 80 should be done at the TCP/IP layer in the stack; however, the HTTP server application should make sure all the data has been received. This is much more important for the POST, since the POSTed data needs to be included in the processing of the request. At a minimum for the GET and HEAD, the first line needs to be received to process the HTTP method and URL.
After the request has been received, the headers need to be parsed to determine the purpose of the request. To offer the most basic server functionality, only the first line needs to be parsed. Recall from the snippet above that the first line of an HTTP request looks like this:
This makes the parsing logic very simple. The first word of the first line is the request type – GET, HEAD, POST, etc. Following the request type is the URL, and following that is the supported HTTP version of the client. At a minimum, GET and HEAD must be supported by the server so processing for the two should be implemented. Any other request type could result in the server returning a 405 (method not allowed) error code.
Parsing the rest of the headers is not necessary to support GET and HEAD but could be helpful for POST to get the content length. It may also be advantageous at this time to log the request to a serial console or internal file system.
Process HTTP GET
The HTTP GET is a request for a file, so this processing routine can simply scan the internal or external file system for the requested file. If the file is found, it should be opened and the file handle should be passed on for further processing. If it is not found, the proper error code should be returned.
Build / Send Headers
Response headers should always be sent back to the client any time a connection is accepted – even if the server is overloaded. The server may refuse a connection, but if it is accepted, care should be taken to return an appropriate response. Recall from above what response headers look like:
The first line sent back contains the HTTP version supported by the server as well as the response code and response string for the client to interpret. Additionally, the server needs to tell the client what type of data is being returned. Finally, for embedded HTTP servers, connection header should be returned, indicating to the client that the server is going to close the connection after the response has been sent. Since embedded devices have limited resources, every connection is valuable.
Build / Send Document
If the request is for a valid file and the headers have already been sent, the server must then return the actual file data, whether it is for an HTML file, picture, or style sheet. Assuming only the headers have been sent and there is a valid file handle available, the following logic can be used to return the file:
Finally, clean up the request by closing the connection with the client to make it available for the next request. This should be a simple Ethernet stack call which, upon completion, can send the routine back to the first state to listen for incoming connections again.
If you are considering Wi-Fi or 802.15.4 for your next wireless design, and if cost and power consumption are important factors to you, 802.15.4 has significant advantages in both categories. With advancements in today’s microcontrollers, bridging 802.15.4 end devices to an IP network can be done cost-effectively. Many open source libraries such as lwIP and FreeRTOS can help to get your application up and running quickly. Add an embedded HTTP server to your wireless bridge and now you have a device that you can monitor, configure, and control remotely from anything with a web browser.
- LwIP – A Lightweight TCP/IP Stack. http://savannah.nongnu.org/projects/lwip.
- Barry, Richard. FreeRTOS – A Free Professional Grade RTOS Supporting 27 Architectures, Including ARM7, ARM9, Cortex-M3, RX600, MSP430, MSP430X, MicroBlaze, AVR, X86, PIC32, PIC24, DsPIC, H8S, HCS12 and 8051, 2004. Real Time Engineers Ltd. Retrieved May 15, 2011, from http://www.freertos.org
- Berners-Lee, T., Fielding, R., and Frystyk, H. Hypertext Transfer Protocol – HTTP/1.0, February 19, 1996. Retrieved April 17, 2011, from http://www.w3.org/Protocols/HTTP/1.0/draft-ietf-http-spec.html.
- Fielding, R., Gettys, J., Mogul, J., Frystyk, H., Masinter, L., Leach, P., et al. Hypertext Transfer Protocol – HTTP/1.1, June, 1999. Retrieved May 8, 2011, from http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html.
- Port Numbers, May 2, 2011. Internet Assigned Numbers Authority. Retrieved May 8, 2011, from http://www.iana.org/assignments/port-numbers.
- Krishnamurthy, B., Mogul, J. C., and Kristol, D. M. Key Differences Between HTTP/1.0 and HTTP/1.1, (n.d.). Retrieved April 19, 2011, from http://www8.org/w8-papers/5c-protocols/key/key.html.