Assemble text String to send via HTTP

I have a number of variables from which I must assemble a text String to send HTTP via GPRS.
However, when I attempt to Serial.print the Strings for clarification, I have the following problem:
Variables:

char latHex[9];
char latNS[2];
char lonHex[10];
char lonEW[2];
int myVolts;
String msgID;
String myDeviceID;
int mySignal;
char txSpeed[4];

My Code to assemble text String:

msgTX1 = String(latHex) + "#" + String(latNS) + "#" + String(lonHex) + "#" + String(lonEW) + "#";
msgTX2 = String(myVolts) + "#" + msgID + "#" + myDeviceID + "#" + String(mySignal) + "#" + String(txSpeed);

I cannot print both msgTX1 and msgTX2 with:

  msgTX1 = String(latHex) + "#" + String(latNS) + "#" + String(lonHex) + "#" + String(lonEW) + "#";
  delay(100);
  Serial.println(msgTX1);
  delay(100);
  msgTX2 = String(myVolts) + "#" + msgID + "#" + myDeviceID + "#" + String(mySignal) + "#" + String(txSpeed);
  delay(100);
  Serial.println(msgTX2);
  delay(100);

The above code outputs the following to Serial Monitor:

41#90#IS003#0#000

Which is msgTX2

However, if I comment out as follows:

  msgTX1 = String(latHex) + "#" + String(latNS) + "#" + String(lonHex) + "#" + String(lonEW) + "#";
  delay(100);
  Serial.println(msgTX1);
  delay(100);
//  msgTX2 = String(myVolts) + "#" + msgID + "#" + myDeviceID + "#" + String(mySignal) + "#" + String(txSpeed);
//  delay(100);
//  Serial.println(msgTX2);
//  delay(100);

I get the following outputs to Serial Monitor:

01854E3E#S#01ACE346#E#

Which is msgTX1 and correct.
Likewise, if I comment out the code for msgTX1 only, I get msgTX2 without a problem.
The problem is that I cannot print both msgTX1 and msgTX2.
I must now combine the msgTX1 and msgTX2 to obtain the final Tx String.

Why would you want to combine it? Just printing the data achieves the same.

Serial.print(latHex);
Serial.print("#");
etc

Which board are you using? On boards with limited memory, the general advise is not to use the String class. And if you do, do not concatenate the way you do it using "+" but use '+='

msgTxt1 += String(latHex);
msgTxt1 += "#";
etc

One of the problems is that each String object that you use requires a minimum of 6 bytes (without the actual data).

For further advise, please post your complete sketch.

1 Like

I second that.
post your complete sketch.

Many thanks, this works:

  msgTX += String(latHex);
  msgTX += "#";
  msgTX += String(latNS);
  msgTX += "#";
  msgTX += lonHex;
  msgTX += "#";
  msgTX += String(lonEW);
  msgTX += "#";
  msgTX += String(myVolts);
  msgTX += "#";
  msgTX += msgID;
  msgTX += "#";
  msgTX += myDeviceID;
  msgTX += "#";
  msgTX += String(mySignal);
  msgTX += "#";
  msgTX += String(txSpeed);

The complete sketch is too large to post.

I have tested this. You can post 120000 characters. This is 117 kB
Look at the filesize of your sketch I. bet it is less than 50 kB.
With an estimated average length of 40 characters for each line
your code could have 3000 lines

I doubt that. If you post it don't forget to use code tags (I've seen that you have been around for a long time so you more-than-likely don't need this reminder :wink:) And if it doesn't fit in the limits mentioned by @StefanL38 you can split it in a sensible way over two posts or attach it.

And if the sketch is "too large", you might have other mistakes like functions that have a String object as an argument and you just use the String object instead of a reference to that String object.

A second/third pair of eyes can always help.

Yes, absolutely.
Here is my sketch - still work in progress and I know there is a lot that needs to be cleaned up.
I am running a barebones ATMEGA328PB.


#include <avr/sleep.h>
#include <avr/wdt.h>
#include <Vcc.h>                // library to read battery voltage
#include "SIM800L.h"

//int myVolts;
Vcc vcc;
float v;

#define MAXIMUM_GPS_DURATION_SEC 1200//
#define MAXIMUM_REG_DURATION_SEC 240
char gpsValid[2];
float myLatGeo;
float myLonGeo;
char gpsLat[11];
char latNS[2];
char gpsLon[12];
char lonEW[2];
char latHex[9];
char lonHex[10];
int myKMPH;
int mySignal;
char txSignal[3];
char txSpeed[4];
String msgTX1;
String msgTX2;
String msgTX;
char txVolts[3];
int myVolts;



volatile int watchdog_counter;
int wakeCount;

String msgID;
String myDeviceID = "IS003";

#define SIM800_RST_PIN 7
#define SIM800_DTR_PIN 13

SIM800L* sim800l;

int BUZZER = 2;
int GPS_PWR = 5;
boolean AT_cmd_result = false;

#define DEBUG true

//String response = "";
boolean status;

bool ModuleState = false;

// watchdog interrupt
ISR (WDT_vect)
{
  watchdog_counter++;
  //  wdt_disable();  // disable watchdog
}  // end of WDT_vect

void sleepNOW() {

   // disable ADC
  ADCSRA = 0;

  // clear various "reset" flags
  MCUSR = 0;
  // allow changes, disable reset
  WDTCSR = bit (WDCE) | bit (WDE);
  // set interrupt mode and an interval
  WDTCSR = bit (WDIE) | bit (WDP3) | bit (WDP0);    // set WDIE, and 8 seconds delay
  wdt_reset();  // pat the dog

  set_sleep_mode (SLEEP_MODE_PWR_DOWN);
  noInterrupts ();           // timed sequence follows
  sleep_enable();

  //  // turn off brown-out enable in software
  //  MCUCR = bit (BODS) | bit (BODSE);
  //  MCUCR = bit (BODS);
  interrupts ();             // guarantees next instruction executed
  sleep_cpu ();
}

