Author Topic: Overview of interfacing between the application and HTML  (Read 9639 times)

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3068
    • View Profile
    • uTasker
Overview of interfacing between the application and HTML
« on: October 11, 2007, 11:37:50 AM »
Hi All

Interfacing between the application and HTML - in order to general dynamic content or pass information - is in fact very simple. Generating dynamic content involves parsing the HTML content and replacing escape sequences, whereby the parsing and manipulation details are intergrated in the project files.

The actual interpreter part belongs to the application and is thus very flexible.

The following is a quick guide which has served as useful in the past.


All interfacing between the Browser and the application takes place in the file webinterface.c. There are the following calls from the web server part (which doesn’t need to be understood in itself):

- fnIsSelected()   the web server asks the application whether a check box or other such field is to be displayed as active or not (eg. Whether a port input is high or low)

- fnHandleWeb()  the web server passes received parameters to the application (eg. A change of a setting such as a port output level)

- fnInsertString() the web server asks the application to fill out text to be displayed on the web side (eg. Display a counter value, define a colour, size, etc.)

 
The rest is basically defined in the html files which can be loaded by ftp and modified as required (they are not compiled into the code as performed by most embedded suites and so can even be changed by users without means to compile the project (eg. To translate the web pages into other languages etc. or to personalise them for a specific customer).

An example: Look at the source to the file “0Menu.html” where you will see the following lines:

<form action=/0 name=r>
Email address <input maxLength=40 size=40 name=M value="£vE0" £Dm0><input type=submit value="Enter" name=r £Dm0></form>


"£vE0" informs the web server that this field is to be filled out by the application and so it will cause fnInsertString() to be called and the application returns in this case an email address to be displayed.


£Dm0 informs the web server that it must request the application as to whether the field should be displayed as enabled (can be changed and not grey) or disabled (can not be modified and is grey). This causes fnIsSelected() to be called so that the application can decide how it should be displayed.


name=M is a reference to the form which is sent when the user clicks on the “Enter” button (when enabled). This causes the web server to call fnHandleWeb() so that the data received (in this case a new email address) can be passed to the application.

 
By simply adding new references in the html and supporting them equivalently in the application it is very easy to built interactive and dynamic web browser interfaces.

If you use the simulator you can simply put a break point in these routines and see how it all interacts. Then it is simple to modify and test new parameters – simulate it to ensure it all works well and then compile with Codewarrior and load to the target – it will then work without any debugging effort on the hardware…




Comments welcome.

Regards

Mark

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3068
    • View Profile
    • uTasker
Re: Overview of interfacing between the application and HTML
« Reply #1 on: October 12, 2007, 12:00:49 PM »
Hi All

It is quite common that when a command has been received via the web interface, the information for the displayed web page is not immediately available.

Examples are when data has to first be collected from external devices via a serial interface or another Ethernet based protocol.

In such cases a method is required which allows the resulting web page to be sent after all details have become available - this is called DELAYED SERVING in the uTasker project. The following illustrates a typical example application and its use:

First of all, ensure that #define SUPPORT_DELAY_WEB_SERVING is active in config.h (in the HTTP section) so that the support is enabled.

In the handling routine fnHandleWeb() we assume that there is support for toggling output ports, which may look like this:

Code: [Select]
        case 'O':                                          // toggle out bit states
            fnTogglePortOut(*ptrData);
            fnEventMessage(MY_TASK, OWN_TASK, E_TREAT_NEW_PORTS);  // send an event to my task
            return DELAY_SERVING;                           // delay serving the page until the event has been handled


This example toggles an output port based on the input to fnHandleWeb(). Depending on the output state, and the reaction of an external piece of equipment, the state displayed when returning the web page can be different. It may take a short time before the new state is stable and so the return value is set to DELAY_SERVING. This will stop the default web page from being returned immediately and the TCP connection will remain open in this state until ready. In this example an event is sent to a task which will be handling the detail about determining the final state.

The task “later” causes the web page to be served by calling:

            fnServeDelayed('B', 0);

‘B’ is the file reference to be served (it can thus also cause different web pages to be served based on the actual state determined). Since the details of the web page content are also now known and stable, the content will be correct even if they have taken some time to have been collected.



Regards

Mark


« Last Edit: October 11, 2008, 10:40:42 AM by mark »

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3068
    • View Profile
    • uTasker
Re: Overview of interfacing between the application and HTML
« Reply #2 on: November 13, 2009, 02:04:59 PM »
Hi All

Here is an additional 'practical' guide to adding some simple strings. It is very easy to do but can already start performing useful things...

Regards

Mark


1) The use of the pound sign as control character:
The good thing about this is that Browsers don’t display it, even if it is put at bad locations – one less fortunate thing is that a US keyboard doesn't actually have it on it...! However it doesn’t have to be this – it can be any other which doesn’t normally appear in text and HTML commands. See config.h
            #define WEB_PARAMETER_GENERATION                             // support of parameter generating (eg. manipulating select and adding values)
            #define WEB_PARAMETER_HANDLING                               // support  handling of received web parameters
            #define WEB_PARSER_START          '£'                        // this symbol is used in Web pages to instruct parsing to begin
            #define WEB_INSERT_STRING         'v'
            #define WEB_DISABLE_FIELD         'D'
            #define WEB_NOT_DISABLE_FIELD     'd'
            #define WEB_SELECTED_FIELD        's'
            #define WEB_INSERT_DYNAMIC        'H'
          //#define WEB_ESCAPE_LEN             5                         // defaults to 4 if not defined


