An increasing number of embedded systems exchange information with larger "soft" systems. Microsoft DCOM (older technology for connecting software components) is not realistic in smaller systems without MS Windows etc. Microsoft .NET Framework has (among many other things) support for Remote Procedure Calls (RPC) that replace DCOM - .NET Remoting and WebService. Both these are build upon the open text based protocols HTTP (exchange of the information - the transport) and SOAP/XML (information about the objects - the encoding). It is also possible to configure .NET systems to use other protocols (such as the XML-RPC.NET library replacing SOAP with XML-RPC), including custom solutions, but this possibility is not covered here.
Literature and examples in the field of .NET are almost exclusively focused on how larger "soft" systems in MS Windows environments connect. The text here is instead intended to show how to connect larger "soft" systems with small embedded systems (see figure below).
The code required to process the data generated and needed for call/return using Remote Procedure Call (RPC) with .NET Framework SOAP/XML procedures is quite simple. Basically it is just sending (and receiving) packages like follows (part of "Firmware" in picture above - for a corresponding request, see the "call" (SOAP) example in section Remote Procedure Calls (RPC) using XML below):
sprintf(sendBuffer, "<?xml version=\“1.0\” encoding = \“ISO-8859-1\” ?>\r\n"); sprintf(&sendBuffer[strlen(sendBuffer)], "<!-- simple SOAP return of the getWeather method from a weather wWbService -->\r\n"); sprintf(&sendBuffer[strlen(sendBuffer)], "<SOAP-ENV:Envelope\r\n"); sprintf(&sendBuffer[strlen(sendBuffer)], " xmlns:SOAP-ENV=\"http://..wc3.../soap-envelope/\"\r\n"); sprintf(&sendBuffer[strlen(sendBuffer)], " xmlns:xsi=\"http://..wc3.../XMLSchema-instance\"\r\n"); sprintf(&sendBuffer[strlen(sendBuffer)], " xmlns:xsd=\"http://..wc3.../XMLSchema\">\r\n"); sprintf(&sendBuffer[strlen(sendBuffer)], " <SOAP-ENV:Body>\r\n"); sprintf(&sendBuffer[strlen(sendBuffer)], " <ns1:getWeatherResponse xmlns:ns1 = \“urn:weatherweb\”\r\n"); sprintf(&sendBuffer[strlen(sendBuffer)], " SOAP-ENV:encoding-style=\“…soap-encoding\”>\r\n"); sprintf(&sendBuffer[strlen(sendBuffer)], " <return xsi-type=“xsd:string”>Horrible and Wet</return>\r\n"); sprintf(&sendBuffer[strlen(sendBuffer)], " </ns1:getWeatherResponse>\r\n"); sprintf(&sendBuffer[strlen(sendBuffer)], " </SOAP-ENV:Body>\r\n"); sprintf(&sendBuffer[strlen(sendBuffer)], "</SOAP-ENV:envelope>\r\n"); write_lan(lanp, sendBuffer, sizeof(sendBuffer));Due to the use of known, simple, readable, and standardised open protocols, it is fully realistic to include interfaces looking like distributed .NET Remoting or WebService objects on systems with limited capabilities. In addition to "impersonating" a .NET interface, such systems also need to have TCP/IP+Ethernet, or a serial port alternatively USB (but this requires more SW at the other end of that link).
Below is first a section describing Remote Procedure Calls (RPC) using XML, then one describing a minimalist implementation of a HTTP server for embedded systems, and finally a section describing minimalist implementations of .NET interfaces for embedded systems (.NET Remoting and WebService). The .NET part also provides basics for distributed objects in .NET, and a sketchy description how they work.
REST relies on HTTP itself for accessing and manipulating objects, remote procedure calling, etc (both transport and encoding), and XML (or possibly something else you like, such as JSON) for additional encoding (when needed). SOAP and XML-RPC are both designed to operate from a single URI with methods being invoked from within the request body. This fails to use URIs as they were designed to be used. A URI is a unique resource on the network and as such, each method in your RPC call should use a unique URI. Using REST this is the case, and depending on your request method, different actions can be invoked. REST uses HTTP as it was designed: if you want to get some data you use a HTTP GET request, if you want to delete a record from a database you use a HTTP DELETE request, and so on. Today many organisations provide REST interfaces: E.g. Twitter, Yahoo, eBay, and Amazon.
The basic REST design principle establishes a one-to-one mapping between create, read, update, and delete (CRUD) operations and HTTP methods:
Programming for RESTful SOA using XML. E.g. create "Robert" in the object "/users/":
POST /users HTTP/1.1 Host: myserver Content-Type: application/xml ... <?xml version="1.0"?> <user> <name>Robert</name> </user>E.g. get the representation of "Robert" in the object "/users/":
GET /users/Robert HTTP/1.1 Host: myserver Accept: application/xml ...XML-RPC is remote procedure calling using HTTP as the transport and XML as the encoding. XML-RPC is designed to be as simple as possible, while allowing complex data structures to be transmitted, processed and returned. Notable quite a few WebServices are implemented with XML-RPC.
<?xml version=“1.0” encoding = “ISO-8859-1” ?> <!-- simple XML-RPC call of the getWeather method from a weather WebService --> <methodCall> <methodName>weather.getWeather</methodName> <params> <param> <value><string>Aberdeen AB25</string></value> </param> </params> </methodCall>
SOAP is the same general idea as XML-RPC (see above), but more features: Enumerations, Polymorphism (type determined at run time), User defined data (such as named parameters). SOAP XML Documents are also more complex: Use namespaces, Formal "envelope" (Soap Header and Soap Body). Notably Microsoft Remoting and WebServices use SOAP.
A typical SOAP call might look like follows when its data are transferred over a network (TCP/IP and HTTP encapsulations excluded):
<?xml version=“1.0” encoding = “ISO-8859-1” ?> <!-- simple SOAP call of the getWeather method from a weather wWbService --> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://..wc3.../soap-envelope/" xmlns:xsi="http://..wc3.../XMLSchema-instance" xmlns:xsd="http://..wc3.../XMLSchema"> <SOAP-ENV:Body> <ns1:getWeather xmlns:ns1 = “urn:weatherweb” SOAP-ENV:encoding-style=“http:..w3c..soap-encoding”> <address xsi-type=“xsd:string”>Aberdeen AB25</address> </ns1:getWeather> </SOAP-ENV:Body> </SOAP-ENV:envelope>
Look at the content of the SOAP call above. It is a fairly simple and readable text that is send over networks "packaged" in HTTP request-response exchanges (also simple and readable text - see section Minimalist code for HTTP server that follows).
Compression, like "gzip", and secure communication, like "SSL", might be added. There are many such libraries available, but the issue of memory footprint on limited embedded systems only leaves a handful of viable candidates (see section "Examples, code, and articles")
For use of "gzip" compression of a HTTP message body, add the lines "Accept-Encoding: gzip" (telling that this sender will accept "gzip" compressed bodies in HTTP messages returned), and "Content-Encoding: gzip" (telling that the "body" part of this HTTP message is compressed using "gzip"), in the preceeding HTTP message header.
peer = getpeer_lan(PROTOCOL_TCP, 80); while (1) { lanp = wait_lan(peer); read_lan(lanp, req_buffer, sizeof(req_buffer)); if (!strcmp(“GET /status HTTP/1.0\r\n\r\n”, req_buffer)) { resplen = create_response_message(resp_buffer, “Hello World”); write_lan(lanp, resp_buffer, resplen); } close(lanp); }
... /* * Send log object "/logdump.xls" to EXCEL */ if (strncmp("GET /logdump.xls ", tbuf, 17) == 0) { /* Create the response message */ sprintf(response_message, "Dump of log data \t Values\n"); sprintf(&response_message[strlen(response_message)], "Donald \t 0x4711\n"); sprintf(&response_message[strlen(response_message)], "Duck \t 17\n"); /* Create response header */ sprintf(response_header, "HTTP/1.0 200 OK\r\n"); sprintf(&response_header[strlen(response_header)], "Content-type: application/vnd.ms-excel\r\n"); sprintf(&response_header[strlen(response_header)], "Content-length: %d\r\n", strlen(response_message)); sprintf(&response_header[strlen(response_header)], "\r\n"); } ...
Here is an introduction how to “Use .NET interacting with embedded systems - Possibilities with limited resources” (file in PDF format).
When a .NET based application on a Windows system (the Client - see code example below) manipulates a distributed object (deployed on the Server), the .NET Framework on the Client automatically creates and sends a HTTP request package from the Client to the Server.
The body of the HTTP request package generated by the client action holds the actual request to the object in SOAP/XML. Here is an example of a HTTP request package sent from a Client to a Server when the client application calls “obj.getValue()” (the actual request encoded with the "i2:getValue" tag):
When the request is served, the object (i.e. the Server) returns a HTTP response package. The body of this HTTP response package then holds the actual response from the object in SOAP/XML. The .NET Framework on the Client automatically interpretates the response, and updates that client application accordingly. Here is an example of a HTTP response package sent from Server to Client as response to a HTTP request package previously generated by the client application “obj.getValue()” call (the actual response encoded with the "i2:getValueResponse" tag):
Implementing .NET Remoting and WebService on an embedded system means receiving calls, interpretating calls, creating reponses, and returning responses, like the ones above. Compression might be interesting for a resource limited embedded system working with HTML, SOAP, and XML (see "how to" in section "Minimalist code for HTTP server ...". On one hand these are fairly verbose text based protocols (actually use 7 bits out of 8, many repeats, and so on - e.g. "gzip" compresses a 393 bytes SOAP package to 249 bytes, or ca 35% reduction), BUT on the other hand the code neded for performing compression and decompression use significant amounts of memory as well (see section "Examples, code, and articles" for alternatives).
The picture below shows a stripped down C-language implementation for processing the “obj.getValue()” example above:
The Dark horse" for implementing .NET Remoting and WebServices at embedded systems, IF they have ca 256 KBytes of flash and 64 KBytes of RAM, is the .NET Micro Framework (NETMF) Open Source .NET platform for resource-constrained devices. It provides an embedded system with "the whole enchilada" at hand here, and a lot more (including GUI and capability to run C# code).
A "proper" .NET Remoting or WebService server implementation has code that parses and interprets XML and SOAP. This approach costs memory (but not as much as .NET Micro Framework (NETMF) - see above). There are many XML and SOAP libraries available, but the issue of memory footprint on limited embedded systems only leaves a handful of viable candidates (see section "Examples, code, and articles").
A "poor man’s solution" is omitting true parsing of XML and SOAP, and just look for the "mission critical" SOAP/XML tags (like the "strstr()" search call for the "<i2:getValue " string in the “obj.getValue()” server code example picture above) and maybe some additional ones for safety, and then discard the rest. When implementing an .NET Remoting or WebService object, its interface is first coded in C# etc, and run on a .NET capable computer with LAN tapping software or application logging to record the HTTP and SOAP/XML packages actually exchanged for this specific objects interface. The server software is then coded to just interpret the critical parts of the received data according to the recorded HTTP + SOAP/XML request, and to return the recorded HTTP + SOAP/XML response with the critical parts modified with the values wanted.
Brief (for embedded systems "to the point") descriptions of this kind of "poor man’s solution" programming implementing basic servers for .NET Service and WebService objects (Client in CS, Server in C-language, and descriptions of the text actually sent on the LAN) are provided in the sections Remoting and WebServices gfurther down.
For more hands-on coding, go to section "Examples, code, and articles" further down.
The C-language source code example remotings.c implements a .NET WebService object "MyRemoteObject.soap" that has the methods "getValue()" and "setValue()".
A fairly comprehensive description of Remoting C# calls, and their corresponding SOAP & HTTP telegrams, are provided in Chapter 13 Remoting of the on-line book "XML Web Services and SOAP".
A WebService object can also provide a WSDL interface that returns an XML description of the different methods of the objects, their parameters, etc - i.e. their interfaces. Accessing the URL of a WebService object with a “?wsdl” appended (e.g. for the object "donaldDuck.asmx" at the server "http://www.mcduck.com/" it becomes “http://www.mcduck.com/donaldDuck.asmx?wsdl”) returns its interface description. This makes it possible for programmers to get the information manually (e.g. Internet Explorer), and for tools to retrieve it more or less automatically (e.g. MS Visual Studio). Microsoft also provides a command line tool for retrieving these descriptions and automatically generates proxy classes (source code) for use by your clients accessing the WebService object and its methods (e.g. in a command line window of a PC "C:\>wsdl /language:C# /out:DuckProxyClass.cs http://www.mcduck.com/donaldDuck.asmx?wdsl").
Different alternatives for a client to call a WebService object (GET, POST, etc) are described in the document “Embedded .NET WebService” (file in PDF). It also describes how to write a Web page to generate such calls directly from HTML form tags, and directly in the URL.
The C-language source code example webservices.c implements a .NET Remoting server object "MyWebServiceObject.asmx" that has the "wsdl" query possibility, and the methods "getValue()" and "setValue()". for both GET and POST.
A fairly comprehensive description of WebService C# calls, and their corresponding SOAP & HTTP telegrams, are provided in Chapter 1 Introduction to Web Services of the on-line book "XML Web Services and SOAP".
A simple possibility to study and play with WebServices is using Microsoft IIS on a PC running Windows. A brief description "Setting up IIS etc" is provided here (file in PDF format).
Here are C and CS source code and executable (PC/Windows) files with working examples from the introduction linked above:
"webmaster" for the domain "karnak" in Sweden ("se")