void setup()
{
  Serial.begin(9600);
  Serial.println("BOOT");

  // Initialize the hardware Serial1
  Serial1.begin(9600);
  delay(1000);

  Serial1.println("AT+IPR=9600");
  delay(100);
  Serial1.println("AT&W");
  delay(100);

  Serial.print("CutOut-L80-800L-");
  Serial.println(myDeviceID);

  pinMode(GPS_PWR, OUTPUT);// GPS Pin
  digitalWrite(GPS_PWR, HIGH);// GPS OFF

  pinMode(BUZZER, OUTPUT);
  // BUZZER - BOOT
  digitalWrite(BUZZER, HIGH);
  delay(100);
  digitalWrite(BUZZER, LOW);

  intSIM800L();
  getPowerMode();
  setPowerNormal();
  delay(1000);
  getSignal();
  delay(1000);
  getRegistered();

  // BUZZER - READY
  digitalWrite(BUZZER, HIGH);
  delay(100);
  digitalWrite(BUZZER, LOW);
  delay(100);
  digitalWrite(BUZZER, HIGH);
  delay(100);
  digitalWrite(BUZZER, LOW);

  sleep800L();

  getGPSrmc();
  msgID = "90";
  sendHTTP();

  /*
    wakeCount 5 == ~1 minute
    wakeCount 10 == ~2 minute
    wakeCount 25 == ~5 minute
    wakeCount 50 == ~10 minute
    wakeCount 75 == ~13 minute
    wakeCount 86 == ~15 minute
    wakeCount 172 == ~30 minute
  */
  wakeCount = 50;
}

void intSIM800L() {
  // Equivalent line with the debug enabled on the Serial
  sim800l = new SIM800L((Stream *)&Serial1, SIM800_RST_PIN, 200, 512, (Stream *)&Serial);
  Serial.println("Start of test protocol");
  // Wait until the module is ready to accept AT commands
  while (!sim800l->isReady()) {
    Serial.println(F("Problem to initialize AT command, retry in 1 sec"));
    delay(1000);
  }
  // Active echo mode (for some module, it is required)
  sim800l->enableEchoMode();
  Serial.println("Module ready");
}

void getPowerMode() {
  // Check Power Mode
  Serial.print("Power Mode ");
  Serial.println(sim800l->getPowerMode());
  delay(500);
  /* POWER MODES
    "AT+CFUN?"    // Check the current power mode
    "AT+CFUN=0"   // Switch minimum power mode
    "AT+CFUN=1"   // Switch normal power mode
    "AT+CFUN=4"   // Switch sleep power mode
  */
}

void setPowerNormal() {
  // Set Power Mode NORMAL
  Serial.println(sim800l->setPowerMode(NORMAL));
}

void getSignal() {
  // Wait for the GSM signal
  uint8_t signal = sim800l->getSignal();
  while (signal <= 0) {
    delay(1000);
    signal = sim800l->getSignal();
    mySignal = signal;
  }
  sprintf(txSignal, "%02d", mySignal);
  Serial.print("txSignal: ");
  Serial.println(txSignal);
}

void getRegistered() {
  NetworkRegistration network = sim800l->getRegistrationStatus();
  while (network != REGISTERED_HOME && network != REGISTERED_ROAMING) {
    delay(1000);
    network = sim800l->getRegistrationStatus();
  }
  if (network == 5) {
    Serial.print("Network: ");
    Serial.println(network);
  }
  /*
    case '0' : return NOT_REGISTERED;
    case '1' : return REGISTERED_HOME;
    case '2' : return SEARCHING;
    case '3' : return DENIED;
    case '5' : return REGISTERED_ROAMING;
    default  : return NET_UNKNOWN;
  */
}

void loop() {

  sleepNOW(); //Go to sleep!

  Serial.print("Wake Count Set: ");
  Serial.println(wakeCount);
  delay(50);

  Serial.print("Sleep Count: ");
  Serial.println(watchdog_counter);
  delay(50);

  if (watchdog_counter >= wakeCount)
  {
    Serial.println("800L Awake");
    delay(50);
    awake800L();
    getGPSrmc();
    msgID = "91";
    sendHTTP();
    watchdog_counter = 0;
  }
}

void sleep800L() {
  // Set Power Mode SLEEP
  Serial.println(sim800l->setPowerMode(SLEEP));

  Serial1.println("AT+CSCLK=2");

  Serial.println(F("800L Going to SLEEP "));
  delay(100);
}

void awake800L() {
  //  digitalWrite(SIM800_DTR_PIN, LOW);
  Serial.println(sim800l->setPowerMode(NORMAL));

  Serial1.println("AT");
  delay(500);
  Serial1.println("AT");
  delay(500);
  Serial1.println("AT+CSCLK=0");
  Serial.println(F("Going to AWAKE "));

  sendATcmd("AT+CFUN=1", 10, "OK");
}

