Author Topic: Generating HTML (fnInsertString() in webInterface.c)  (Read 9730 times)

Offline Thomas

  • Newbie
  • *
  • Posts: 17
    • View Profile
Generating HTML (fnInsertString() in webInterface.c)
« on: October 15, 2007, 03:17:43 PM »
Hi!

I need to create a table consisting of about 5 columns and a maximum of 255 rows. Each row will be built from a total of about 64 bytes consisting of different parameters.

I've been looking into the webInterface a little bit now and wonder how this would be best to solve. I was thinking to just keep a template of one row containing all the html formatting and data place holders, and just fill out the neccessary data when called through fnInsertString(). Having a HTML file with 255 $vnn references..

But I wonder about size limitations. One complete row including all HTML formatting and data might be around 400bytes or so. How are the packets sent and split? Thinking about how to make a reasonably efficent transer. I see a reference to "dynamic HTML" but no implementation. What was the intention for that?

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3236
    • View Profile
    • uTasker
Re: Generating HTML (fnInsertString() in webInterface.c)
« Reply #1 on: October 15, 2007, 04:19:10 PM »
Hi Thomas

Yes, the define HTTP_DYNAMIC_CONTENT is intended for generation of content which is not predefined. There is no demo of this in the project but generating tables of variable lengths is a good example of where it can be useful.

You have probably seen that a counter is added to the HTTP structure (each HTTP session has its own counter)

    unsigned short usDynamicCnt;                                         // reference during dynamic content generation

This is used later to manage the progress of the build up of dynamic content.

Here is how it can work:

1. When the parser encounters the escape sequence for dynamic content ($Hxx for example) it calls fnInsertString() from the applications webInterface.c. Rather than calling this with length = 0 (as is the case when strings are to be inserted) it calls it with a length (!= 0) - this is the length remaining in the current TCP transmit buffer.

2. fnInsertString() then can insert the correct contents. If there is not enough space for a line of table it can skip until the next frame. It can use the session counter to keep track of now many lines of the table have already been generated (for example).

3. For the start of the table (when usDynamicCnt is zero) it first inserts the HTML code for the table start.

4. For each line of the table it copies HTML code for the content (strings derived from variable values for example). It fits as many lines into the TCP tx buffer space as possible.

5. When all variables have been added, it adds the end of the table.

Here is an extract of some old code which was used to build up a table of temperature values collected over a period of time - the table increased in size over time. It was inserted in fnInsertString() and added the temperature plus a time stamp per line.

 
Code: [Select]
               static const signed char cStartTable[] = "<TABLE border=""1""><CAPTION><EM>Temperature history</EM></CAPTION><TR><TH>Date<TH>Time<TH>Temperature<br>(Celcius)";
                static const signed char cEndTable[] = "</TABLE><br><br>";

                // We can add our own content here.
                // we don't try to shift inside of the buffer since our data will generally fill several buffers. Instead
                // we halt the html file at its present location and fill as many frames as possible. At the end we restart html
                // possibly after short last frame.
                http_session->usDynamicCnt++;
                if (http_session->usDynamicCnt == 1) {
    usLen++;
                    *usMaxLen -= (usLen);
    return (usFrameLength - usLen);  // parameter list cut off, handle it next time around
                }
                else if (http_session->usDynamicCnt >= 2) {
                    static signed char cTableLine[] = "<TR><TD>14.10.2005<TD>12:24:50<TD>+25";
                    unsigned short usTableLength = 0;

                    ptrBuffer--;                     // overwrite the Dynamic data field
                    http_session->usUnacked = 0;

                    if (http_session->usDynamicCnt == 2) {
                      // create a table
                      memcpy(ptrBuffer, (unsigned char *)cStartTable, (sizeof(cStartTable)-1));

                      usTableLength += (sizeof(cStartTable)-1);
                      ptrBuffer += (sizeof(cStartTable)-1);
                    }


                    while (usTableLength < (HTTP_BUFFER_LENGTH - sizeof(cTableLine)-1)) {
                        if (fnGetTempLog((unsigned short)((http_session->usDynamicCnt)++ - 2), &cTableLine[8], &cTableLine[22], &cTableLine[34])) {
                            // close table
                            if (usTableLength < (HTTP_BUFFER_LENGTH - sizeof(cEndTable)-1)) {
                              memcpy(ptrBuffer, (unsigned char *)cEndTable, (sizeof(cEndTable)-1));
                              usTableLength += (sizeof(cEndTable)-1);

                              http_session->usDynamicCnt = 0;                   // terminated
                              http_session->usUnacked = 2;                      // complete buffer was overwritten
                            }
                            break;
                        }
                        memcpy(ptrBuffer, (unsigned char *)cTableLine, (sizeof(cTableLine)-1));
                        usTableLength += (sizeof(cTableLine)-1);
                        ptrBuffer += (sizeof(cTableLine)-1);
                    }
                    return usTableLength;
                }
            }

Unfortunately this technique has not been used in the project for a very long time and the code is almost certainly no longer compatible. In addition I am not sure that it correctly handles repetitions of TCP frames (it may lose lines in (?)).

I hope that gives you an idea of how it could work. I will try to get a tested example added to the project in the near future, including correct handling of TCP repetitions if it proves to be flawed at the moment.

Regards

Mark
« Last Edit: October 16, 2007, 07:02:13 PM by mark »