Today, you often find powerful processors in embedded systems. Dedicated network routers and controllers for all kinds of machinery are examples of embedded systems. Processors like the Intel 80x86 or the AMD Elan are able to run multitasking operating systems, such as XINU or GNU/Linux in embedded PCs. These systems are small and usually do not have a keyboard or a display. Therefore it is difficult to set up their configuration. There are several widespread ways to set them up:
telnet
or SNMP
In this section, we look at a solution that uses HTTP connections
to control variables of an embedded system that are stored in a file.
Since embedded systems have tight limits on resources like memory,
it is difficult to employ advanced techniques such as SNMP and HTTP
servers. gawk
fits in quite nicely with its single executable
which needs just a short script to start working.
The following program stores the variables in a file, and a concurrent
process in the embedded system may read the file. The program uses the
site-independent part of the simple web server that we developed in
A Web Service with Interaction.
As mentioned there, all we have to do is to write two new procedures
SetUpServer()
and HandleGET()
:
function SetUpServer() { TopHeader = "<HTML><title>Remote Configuration</title>" TopDoc = "<BODY>\ <h2>Please choose one of the following actions:</h2>\ <UL>\ <LI><A HREF=" MyPrefix "/AboutServer>About this server</A></LI>\ <LI><A HREF=" MyPrefix "/ReadConfig>Read Configuration</A></LI>\ <LI><A HREF=" MyPrefix "/CheckConfig>Check Configuration</A></LI>\ <LI><A HREF=" MyPrefix "/ChangeConfig>Change Configuration</A></LI>\ <LI><A HREF=" MyPrefix "/SaveConfig>Save Configuration</A></LI>\ </UL>" TopFooter = "</BODY></HTML>" if (ConfigFile == "") ConfigFile = "config.asc" }
The function SetUpServer()
initializes the top level HTML texts
as usual. It also initializes the name of the file that contains the
configuration parameters and their values. In case the user supplies
a name from the command line, that name is used. The file is expected to
contain one parameter per line, with the name of the parameter in
column one and the value in column two.
The function HandleGET()
reflects the structure of the menu
tree as usual. The first menu choice tells the user what this is all
about. The second choice reads the configuration file line by line
and stores the parameters and their values. Notice that the record
separator for this file is "\n"
, in contrast to the record separator
for HTTP. The third menu choice builds an HTML table to show
the contents of the configuration file just read. The fourth choice
does the real work of changing parameters, and the last one just saves
the configuration into a file:
function HandleGET() { if (MENU[2] == "AboutServer") { Document = "This is a GUI for remote configuration of an\ embedded system. It is is implemented as one GAWK script." } else if (MENU[2] == "ReadConfig") { RS = "\n" while ((getline < ConfigFile) > 0) config[$1] = $2; close(ConfigFile) RS = "\r\n" Document = "Configuration has been read." } else if (MENU[2] == "CheckConfig") { Document = "<TABLE BORDER=1 CELLPADDING=5>" for (i in config) Document = Document "<TR><TD>" i "</TD>" \ "<TD>" config[i] "</TD></TR>" Document = Document "</TABLE>" } else if (MENU[2] == "ChangeConfig") { if ("Param" in GETARG) { # any parameter to set? if (GETARG["Param"] in config) { # is parameter valid? config[GETARG["Param"]] = GETARG["Value"] Document = (GETARG["Param"] " = " GETARG["Value"] ".") } else { Document = "Parameter <b>" GETARG["Param"] "</b> is invalid." } } else { Document = "<FORM method=GET><h4>Change one parameter</h4>\ <TABLE BORDER CELLPADDING=5>\ <TR><TD>Parameter</TD><TD>Value</TD></TR>\ <TR><TD><input type=text name=Param value=\"\" size=20></TD>\ <TD><input type=text name=Value value=\"\" size=40></TD>\ </TR></TABLE><input type=submit value=\"Set\"></FORM>" } } else if (MENU[2] == "SaveConfig") { for (i in config) printf("%s %s\n", i, config[i]) > ConfigFile close(ConfigFile) Document = "Configuration has been saved." } }
We could also view the configuration file as a database. From this point of view, the previous program acts like a primitive database server. Real SQL database systems also make a service available by providing a TCP port that clients can connect to. But the application level protocols they use are usually proprietary and also change from time to time. This is also true for the protocol that MiniSQL uses.