Calculating Content Length

Hi Spark Community,

i have a Problem calculating the Content Length of a Post Request.

static uint16_t werte[60];
static uint8_t sec[60];
static uint8_t min[60];
static uint8_t hr[60];
static uint8_t day[60];
static uint8_t month[60];
static uint8_t year[60];

void ANALOGREAD() //Just for testing
{
    for(uint8_t i = 0; i<60;i++)
    {
        delay(300);
        werte[i] = i;
        sec[i] = Time.second();
        min[i] = Time.minute();
        hr[i] = Time.hour();
        day[i] = Time.day();
        month[i] = Time.month();
        year[i] = (Time.year()) % 2000;
    }
}    
void postRequest()
{
    client.connect(LIB_DOMAIN, 80);
    delay(20);
    client.println("POST /hakan/index2.php HTTP/1.1");
    client.println("Host: " LIB_DOMAIN);
    client.println("Content-Type: application/x-www-form-urlencoded");
    client.print("Content-Length: ");
    client.println(contentLength()); 
    client.println();
    clientPrint2();
    delay(20);
}
void clientPrint2()         //s0=12&d0=14-7-15 11:45:25&s1=....
{
    for(uint8_t i = 0; i < 60;i++)
    {
        if(i!=0)
        {
            client.print("&");
        }
        client.print("s");
        client.print(i);
        client.print("=");
        client.print(werte[i]);
        client.print("&d");
        client.print(i);
        client.print("=");
        client.print(year[i]);               // ändern
        client.print("-");
        client.print(month[i]);
        client.print("-");
        client.print(day[i]);
        client.print(" ");
        client.print(hr[i]);
        client.print(":");
        client.print(min[i]);
        client.print(":");
        client.print(sec[i]);
        delay(20);
    }
    delay(1000);
    postResponse();
}
uint16_t contentLength()
{
    uint16_t cL = 0;
    for(uint8_t i = 0; i < 60; i++)
    {
        char a[] = {werte[i]};
        cL += sizeof(a)/sizeof(char);
        char b[] = {day[i]};
        cL += sizeof(b)/sizeof(char);
        char c[] = {hr[i]};
        cL += sizeof(c)/sizeof(char);
        char d[] = {sec[i]};
        cL += sizeof(d)/sizeof(char);
        char e[] = {min[i]};
        cL += sizeof(e)/sizeof(char);
        char f[] = {month[i]};
        cL += sizeof(f)/sizeof(char);
        char g[] = {year[i]};
        cL += sizeof(g)/sizeof(char);
        cL -= 7; // Null Termination of each char[]
        
    }
    cL += (10*2)+(49*4);    //(i0-9)+(i10-59)
    cL += (60 * 7);         // "=" "=" "-" "-" " " ":" ":"
    cL += (60 *2);          // s & d
    cL += (60 *2)-1;        // "&"
    
    return cL;
}

0;14-7-15 12:23:48;
1;14-7-15 12:23:48;
2;14-7-15 12:23:48;
3;14-7-15 12:23:49;
4;14-7-15 12:23:49;
5;14-7-15 12:23:49;
6;14-7-15 12:23:50;
7;14-7-15 12:23:50;
8;14-7-15 12:23:50;
9;14-7-15 12:23:50;
10;14-7-15 12:23:51;
11;14-7-15 12:23:51;
12;14-7-15 12:23:51;
13;14-7-15 12:23:52;
14;14-7-15 12:23:52;
15;14-7-15 12:23:52;
16;14-7-15 12:23:53;
17;14-7-15 12:23:53;
18;14-7-15 12:23:53;
19;14-7-15 12:23:53;
20;14-7-15 12:23:54;
21;14-7-15 12:23:54;
22;14-7-15 12:23:54;
23;14-7-15 12:23:55;
24;14-7-15 12:23:55;
25;14-7-15 12:23:55;
26;14-7-15 12:23:56;
27;14-7-15 12:23:56;
28;14-7-15 12:23:56;
29;14-7-15 12:23:56;
30;14-7-15 12:23:57;
31;14-7-15 12:23:57;
32;;
;;
;;
;; an so on ...

After the Post, only half of the Post Request is cought by the Server. So i am making a mistake somewhere.
Anyone any ideas to Solve this Problem ?

Thx,
Dongamelo

try adding a 10ms delay between each client print, its not the best thing to have to do, but give it a go and see what happens.

Thx @Hootie81 ,

i knew that trick. But this is not my Problem. For example, if i write Content Length = 2000 everything will do fine, but the Response Header would be wrong. So i need the right/exact calculation of the Content Length to get the right Response Header which i need to decide the if values were saved in the external flash or not.

Thx

what about a different approach, forming the string to post with a strcpy and then strcat to add to it once the string is built work out the length of the whole string with strlen?

This is a snippet of what i use to help debugging…