void sendHTTP() {
  myVolts = Vcc::measure(1000, 1100);
  myVolts = (myVolts / 100);

  awake800L();
  delay(1000);
  Serial1.println("AT");
  delay(500);

  Serial.println(F("--------------------GET Message----------------------"));
  msgTX += String(latHex);
  msgTX += "#";
  msgTX += String(latNS);
  msgTX += "#";
  msgTX += lonHex;
  msgTX += "#";
  msgTX += String(lonEW);
  msgTX += "#";
  msgTX += String(myVolts);
  msgTX += "#";
  msgTX += msgID;
  msgTX += "#";
  msgTX += myDeviceID;
  msgTX += "#";
  msgTX += String(mySignal);
  msgTX += "#";
  msgTX += String(txSpeed);

  Serial.println(msgTX);
  int lenTX = msgTX.length();
  Serial.print("msgTX.length: ");
  Serial.println(lenTX);
  msgTX = "";

// Still working on the below code - this not working
//  const char URL[] = "https//:www.xxxxxxxxxxxxxxxx.dedicated.xxx/5000";
//  const char CONTENT_TYPE[] = "text";
//  const char PAYLOAD[] = "0185777E#S#01ACC033#E#36#91#IS003#31#001";

  const char APN[] = "flickswitch";
  // Setup APN for GPRS configuration
  bool success = sim800l->setupGPRS(APN);
  while (!success) {
    success = sim800l->setupGPRS(APN);
    delay(5000);
  }
  Serial.println(F("GPRS config OK"));

  // Establish GPRS connectivity (5 trials)
  bool connected = false;
  for (uint8_t i = 0; i < 5 && !connected; i++) {
    delay(1000);
    connected = sim800l->connectGPRS();
  }

  Serial.println(F("Start HTTP POST..."));

  // Do HTTP POST communication with 10s for the timeout (read and write)
  uint16_t rc = sim800l->doPost(URL, CONTENT_TYPE, PAYLOAD, 10000, 10000);
  if (rc == 200) {
    // Success, output the data received on the serial
    Serial.print(F("HTTP POST successful ("));
    Serial.print(sim800l->getDataSizeReceived());
    Serial.println(F(" bytes)"));
    Serial.print(F("Received : "));
    Serial.println(sim800l->getDataReceived());
  } else {
    // Failed...
    Serial.print(F("HTTP POST error "));
    Serial.println(rc);
  }

  // Close GPRS connectivity (5 trials)
  bool disconnected = sim800l->disconnectGPRS();
  for (uint8_t i = 0; i < 5 && !connected; i++) {
    delay(1000);
    disconnected = sim800l->disconnectGPRS();
  }

  if (disconnected) {
    Serial.println(F("GPRS disconnected !"));
  } else {
    Serial.println(F("GPRS still connected !"));
  }

  delay(5000);
  sleep800L();
}


String sendData(String command, const int timeout, boolean debug)
{
  String response = "";

  Serial1.println(command);
  delay(20);
  long int time = millis();
  while ((time + timeout) > millis())
  {
    while (Serial1.available())
    {
      char c = Serial1.read();
      response += c;
    }
  }
  if (DEBUG)
  {
    Serial.print(response);
    delay(100);
  }
  return response;
}

bool sendATcmd(String AT_cmd, int AT_cmd_maxTime, char readReply[])
{
  int   trycnt = 0;
  bool  status = false;
  Serial.print(F("AT command:"));
  Serial.println(AT_cmd);
  delay(50);
  while (trycnt < AT_cmd_maxTime) {
    Serial1.println(AT_cmd);
    if (Serial1.find(readReply)) {
      AT_cmd_result = true;
      break;
    }
    ++trycnt;
  }
  Serial.print(F("Result:"));
  if (true == AT_cmd_result) {
    Serial.print(AT_cmd);
    Serial.println(F(" DONE"));
    status = true;
  } else {
    Serial.println(F("FAILED"));
  }
  AT_cmd_result = false;
  return status;
}

bool moduleStateCheck()
{
  int i = 0;
  bool moduleState = false;
  for (i = 0; i < 5; i++)
  {
    String msg = String("");
    Serial1.println("AT");
    if (msg.indexOf("OK") >= 0)
    {
      Serial.println("A9G was ON.");
      moduleState = true;
      return moduleState;
    }
    delay(1000);
  }
  return moduleState;
}