As you see, you can define all control characters as you feel fit. This will at least overcome the problem of the missing key.

2. To get you going on parsing here is a more detailed example.
I suggest that you even remove all content of fnInsertString() since it is quite large in the demo and, although case statements help (in comparison) to if () {} else if{} else if{} at some point they do get rather big and then it can be difficult to get your bearings.

3. In an HTML file simply try the following.
I assume here that you change the pound sign to the dollar sign [define WEB_PARSER_START '$'] (beware that you would however not be able to use the dollar sign in text of it were really chosen – you can decide the best for yourself – the others remain as they are).


Hello my name is $vMB {these are my initials but you can use your own if you like and change the use below}


Load this HTML file to the board (or better the simulator). If you view the page it will simply display this: “Hello my name is $vMB
However the routine fnInsertString() will have been called due to the fact that the parser had found the sequence $v – it then passes parameters “MB” to the routine. Initially it doesn't do anything and lets the control sequence through.

4. Now edit fnInsertString() as follows:

#define MAX_SIMPLE_INSERT 100 // depends on you maximum content
    static       CHAR cValue[MAX_SIMPLE_INSERT];                         // space to hold statistic string !!Must be static!!!
    CHAR *cPtr = 0;
    if (*ptrBuffer++ == 'M') {
        static const CHAR Mark[] = "Mark Butcher";
        uStrcpy(cValue, Mark);
        *usLengthToSend = (sizeof(Mark) - 1);
    }
    return cValue;


When this now runs it will serve the following: “Hello my name is Mark Butcher” {or your own name if you have inserted it instead}

The routine above has simply interpreted the ‘M’ to know that it needs to insert the string. It could also use the following ‘B’ to distinguish sub-decisions (like name of wife MW, or of child MC etc.). Also the length of the interpreter sequence can be increased by defining a longer value of WEB_SCAPE_LEN (but it is very rare that two characters is not enough (62 x 62 possibilities already gives 3’844 decisions) – but sometimes it does help to be able to use less cryptic values… As you see, the handler is in fact not that complicated but can of course grow with increased number of permutations (then it is up to the programmer to keep it well managed so that he/she doesn’t get lost as work increases).

Note that values (eg. ADC values) can be displayed – simply insert the value into the string – eg.

    else if ("A") {                     // an ADC value is to be displayed
        static const unsigned short usADC[8] = {1,2,3,4,5,6,7,8}; // test values
        unsigned char ucADC = (*ptrBuffer - '0');         // which input is to be displayed? (0..7)
        if (ucADC < 8 ) {                // check valid range
            fnBufferHex(usADC[ucADC], (sizeof(usADC[0]) | WITH_LEADIN), cValue); // insert string value in HEX
            *usLengthToSend = 6;                                     // 0x0000 - fixed string length
        }
    }


This uses fixed values for test purposes but could be real values from registers.

In the HTML file simply edit

Hello my name is $vMB<br>
ADC0 = $vA0<br>
ADC1 = $vA1<br>
ADC2 = $vA2<br>
ADC3 = $vA3<br>
ADC4 = $vA4<br>
ADC5 = $vA5<br>
ADC6 = $vA6<br>
ADC7 = $vA7<br>


Load the page and (with the second test code above) the web page now looks like:

Hello may name is Mark Butcher
ADC0 = 0x0001
ADC1 = 0x0002
ADC2 = 0x0003
ADC3 = 0x0004
ADC4 = 0x0005
ADC5 = 0x0006
ADC6 = 0x0007
ADC7 = 0x0008


5. Now add your own extensions display the data that you would like to see
... good luck!!