char line[255];
    
    if(DEBUG){Serial.print("connecting... ");}
    if (clientx.connect(serverpbName, 80)) {
        
        if(DEBUG){
            Serial.print("connected to ");
            Serial.println(serverpbName);
        }
        delay(500);
        digitalWrite(LED, LOW);
        strcpy(line, "GET ");
        strcat(line, devid);
        strcat(line, " HTTP/1.1\r\n");
        clientx.print(line);
        if(DEBUG){Serial.print(line);}
        strcpy(line, "Host: ");
        strcat(line, serverpbName);
        strcat(line, "\r\n");
        clientx.print(line);
        if(DEBUG){Serial.print(line);}
        strcpy(line, "Connection: close\r\n");
        strcat(line, "Accept: text/html, text/plain\r\n");
        strcat(line, "Content-Length: 0\r\n");
        strcat(line, "User-Agent: Spark\r\n\r\n");
        clientx.print(line);
1 Like

I don’t think your contentLength() function is doing what you think it’s doing.

You might be better off using a String object to build your request, then just using String.length().

Another option could be to force the values to be zero-padded so that every record has a fixed length: s00=00&d00=14-07-15 09:47:03

Your other option with sending data is to BASE64 the data. In this case, 3 bytes of binary data get sent as four characters. In the case where you were sending a group of timestamps with a group of 8 bit numbers, this would be stored in RAM as 32 + 8 = 40 bits, or 5 bytes. Thus, a group of them would be 6 2/3 bytes each. To use your example, 60 lots timestamps with a 1 byte reading each would be 4000 bytes when BASE64 encoded.

I have some sample code using BASE64 if that helps. It is also useful for populating variables to be read by the Spark Core.

Darryl

1 Like

Hi All,

sry for late reply. I was on Holiday :slight_smile: . @Hootie81 my Post is too long to send it with one char[] . @dougal I also dont´t think its doing what i think it should do :slight_smile: . I now made it with String again. I didn´t wanted it to do that that way because my String was too long at first try, But now it works, confusing … . @vk2tds I do not really get it, but i would love to see youre sample code to work through.

Thx all

Hi All…

Here is my code to do some horrible things with sending data between the Spark and a server. Please bear in mind that this comes from a real project, so it might not be as clear as it could be.

The first bit defines some complex data structures.

#define CIRCUIT_COUNT 8

struct teridianBillingPosStruct {
    unsigned int start;
    unsigned int last;
    struct {
        unsigned int PP_POS_CNT;
        unsigned int PQ_POS_CNT;
        unsigned int PS_CNT;
    } count[CIRCUIT_COUNT + 1];
};

struct teridianBillingPosStruct teridianBillingPos;

char v_energy_pos[160];

This is standard C stuff. v_energy_pos is the variable that actually gets either pulled or pushed to the server. It is a base 64 representation of the raw data in the data structure. In this case we are talking mostly unsigned int, but it could be any C structure.

The next bit of code requests that the variables are encoded. This happens on every loop in my case when the underlying data has been updated.

void saveVariables(){
    base64_encode ((char *)&teridianBillingPos, sizeof (teridianBillingPos), v_energy_pos);

}

The previous function calls the following one, which returns Base64 data. The advantage with Base64 is that it can deal with binary data. It sends four characters for three bytes. There are standard Javascript functions to do the decode.

//
// Library Code
//

// base 64 - Convert from a binary blob to a string.
 static char encoding_table[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
                                'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
                                'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
                                'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
                                'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
                                'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
                                'w', 'x', 'y', 'z', '0', '1', '2', '3',
                                '4', '5', '6', '7', '8', '9', '+', '/'};
                                
static int mod_table[] = {0, 2, 1};


void base64_encode(char *data,
                    size_t input_length,
                    char *encoded_data) {
    // From http://stackoverflow.com/questions/342409/how-do-i-base64-encode-decode-in-c

    int  output_length = ((input_length - 1) / 3) * 4 + 4;
    encoded_data[output_length] = 0;

    for (unsigned int i = 0, j = 0; i < input_length;) {

        unsigned int octet_a = i < input_length ? (unsigned char)data[i++] : 0;
        unsigned int octet_b = i < input_length ? (unsigned char)data[i++] : 0;
        unsigned int octet_c = i < input_length ? (unsigned char)data[i++] : 0;

        unsigned int triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c;

        encoded_data[j++] = encoding_table[(triple >> 3 * 6) & 0x3F];
        encoded_data[j++] = encoding_table[(triple >> 2 * 6) & 0x3F];
        encoded_data[j++] = encoding_table[(triple >> 1 * 6) & 0x3F];
        encoded_data[j++] = encoding_table[(triple >> 0 * 6) & 0x3F];

    }
    
    for (int i = 0; i < mod_table[input_length % 3]; i++)
        encoded_data[output_length - 1 - i] = '=';
}

I hope this helps. Let me know if you have any questions.