void getGPSrmc() {
  // Wake Up GPS
  digitalWrite (GPS_PWR, LOW); // turn POWER_GPS ON
  delay(1000);
  Serial.println("Got to getGPS");

  // RMC Only
  Serial.println("$PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29");
  delay(2000);

  char gpsResponse[82] = {0}; // 80 chars + null terminator
  //  while (Serial.available()) Serial.read(); // Clear all ACK logs

  const unsigned char MAX_gpsCOUNT = 4;
  unsigned char gpsCount = 0;
  bool gpsSuccess = false;
  do {
    for (int s = 0; s < MAXIMUM_GPS_DURATION_SEC; s++) {
      do {
        while (Serial.available()) gpsResponse[0] = Serial.read();
      }
      while (gpsResponse[0] != '$'); // Wait for response message
      for (unsigned char c = 0; c < sizeof(gpsResponse) - 1; c++) {
        while (!Serial.available());
        gpsResponse[c] = Serial.read(); // Capture response character
        if (gpsResponse[c] == '\r') gpsResponse[c] = 0x00; // Ignore CR
        if (gpsResponse[c] == '\n') break; // LF means the end of one line of response
      }
      Serial.println(gpsResponse);
      delay(50);

      //GNRMC,070932.860,A,2551.3716,S,02810.7482,E,0.84,290.21,081122,,,A*7C
      const char* foundGPS = "GPRMC";
      char* p;
      p = strstr (gpsResponse, foundGPS);
      if (p) {
        // Check that GPS has a Valid message (A==Valid / V==Not Valid)
        strncpy(gpsValid, gpsResponse + 17, 1);
        gpsValid[1] = '\0';

        if (gpsValid[0] == 65) {// A==Dec 65

          // Get Latitude
          char gpsLat[10];
          strncpy(gpsLat, gpsResponse + 19, 4);
          strncpy(&gpsLat[4], gpsResponse + 24, 4);
          gpsLat[8] = '\0';

          float myLatGeo0 = atof(gpsLat);
          float myLatGeo1 = myLatGeo0 / 1000000;
          float latNmea = myLatGeo1 * 100;
          uint16_t wholeDegrees = 0.01 * latNmea;
          myLatGeo = wholeDegrees + (latNmea - 100.0 * wholeDegrees) / 60.0;

          Serial.print("Lat DD.dddd: ");
          Serial.println(myLatGeo, 6);
          delay(50);
          Serial.print("Lat DEC: ");
          Serial.println(gpsLat);
          delay(50);

          sprintf(latHex, "%08lX", atol(gpsLat));
          Serial.print("Lat HEX: ");
          Serial.println(latHex);
          delay(50);

          // Get NS
          strncpy(latNS, gpsResponse + 29, 1);
          latNS[1] = '\0';
          Serial.print("NS: ");
          Serial.println(latNS);

          // Get Longitude
          char gpsLon[10];
          strncpy(gpsLon, gpsResponse + 31, 5);
          strncpy(&gpsLon[5], gpsResponse + 37, 4);
          gpsLon[9] = '\0';

          float myLonGeo0 = atof(gpsLon);
          float myLonGeo1 = myLonGeo0 / 1000000;
          float lonNmea = myLonGeo1 * 100;
          uint16_t wholeDegreesLon = 0.01 * lonNmea;
          myLonGeo = wholeDegreesLon + (lonNmea - 100.0 * wholeDegreesLon) / 60.0;

          Serial.print("Lon DD.dddd: ");
          Serial.println(myLonGeo, 6);
          delay(50);
          Serial.print("Lon DEC: ");
          Serial.println(gpsLon);
          delay(50);
          sprintf(lonHex, "%08lX", atol(gpsLon));
          Serial.print("Lon HEX: ");
          Serial.println(lonHex);
          delay(50);

          // Get EW
          strncpy(lonEW, gpsResponse + 42, 1);
          lonEW[1] = '\0';
          Serial.print("EW: ");
          Serial.println(lonEW);
          delay(50);

          int i = 0;
          char *start_pch, *end_pch;
          char extracted_str[16];

          start_pch = gpsResponse - 1;

          end_pch = strstr (gpsResponse, ",");
          while ( end_pch != NULL ) {
            memset (extracted_str, 0, 16);
            strncpy (extracted_str, start_pch + 1, end_pch - start_pch - 1); //<----
            Serial.print(++i);
            Serial.print(": ");
            Serial.println(extracted_str);
            start_pch = end_pch;
            end_pch = strstr (end_pch + 1, ",");

            if (i == 8) {
              myKMPH = atoi(extracted_str);
              //              int KMPH = (atoi(extracted_str)) * 1.852);
              myKMPH = myKMPH * 1.852;
              sprintf(txSpeed, "%03d", myKMPH);
              Serial.print("txSpeed: ");
              Serial.println(txSpeed);

              //to print out the last value
              memset (extracted_str, 0, 16);
              strncpy (extracted_str, start_pch + 8, strlen(start_pch));
              //              Serial.print(++i);
              //              Serial.print(": ");
              //              Serial.println(extracted_str);
            }

          }
          gpsSuccess = true;
          break; // Not continue if found A (65)
        }// END if (gpsValid[0] == 65)

      } else {
        gpsSuccess = false;
      }
    }// END for (int s = 0; s < MAXIMUM_GPS_DURATION_SEC; s++)

    Serial.print("gpsCount: ");
    Serial.println(gpsCount);
    delay(50);

    //  } while (++gpsCount < MAX_gpsCOUNT && !gpsSuccess);
  } while (++gpsCount < MAX_gpsCOUNT && gpsSuccess);

  Serial.println("GPS Timeout");

  // Switch GPS OFF
  Serial.println("GPS OFF");
  delay(50);
  digitalWrite (GPS_PWR, HIGH); // turn POWER_GPS OFF
}

void readBattery()
{
  myVolts = Vcc::measure(1000, 1100);
  sprintf(txVolts, "%02d", myVolts);
}

Thanks

This is what I was talking about in my previous comment

Every time that you call that function, the full command is copied onto the stack. If that command is 100 bytes, that is 100 bytes of "wasted" RAM. If you use a reference, only the reference is placed on the stack which is only two bytes.

