As devices are increasingly more networked, an embedded web server is becoming a standard way for users to interact with and configure an embedded device using a standard web browser. As an example, most pieces of networking equipment (such as routers and wireless access points) are configured this way. There are many ways to implement a web server. One way is to just write a monolithic program that handles the requests and outputs HTML using print statements. Without a lot of planning, you usually end up with something where logic is intermixed with presentation. The disadvantage of such an approach is that it quickly becomes very difficult to maintain your web application as it grows and changes. The current best practice with web application frameworks (such as Ruby on Rails) splits a web application into 3 distinct components (Model, View, Controller — MVC) so that changes to one component can be made with minimal impact to others. This article details a solution used in a recent project to implement such an architecture using the following open source components: SQLite, Clearsilver, and Python. The challenge was to find a solution that performed acceptably on a resource constrained 130MHz ARM-Linux system.
The requirements for the web application framework for this system are:
- Footprint must be fairly small — less than 10MiB.
- Must enable us to implement a clean MVC type architecture.
- Must support a high level language like python for rapid development.
- Includes a database.
- Reasonable performance — less than 1 second to render a typical page.
After researching and testing several options, the following components were chosen to implement the framework:
- Web Server: Cherokee (1MiB)
- Model: SQLite (290KiB)
- View: Clearsilver (170KiB)
- Controller: Python (2-3MiB)
Total size for the above components is about 4MiB.
The following sequence occurs during a typical web transaction:
- An HTTP request is received by Cherokee
- If the request matches the URI for the web application, Cherokee forwards the request to the web application framework via CGI.
- Clearsilver parses the HTTP headers (including CGI GET and POST parameters) and provides the data to python in a easy to access HDF format.
- Python looks at the URI and dispatches the request to the appropriate function. Data is extracted from the SQLite database and an HDF datastructure is created.
- Clearsilver is called to render the appropriate template. Data from the HDF datastructure is used in the template to provide the dynamic content in the page.
- The rendered HTML is passed back to Cherokee, and is then returned to the user’s web browser.
Each component is discussed in more detail in the following sections.
One of the issues with modern web frameworks is that most require a lot of processing power. Many frameworks are written in an interpreted language which tend to be not very efficient on embedded systems such as the 130MHz ARM-Linux system used in this project. As most of the application development for this project is done in Python, I tried several other Python based solutions with the following results:
- Django: takes 10 seconds to render a page
- webpy: takes 5 seconds to render a page
- Clearsilver/Python: takes about 1 second to render a page
Anything over 1 second is very slow for a web interface. With fastcgi, webpy could probably have been sped up to be acceptably fast, but I don’t think there is much hope for frameworks like django on this type of system. I have read of similar experiences trying to run Ruby-on-Rails on ARM-Linux systems. As I’m currently just using a basic CGI interface, the Clearsilver solution could also be sped up significantly as well, if the Python portion could be kept running between requests with fastcgi or a similar mechanism.
Cherokee Web Server
A web application typically consists of a web server (like Apache) and a program that provides the dynamic web content. Some of the functions of a web server are:
- receives HTTP requests
- handles the request by serving static files/images or routes the request to a program that outputs dynamic content
- encryption (SSL, TLS)
There are many web servers that can be used in embedded devices. Some of them are:
- Lighttpd (http://www.lighttpd.net )
- thttpd (http://www.acme.com/software/thttpd/ )
- Appweb (http://www.appwebserver.org/ )
- Boa (http://www.boa.org )
- Cherokee (http://www.cherokee-project.com )
- SHTTPD (http://shttpd.sourceforge.net/ )
Cherokee was chosen for this application because it provides a good balance between the size and functionality I am looking for. It is also included in the Openembedded (http://openembedded.org ) build system I am using. Other systems will have different requirements — use the one that fits your application best.
Clearsilver (http://www.clearsilver.net/ ) is the real gem that was discovered during this exercise. Clearsilver is a language-neutral HTML template system written in C. It is used as the templating system for many high volume sites such as Google Groups 2. Clearsilver also provides CGI handling functions and bindings to several languages including Python. The fact that it is written in C and is fast for high volume sites also makes it fast enough on slower embedded systems. Because Clearsilver is written in C, the templating system is already fast. Parts or all of the application can also be moved to C as needed to get the required performance. Having a performance upgrade path is nice. Clearsilver also forces a strict separation of application logic and presentation templates, which keeps things in line with the MVC architecture.
SQLite (http://www.sqlite.org/ ) is a small C library that implements a self-contained, embeddable, zero-configuration SQL database engine. SQLite works as expected and also has bindings to a number of languages including Python. A SQLite database is just a single file that requires no configuration, making it very easy to use. The database engine runs in the same process as the application using it, which increases performance because there is no context switch when running database operations. Because SQLite does not have its own process, it does not handle concurrency as well as other databases such as MySQL, but in an embedded system you seldom have more than one process using the database. SQLite provides some support for concurrency with reader/writer locks for the entire database. If your application is not real busy, this is often adequate if you need two processes to share some data.
Python is the glue that ties things together in this web application framework. It sits between Clearsilver and the database. The advantages of using a language like Python are rapid development and an extensive library. Python is considerably slower than C, but there is always the option to move parts of the application into C as needed.
Openembedded Build System
How does one put together a system with all these components? The answer is the Openembedded Build System (OE) (http://openembedded.org). OE includes support for all of the components discussed in this article.
The combination of Python, Clearsilver, and SQLite provides a compelling solution for a web application framework in an Embedded Linux System. The solution is reasonably small, performs well, and provides a path to improve performance if needed. We also get a clean architecture to create clean, maintainable web applications.
About the author — Cliff Brake owns BEC Systems, a consulting operation that helps customers utilize modern computer technologies in their products. BEC offers a range of services to make your embedded project a success including technology selection, development, troubleshooting, and training. Please visit our website (http://bec-systems.com ) for more information and other free resources.