Skip to main content
Described how to calculate content length.
Source Link
Nick Gammon
  • 38.9k
  • 13
  • 70
  • 126

Problem now is the Content-length... How do I calculate it ?

Do you absolutely need it? If you do, instead of building up the entire content first, I suggest two passes.

First pass outputs to a dummy class which simply calculates the length, second pass actually outputs. Something like this:

// outputting class that just counts output
class DummyOutput : public Print
{
private:
  unsigned long length_;
  
public:
  void begin () 
    { 
    length_ = 0; 
    }
  virtual size_t write (byte c)
    {
    length_++;
    return 1;
    }
  unsigned long getLength () const { return length_; }
  
};  // end of DummyOutput

DummyOutput countOutput;  // instance of DummyOutput

void setup ()
  {
  Serial.begin (115200);
  Serial.println ();
  Serial.println ("Starting");
 
  Print * outputter;  // where to write to
  
  for (int pass = 1; pass <= 2; pass++)
    {
    randomSeed (1);
    switch (pass)
     {
     case 1: outputter = &countOutput;
             countOutput.begin ();
             break;
             
     case 2: outputter = &Serial;
             break;
     } // end of switch
      
    // generate some output
    for (int i = 0; i < 25; i++)
      {
      outputter->print (random (5000));
      outputter->print ('\n');
      }
      
    switch (pass)
     {
     case 1: Serial.print (F("Content-length: "));
             Serial.println (countOutput.getLength ());
             break;
             
     case 2: break;
     } // end of switch
    
    }  // end of for loop
  }  // end of setup

void loop ()
  {
  }  // end of loop
  

Output:

Starting
Content-length: 121
1807
249
73
3658
3930
1272
2544
878
2923
2709
4440
3165
4492
3042
2987
2503
2327
1729
3840
2612
4303
3169
2709
2157
4560

By generating the same output in two passes you can first just calculate the length (without outputting) and the second time you can output that length first, and then output the actual data.


Problem now is the Content-length... How do I calculate it ?

Do you absolutely need it? If you do, instead of building up the entire content first, I suggest two passes.

First pass outputs to a dummy class which simply calculates the length, second pass actually outputs. Something like this:

// outputting class that just counts output
class DummyOutput : public Print
{
private:
  unsigned long length_;
  
public:
  void begin () 
    { 
    length_ = 0; 
    }
  virtual size_t write (byte c)
    {
    length_++;
    return 1;
    }
  unsigned long getLength () const { return length_; }
  
};  // end of DummyOutput

DummyOutput countOutput;  // instance of DummyOutput

void setup ()
  {
  Serial.begin (115200);
  Serial.println ();
  Serial.println ("Starting");
 
  Print * outputter;  // where to write to
  
  for (int pass = 1; pass <= 2; pass++)
    {
    randomSeed (1);
    switch (pass)
     {
     case 1: outputter = &countOutput;
             countOutput.begin ();
             break;
             
     case 2: outputter = &Serial;
             break;
     } // end of switch
      
    // generate some output
    for (int i = 0; i < 25; i++)
      {
      outputter->print (random (5000));
      outputter->print ('\n');
      }
      
    switch (pass)
     {
     case 1: Serial.print (F("Content-length: "));
             Serial.println (countOutput.getLength ());
             break;
             
     case 2: break;
     } // end of switch
    
    }  // end of for loop
  }  // end of setup

void loop ()
  {
  }  // end of loop
  

Output:

Starting
Content-length: 121
1807
249
73
3658
3930
1272
2544
878
2923
2709
4440
3165
4492
3042
2987
2503
2327
1729
3840
2612
4303
3169
2709
2157
4560

By generating the same output in two passes you can first just calculate the length (without outputting) and the second time you can output that length first, and then output the actual data.

Source Link
Nick Gammon
  • 38.9k
  • 13
  • 70
  • 126

You have used 461 out of 2048 of your RAM bytes for string literals alone. At the very least, use the F() macro where you can, eg.

client.println(F("POST /v1/sensors HTTP/1.1"));
client.println(F("Host: api.terrariums.eu")); // SERVER ADDRESS HERE TOO
client.println(F("Content-Type: application/json"));
client.println(F("Authorization: Basic bW9kdWxlMzoxMzIxMzI="));
client.println(F("Connection: close"));
client.print(F("Content-Length: "));

Ditto for Serial.print and lcd.print where you are printing strings.

After that, what Majenko suggested is a good idea. Using a custom library is well and good, but JSON is easy enough to output directly. Just make a small function to do it for you.