String sendData(String &command, const int timeout, boolean debug)
{

Another point is that you have not been 100% consistent in the use of the F macro; e.g.

Check all print and println statements. They apply both to Serial and Serial1.

You have two variables gpsLat, one at global level and one in getGPSrmc. This is confusing; at a later stage you might want to use the former and don't understand why it's always empty. The former also does not seem to be used, remove it. The same applies to gpsLon. So roughly 20 bytes saved :wink:

Note:
You still haven't explained why you first want to (or think that you need to) build a String.

Thanks, I have implemented the changes recommended by you.
I save about 9 bytes of ram.

I am not experienced enough to assemble the data to Post any other way :blush:

Your SIM800L is connected to serial1. Instead of building the String, just print as described in the first snip of post #2. Replace Serial in that snip by Serial1.

Ah, I think that I now see why

Do you have a link to the SIM800 libraryb that you use?

As soon as I have the HTTP Post functions, I will try this.
I am using this GSM Library:

But I need to change the following so that I can Post to a IP and Port.
Also I do not know what "CONTENT_TYPE" is and "PAYLOAD" requirement.

const char URL[] = "https://postman-echo.com/post";
const char CONTENT_TYPE[] = "application/json";
const char PAYLOAD[] = "{\"name\": \"morpheus\", \"job\": \"leader\"}";

With the library that you use you indeed will have to compose the message first.

For the content type, use application/text.
For the payload, use msgTx.c_str().

I get a compile error:
"initializer fails to determine size of 'PAYLOAD'"

Show the full code that caused the error.

This is the full code.
The error is in: void sendHTTP()
I have commented the error in the code


#include <avr/sleep.h>
#include <avr/wdt.h>
#include <Vcc.h>                // library to read battery voltage
#include "SIM800L.h"

//int myVolts;
Vcc vcc;
float v;

#define MAXIMUM_GPS_DURATION_SEC 1200//
#define MAXIMUM_REG_DURATION_SEC 240
char gpsValid[2];
float myLatGeo;
float myLonGeo;
//char gpsLat[11];
char latNS[2];
//char gpsLon[12];
char lonEW[2];
char latHex[9];
char lonHex[10];
int myKMPH;
int mySignal;
char txSignal[3];
char txSpeed[4];
String msgTX1;
String msgTX2;
String msgTX;
char txVolts[3];
int myVolts;



volatile int watchdog_counter;
int wakeCount;

String msgID;
String myDeviceID = "IS003";

#define SIM800_RST_PIN 7
#define SIM800_DTR_PIN 13

SIM800L* sim800l;

int BUZZER = 2;
int GPS_PWR = 5;
boolean AT_cmd_result = false;

#define DEBUG true

//String response = "";
boolean status;

bool ModuleState = false;

// watchdog interrupt
ISR (WDT_vect)
{
  watchdog_counter++;
  //  wdt_disable();  // disable watchdog
}  // end of WDT_vect

void sleepNOW() {

   // disable ADC
  ADCSRA = 0;

  // clear various "reset" flags
  MCUSR = 0;
  // allow changes, disable reset
  WDTCSR = bit (WDCE) | bit (WDE);
  // set interrupt mode and an interval
  WDTCSR = bit (WDIE) | bit (WDP3) | bit (WDP0);    // set WDIE, and 8 seconds delay
  wdt_reset();  // pat the dog

  set_sleep_mode (SLEEP_MODE_PWR_DOWN);
  noInterrupts ();           // timed sequence follows
  sleep_enable();

  //  // turn off brown-out enable in software
  //  MCUCR = bit (BODS) | bit (BODSE);
  //  MCUCR = bit (BODS);
  interrupts ();             // guarantees next instruction executed
  sleep_cpu ();
}

void setup()
{
  Serial.begin(9600);
  Serial.println("BOOT");

  // Initialize the hardware Serial1
  Serial1.begin(9600);
  delay(1000);

  Serial1.println(F("AT+IPR=9600"));
  delay(100);
  Serial1.println(F("AT&W"));
  delay(100);

  Serial.print(F("CutOut-L80-800L-"));
  Serial.println(myDeviceID);

  pinMode(GPS_PWR, OUTPUT);// GPS Pin
  digitalWrite(GPS_PWR, HIGH);// GPS OFF

  pinMode(BUZZER, OUTPUT);
  // BUZZER - BOOT
  digitalWrite(BUZZER, HIGH);
  delay(100);
  digitalWrite(BUZZER, LOW);

  intSIM800L();
  getPowerMode();
  setPowerNormal();
  delay(1000);
  getSignal();
  delay(1000);
  getRegistered();

  // BUZZER - READY
  digitalWrite(BUZZER, HIGH);
  delay(100);
  digitalWrite(BUZZER, LOW);
  delay(100);
  digitalWrite(BUZZER, HIGH);
  delay(100);
  digitalWrite(BUZZER, LOW);

  sleep800L();

  getGPSrmc();
  msgID = "90";
  sendHTTP();

  /*
    wakeCount 5 == ~1 minute
    wakeCount 10 == ~2 minute
    wakeCount 25 == ~5 minute
    wakeCount 50 == ~10 minute
    wakeCount 75 == ~13 minute
    wakeCount 86 == ~15 minute
    wakeCount 172 == ~30 minute
  */
  wakeCount = 50;
}

void intSIM800L() {
  // Equivalent line with the debug enabled on the Serial
  sim800l = new SIM800L((Stream *)&Serial1, SIM800_RST_PIN, 200, 512, (Stream *)&Serial);
  Serial.println(F("Start of test protocol"));
  // Wait until the module is ready to accept AT commands
  while (!sim800l->isReady()) {
    Serial.println(F("Problem to initialize AT command, retry in 1 sec"));
    delay(1000);
  }
  // Active echo mode (for some module, it is required)
  sim800l->enableEchoMode();
  Serial.println(F("Module ready"));
}

void getPowerMode() {
  // Check Power Mode
  Serial.print(F("Power Mode "));
  Serial.println(sim800l->getPowerMode());
  delay(500);
  /* POWER MODES
    "AT+CFUN?"    // Check the current power mode
    "AT+CFUN=0"   // Switch minimum power mode
    "AT+CFUN=1"   // Switch normal power mode
    "AT+CFUN=4"   // Switch sleep power mode
  */
}

void setPowerNormal() {
  // Set Power Mode NORMAL
  Serial.println(sim800l->setPowerMode(NORMAL));
}

void getSignal() {
  // Wait for the GSM signal
  uint8_t signal = sim800l->getSignal();
  while (signal <= 0) {
    delay(1000);
    signal = sim800l->getSignal();
    mySignal = signal;
  }
  sprintf(txSignal, "%02d", mySignal);
  Serial.print(F("txSignal: "));
  Serial.println(txSignal);
}

void getRegistered() {
  NetworkRegistration network = sim800l->getRegistrationStatus();
  while (network != REGISTERED_HOME && network != REGISTERED_ROAMING) {
    delay(1000);
    network = sim800l->getRegistrationStatus();
  }
  if (network == 5) {
    Serial.print(F("Network: "));
    Serial.println(network);
  }
  /*
    case '0' : return NOT_REGISTERED;
    case '1' : return REGISTERED_HOME;
    case '2' : return SEARCHING;
    case '3' : return DENIED;
    case '5' : return REGISTERED_ROAMING;
    default  : return NET_UNKNOWN;
  */
}

void loop() {

  sleepNOW(); //Go to sleep!

  Serial.print(F("Wake Count Set: "));
  Serial.println(wakeCount);
  delay(50);

  Serial.print(F("Sleep Count: "));
  Serial.println(watchdog_counter);
  delay(50);

  if (watchdog_counter >= wakeCount)
  {
    Serial.println(F("800L Awake"));
    delay(50);
    awake800L();
    getGPSrmc();
    msgID = "91";
    sendHTTP();
    watchdog_counter = 0;
  }
}

void sleep800L() {
  // Set Power Mode SLEEP
  Serial.println(sim800l->setPowerMode(SLEEP));

  Serial1.println(F("AT+CSCLK=2"));

  Serial.println(F("800L Going to SLEEP "));
  delay(100);
}

void awake800L() {
  Serial.println(sim800l->setPowerMode(NORMAL));

  Serial1.println(F("AT"));
  delay(500);
  Serial1.println(F("AT"));
  delay(500);
  Serial1.println(F("AT+CSCLK=0"));
  Serial.println(F("Going to AWAKE "));

  sendATcmd("AT+CFUN=1", 10, "OK");
}

void sendHTTP() {
  myVolts = Vcc::measure(1000, 1100);
  myVolts = (myVolts / 100);

  awake800L();
  delay(1000);
  Serial1.println(F("AT"));
  delay(500);

  Serial.println(F("--------------------GET Message----------------------"));
  msgTX += String(latHex);
  msgTX += "#";
  msgTX += String(latNS);
  msgTX += "#";
  msgTX += lonHex;
  msgTX += "#";
  msgTX += String(lonEW);
  msgTX += "#";
  msgTX += String(myVolts);
  msgTX += "#";
  msgTX += msgID;
  msgTX += "#";
  msgTX += myDeviceID;
  msgTX += "#";
  msgTX += String(mySignal);
  msgTX += "#";
  msgTX += String(txSpeed);

  Serial.println(msgTX);
  int lenTX = msgTX.length();
  Serial.print(F("msgTX.length: "));
  Serial.println(lenTX);
  msgTX = "";

// Still working on the below code - this now working - But only sends once on initial boot
  const char URL[] = "http://majorparallelogram1.dedicated.co.za:5000";
  const char CONTENT_TYPE[] = "application/text";

  const char PAYLOAD[] = "01854EA3#S#01ACE45D#E#36#91#IS003#31#001";// <<-- This works
//  const char PAYLOAD[] = msgTX.c_str();// <<-- This gives as Error: "initializer fails to determine size of 'PAYLOAD'"

  const char APN[] = "flickswitch";
  // Setup APN for GPRS configuration
  bool success = sim800l->setupGPRS(APN);
  while (!success) {
    success = sim800l->setupGPRS(APN);
    delay(5000);
  }
  Serial.println(F("GPRS config OK"));

  // Establish GPRS connectivity (5 trials)
  bool connected = false;
  for (uint8_t i = 0; i < 5 && !connected; i++) {
    delay(1000);
    connected = sim800l->connectGPRS();
  }

  Serial.println(F("Start HTTP POST..."));

  // Do HTTP POST communication with 10s for the timeout (read and write)
  uint16_t rc = sim800l->doPost(URL, CONTENT_TYPE, PAYLOAD, 10000, 10000);
  if (rc == 200) {
    // Success, output the data received on the serial
    Serial.print(F("HTTP POST successful ("));
    Serial.print(sim800l->getDataSizeReceived());
    Serial.println(F(" bytes)"));
    Serial.print(F("Received : "));
    Serial.println(sim800l->getDataReceived());
  } else {
    // Failed...
    Serial.print(F("HTTP POST error "));
    Serial.println(rc);
  }

  // Close GPRS connectivity (5 trials)
  bool disconnected = sim800l->disconnectGPRS();
  for (uint8_t i = 0; i < 5 && !connected; i++) {
    delay(1000);
    disconnected = sim800l->disconnectGPRS();
  }

  if (disconnected) {
    Serial.println(F("GPRS disconnected !"));
  } else {
    Serial.println(F("GPRS still connected !"));
  }

  delay(5000);
  sleep800L();
}


//String sendData(String command, const int timeout, boolean debug)
//{
  String sendData(String &command, const int timeout, boolean debug)
{
  String response = "";

  Serial1.println(command);
  delay(20);
  long int time = millis();
  while ((time + timeout) > millis())
  {
    while (Serial1.available())
    {
      char c = Serial1.read();
      response += c;
    }
  }
  if (DEBUG)
  {
    Serial.print(response);
    delay(100);
  }
  return response;
}

bool sendATcmd(String AT_cmd, int AT_cmd_maxTime, char readReply[])
{
  int   trycnt = 0;
  bool  status = false;
  Serial.print(F("AT command:"));
  Serial.println(AT_cmd);
  delay(50);
  while (trycnt < AT_cmd_maxTime) {
    Serial1.println(AT_cmd);
    if (Serial1.find(readReply)) {
      AT_cmd_result = true;
      break;
    }
    ++trycnt;
  }
  Serial.print(F("Result:"));
  if (true == AT_cmd_result) {
    Serial.print(AT_cmd);
    Serial.println(F(" DONE"));
    status = true;
  } else {
    Serial.println(F("FAILED"));
  }
  AT_cmd_result = false;
  return status;
}

bool moduleStateCheck()
{
  int i = 0;
  bool moduleState = false;
  for (i = 0; i < 5; i++)
  {
    String msg = String("");
    Serial1.println("AT");
    if (msg.indexOf("OK") >= 0)
    {
      Serial.println("A9G was ON.");
      moduleState = true;
      return moduleState;
    }
    delay(1000);
  }
  return moduleState;
}

void getGPSrmc() {
  // Wake Up GPS
  digitalWrite (GPS_PWR, LOW); // turn POWER_GPS ON
  delay(1000);
  Serial.println("Got to getGPS");

  // RMC Only
  Serial.println("$PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29");
  delay(2000);

  char gpsResponse[82] = {0}; // 80 chars + null terminator
  //  while (Serial.available()) Serial.read(); // Clear all ACK logs

  const unsigned char MAX_gpsCOUNT = 5;
  unsigned char gpsCount = 0;
  bool gpsSuccess = false;
  do {
    for (int s = 0; s < MAXIMUM_GPS_DURATION_SEC; s++) {
      do {
        while (Serial.available()) gpsResponse[0] = Serial.read();
      }
      while (gpsResponse[0] != '$'); // Wait for response message
      for (unsigned char c = 0; c < sizeof(gpsResponse) - 1; c++) {
        while (!Serial.available());
        gpsResponse[c] = Serial.read(); // Capture response character
        if (gpsResponse[c] == '\r') gpsResponse[c] = 0x00; // Ignore CR
        if (gpsResponse[c] == '\n') break; // LF means the end of one line of response
      }
      Serial.println(gpsResponse);
      delay(50);

      //GNRMC,070932.860,A,2551.3716,S,02810.7482,E,0.84,290.21,081122,,,A*7C
      const char* foundGPS = "GPRMC";
      char* p;
      p = strstr (gpsResponse, foundGPS);
      if (p) {
        // Check that GPS has a Valid message (A==Valid / V==Not Valid)
        strncpy(gpsValid, gpsResponse + 17, 1);
        gpsValid[1] = '\0';

        if (gpsValid[0] == 65) {// A==Dec 65

          // Get Latitude
          char gpsLat[10];
          strncpy(gpsLat, gpsResponse + 19, 4);
          strncpy(&gpsLat[4], gpsResponse + 24, 4);
          gpsLat[8] = '\0';

          float myLatGeo0 = atof(gpsLat);
          float myLatGeo1 = myLatGeo0 / 1000000;
          float latNmea = myLatGeo1 * 100;
          uint16_t wholeDegrees = 0.01 * latNmea;
          myLatGeo = wholeDegrees + (latNmea - 100.0 * wholeDegrees) / 60.0;

          Serial.print("Lat DD.dddd: ");
          Serial.println(myLatGeo, 6);
          delay(50);
          Serial.print("Lat DEC: ");
          Serial.println(gpsLat);
          delay(50);

          sprintf(latHex, "%08lX", atol(gpsLat));
          Serial.print("Lat HEX: ");
          Serial.println(latHex);
          delay(50);

          // Get NS
          strncpy(latNS, gpsResponse + 29, 1);
          latNS[1] = '\0';
          Serial.print("NS: ");
          Serial.println(latNS);

          // Get Longitude
          char gpsLon[10];
          strncpy(gpsLon, gpsResponse + 31, 5);
          strncpy(&gpsLon[5], gpsResponse + 37, 4);
          gpsLon[9] = '\0';

          float myLonGeo0 = atof(gpsLon);
          float myLonGeo1 = myLonGeo0 / 1000000;
          float lonNmea = myLonGeo1 * 100;
          uint16_t wholeDegreesLon = 0.01 * lonNmea;
          myLonGeo = wholeDegreesLon + (lonNmea - 100.0 * wholeDegreesLon) / 60.0;

          Serial.print("Lon DD.dddd: ");
          Serial.println(myLonGeo, 6);
          delay(50);
          Serial.print("Lon DEC: ");
          Serial.println(gpsLon);
          delay(50);
          sprintf(lonHex, "%08lX", atol(gpsLon));
          Serial.print("Lon HEX: ");
          Serial.println(lonHex);
          delay(50);

          // Get EW
          strncpy(lonEW, gpsResponse + 42, 1);
          lonEW[1] = '\0';
          Serial.print("EW: ");
          Serial.println(lonEW);
          delay(50);

          int i = 0;
          char *start_pch, *end_pch;
          char extracted_str[16];

          start_pch = gpsResponse - 1;

          end_pch = strstr (gpsResponse, ",");
          while ( end_pch != NULL ) {
            memset (extracted_str, 0, 16);
            strncpy (extracted_str, start_pch + 1, end_pch - start_pch - 1); //<----
            Serial.print(++i);
            Serial.print(": ");
            Serial.println(extracted_str);
            start_pch = end_pch;
            end_pch = strstr (end_pch + 1, ",");

            if (i == 8) {
              myKMPH = atoi(extracted_str);
              //              int KMPH = (atoi(extracted_str)) * 1.852);
              myKMPH = myKMPH * 1.852;
              sprintf(txSpeed, "%03d", myKMPH);
              Serial.print("txSpeed: ");
              Serial.println(txSpeed);

              //to print out the last value
              memset (extracted_str, 0, 16);
              strncpy (extracted_str, start_pch + 8, strlen(start_pch));
              //              Serial.print(++i);
              //              Serial.print(": ");
              //              Serial.println(extracted_str);
            }

          }
          gpsSuccess = true;
          break; // Not continue if found A (65)
        }// END if (gpsValid[0] == 65)

      } else {
        gpsSuccess = false;
      }
    }// END for (int s = 0; s < MAXIMUM_GPS_DURATION_SEC; s++)

    Serial.print("gpsCount: ");
    Serial.println(gpsCount);
    delay(50);

    //  } while (++gpsCount < MAX_gpsCOUNT && !gpsSuccess);
  } while (++gpsCount < MAX_gpsCOUNT && gpsSuccess);

  Serial.println("GPS Timeout");

  // Switch GPS OFF
  Serial.println("GPS OFF");
  delay(50);
  digitalWrite (GPS_PWR, HIGH); // turn POWER_GPS OFF
}

void readBattery()
{
  myVolts = Vcc::measure(1000, 1100);
  sprintf(txVolts, "%02d", myVolts);
}

This is the Serial Monitor Log:

12:48:43.157 -> Going to AWAKE 
12:48:43.157 -> AT command:AT+CFUN=1
12:48:43.197 -> Result:AT+CFUN=1 DONE
12:48:44.687 -> --------------------GET Message----------------------
12:48:44.724 -> 01854F59#S#01ACE23D#E#40#90#IS003#31#000
12:48:44.807 -> msgTX.length: 40
12:48:44.807 -> SIM800L : Send "AT+SAPBR=3,1,"Contype","GPRS""
12:48:44.887 -> SIM800L : End of transmission
12:48:44.887 -> SIM800L : Receive "AT+SAPBR=3,1,"Contype","GPRS"

12:48:44.967 -> OK
12:48:44.967 -> "
12:48:44.967 -> SIM800L : Send "AT+SAPBR=3,1,"APN","flickswitch""
12:48:45.047 -> SIM800L : End of transmission
12:48:45.047 -> SIM800L : Receive "AT+SAPBR=3,1,"APN","flickswitch"

12:48:45.087 -> OK
12:48:45.087 -> "
12:48:45.087 -> GPRS config OK
12:48:46.077 -> SIM800L : Send "AT+SAPBR=1,1"
12:48:51.897 -> SIM800L : End of transmission
12:48:51.897 -> SIM800L : Receive "AT+SAPBR=1,1

12:48:51.936 -> OK
12:48:51.936 -> "
12:48:51.936 -> Start HTTP POST...
12:48:51.936 -> SIM800L : Send "AT+HTTPINIT"
12:48:51.977 -> SIM800L : End of transmission
12:48:52.017 -> SIM800L : Receive "AT+HTTPINIT

12:48:52.057 -> OK
12:48:52.057 -> "
12:48:52.097 -> SIM800L : Send "AT+HTTPPARA="CID",1"
12:48:52.097 -> SIM800L : End of transmission
12:48:52.137 -> SIM800L : Receive "AT+HTTPPARA="CID",1

12:48:52.178 -> OK
12:48:52.178 -> "
12:48:52.178 -> SIM800L : Send "AT+HTTPPARA="URL","http://majorparallelogram1.dedicated.co.za:5000""
12:48:52.377 -> SIM800L : End of transmission
12:48:52.377 -> SIM800L : Receive "AT+HTTPPARA="URL","http://majorparallelogram1.dedicated.co.za:5000"

12:48:52.497 -> OK
12:48:52.497 -> "
12:48:52.497 -> SIM800L : Send "AT+HTTPPARA="REDIR",1"
12:48:52.537 -> SIM800L : End of transmission
12:48:52.577 -> SIM800L : Receive "AT+HTTPPARA="REDIR",1

12:48:52.617 -> OK
12:48:52.617 -> "
12:48:52.617 -> SIM800L : Send "ATI"
12:48:52.658 -> SIM800L : End of transmission
12:48:52.707 -> SIM800L : Receive "ATI

12:48:52.707 -> SIM800 R14.18
12:48:52.707 -> "
12:48:52.707 -> SIM800L : initiateHTTP() - Support of SSL enabled
12:48:52.787 -> SIM800L : Send "AT+HTTPSSL=0"
12:48:52.827 -> SIM800L : End of transmission
12:48:52.827 -> SIM800L : Receive "AT+HTTPSSL=0

12:48:52.867 -> OK
12:48:52.867 -> "
12:48:52.867 -> SIM800L : Send "AT+HTTPPARA="CONTENT","application/text""
12:48:52.987 -> SIM800L : End of transmission
12:48:52.987 -> SIM800L : Receive "AT+HTTPPARA="CONTENT","application/text"

12:48:53.038 -> OK
12:48:53.077 -> "
12:48:53.077 -> SIM800L : Send "AT+HTTPDATA=40,10000"
12:48:53.117 -> SIM800L : End of transmission
12:48:53.152 -> SIM800L : Receive "AT+HTTPDATA=40,10000

12:48:53.187 -> DOWNLOAD
12:48:53.187 -> "
12:48:53.238 -> SIM800L : doPost() - Payload to send : 01854EA3#S#01ACE45D#E#36#91#IS003#31#001
12:48:53.797 -> SIM800L : Send "AT+HTTPACTION=1"
12:48:53.837 -> SIM800L : End of transmission
12:48:53.837 -> SIM800L : Receive "AT+HTTPACTION=1

12:48:53.877 -> OK
12:48:53.877 -> "
12:48:57.257 -> SIM800L : End of transmission
12:48:57.257 -> SIM800L : Receive "
12:48:57.257 -> +HTTPACTION: 1,200,0
12:48:57.297 -> "
12:48:57.297 -> SIM800L : readHTTP() - HTTP status 200
12:48:57.337 -> SIM800L : readHTTP() - Data size received of 0 bytes
12:48:57.427 -> SIM800L : Send "AT+HTTPREAD"
12:48:57.427 -> SIM800L : End of transmission
12:48:57.477 -> SIM800L : Receive "AT+HTTPREAD

12:48:57.517 -> OK
12:48:57.517 -> "
12:48:57.517 -> HTTP POST error 705
12:48:57.557 -> SIM800L : Send "AT+SAPBR=0,1"
12:48:57.877 -> SIM800L : End of transmission
12:48:57.877 -> SIM800L : Receive "AT+SAPBR=0,1

12:48:57.957 -> OK
12:48:57.957 -> "
12:48:57.957 -> GPRS disconnected !
12:49:02.907 -> SIM800L : Send "AT+CFUN?"
12:49:02.957 -> SIM800L : End of transmission
12:49:02.957 -> SIM800L : Receive "AT+CFUN?

12:49:02.957 -> +CFUN: 1
12:49:02.997 -> "
12:49:02.997 -> SIM800L : Send "AT+CFUN=4"
12:49:03.037 -> SIM800L : Send "AT+CFUN?"
12:49:05.377 -> SIM800L : End of transmission
12:49:05.377 -> SIM800L : Receive "
12:49:05.427 -> OK
12:49:05.427 -> "
12:49:05.427 -> 0
12:49:05.427 -> 800L Going to SLEEP 

That works because you create an array,

You basically create an array with 0 bytes space and assign it a pointer.

Below would be the way; PAYLOAD must be a pointer because c_str() returns a pointer to an array, not an array.

char *PAYLOAD = msgTx.c_str();

And you can completely get rid of the PAYLOAD variable if you put the msgTx in the doPost() call as shown below

uint16_t rc = sim800l->doPost(URL, CONTENT_TYPE, msgTx.c_str(), 10000, 10000);

The doPost() methods expect pointers to character arrays for the first three arguments, not character arrays. The difference is subtle. When you have an array, its name is actually a pointer to the first element of that array. So if you pass a variable like CONTENT_TYPE to the doPost*()* method, you actually pass the pointer to the first element of the CONTENT_TYPE array.

Additional comment

Although opinions differ, for easy maintenance this should be a global variable (in my opinion) declared near the top of the code. You don't want to dig through hundreds of lines of code to find where you have to change it if you ever have to in a few years time :smiley:

Other question regarding this: are you living in South Africa?

Yes, where are you living?