SoftwareSerial Parse incoming

Hello for all.

I use the code below to receive some data from SoftwareSerial:

while (Serial2.available()) {
    delay(1);
    c = Serial2.readString();

    Serial.println(c);

And I receive a incoming data from software serial like this:

+IPD,4,570:HTTP/1.1 200 OK
Date: Tue, 23 Apr 2019 12:50:06 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 51
Connection: keep-alive
Cache-Control: private
Server: Microsoft-IIS/10.0
X-Provisioner-Version: v3.3.15-07082018
X-Domain-Checked: FALSE
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
X-App-Status: 1
X-Cache-Status: BYPASS

{"kw":0.93,"email":"email@email.com","hw":"1234"}

I need only the last line {"kw":0.93,"email":"email@email.com","hw":"1234"} to parse after.

How to proceed with this question?

Thanks for all.

I'm guessing (since you have not told us) that each line ends with a linefeed character. Have a look at the second example in Serial Input Basics. Each time a line of text is received it will set the varaible newData to true. When that happens you can check the content of the received data to see if it contains the stuff you want. Perhaps check if the 2nd character (counting from 0) is 'k' .

...R

Thanks Robin,

I have tryed to use the example2 and example3, but dont work to this question.

I increase the const byte numChars = 220;

I changed the char endMarker = '\n'; to \r and \r\n

And my answer in debug is:

Sending Request...
Request Sent
This just in ... 

TCP Connection Closed

Set the start marker to {

joaodbm:
I have tryed to use the example2 and example3, but dont work to this question.

Example 3 needs a start marker and I don’t see any evidence of one in the text you posted

I increase the const byte numChars = 220;

It only needs to be a little bigger than the longests single line

I changed the char endMarker = ‘\n’; to \r and \r\n

It is not designed to check for 2 characters. If there is a ‘\n’ then that is sufficient. Alternatively if there is only a ‘\r’ then that would work. If the text includes both then either one will work

And my answer in debug is:

Post the complete program that shows that output.

You could also temporarily add this line into the function recvWithEndMarker() to see the ASCII value of every character received.

  while (Serial2.available() > 0 && newData == false) {
        rc = Serial2.read();
        Serial.println((byte) rc);  //  <------add this line

…R

Thanks again Robin.

The code is below:

#include <SoftwareSerial.h>
#include <ArduinoJson.h>

const byte rxPin = 2;
const byte txPin = 3;

String ssid = "SSID";
String password = "PASSWIFI";

SoftwareSerial Serial2 (rxPin, txPin);
String path = "/serialize.aspx?t=?";

String server = "MYSERVER";

String PostMessage = "token=?";

String messageLength = String(PostMessage.length());

String getRequest = "GET " + path + " HTTP/1.1\r\n" + "Host: " + server + "\r\n" + "Connection: keep-alive\r\n\r\n";

String getRequestLength = String(getRequest.length());

const byte numChars = 32;
char receivedChars[numChars];   // an array to store the received data
boolean newData = false;

void setup() {
  Serial.begin(9600);
  Serial2.begin(9600);
  delay(1000);
  reset();
  desconecta();
  //setMode("1");
  connectWifi();
}


void loop() {
  Serial2.println("AT+CIPMUX=1");
  delay(500);

  Serial2.println("AT+CIPSTART=4,\"TCP\",\"" + server + "\",80");
  if (Serial2.find("OK")) Serial.println("TCP Connection Ready");
  delay(500);
  Serial2.println("AT+CIPSEND=4," + getRequestLength);

  if (Serial2.find(">")) {
    Serial.println("Sending Request...");
    Serial2.print(getRequest);
  }

  //Serial.println(getRequest);

  if (Serial2.find("SEND OK")) Serial.println("Request Sent");
  //  while (!Serial2.available()) {};
  espRead();
  Serial2.println("AT+CIPCLOSE");
  if (Serial2.find("OK")) Serial.println("TCP Connection Closed");
  delay(5000);
}


void espRead() {
  static byte ndx = 0;
  char endMarker = '\n';
  char rc;

  while (Serial2.available() > 0 && newData == false) {
    rc = Serial2.read();
    Serial.println((byte) rc);
    if (rc != endMarker) {
      receivedChars[ndx] = rc;
      ndx++;

      if (ndx >= numChars) {
        ndx = numChars - 1;
      }
    }
    else {
      receivedChars[ndx] = '\0'; // terminate the string

      ndx = 0;
      newData = true;
    }
  }

  showNewData();

  //  String c;
  //  while (Serial2.available()) {
  //    delay(1);
  //    c = Serial2.readString();
  //
  //    Serial.println(c);
  //

  //
  //
  //
  //    //    //const size_t bufferSize = JSON_OBJECT_SIZE(2) + JSON_OBJECT_SIZE(3) + JSON_OBJECT_SIZE(5) + JSON_OBJECT_SIZE(8) + 370;
  //    //    const int capacity = JSON_OBJECT_SIZE(3) + 2 * JSON_OBJECT_SIZE(1);
  //    //
  //    //    StaticJsonDocument<capacity> doc;
  //    //
  //    //    deserializeJson(doc, Serial2.readString());
  //    //    // Parameters
  //    //
  //    //    const char* equipamento = doc["nome"]; //
  //    //
  //    //    // Output to serial monitor
  //    //    Serial.print("HW:");
  //
  //  }
  //

}

void showNewData() {
  if (newData == true) {
    Serial.print("This just in ... ");
    Serial.println(receivedChars);
    newData = false;
  }
}

void reset() {
  Serial.println("Resetting WiFi");
  Serial2.println("AT+RST");
  delay(1000);
  if (Serial2.find("OK")) Serial.println("Reset!");
}

void desconecta() {
  Serial.println("Desconectando WiFi");
  Serial2.println("AT+CWQAP");
  delay(1500);
  if (Serial2.find("OK")) Serial.println("Desconectado!");
}

void connectWifi() {
  //espClear();
  Serial.println("Connecting...");
  String CMD = "AT+CWJAP=\"" + ssid + "\",\"" + password + "\"";
  Serial2.println(CMD);
  delay(6000);
  while (!Serial2.available()) {};
  if (Serial2.find("OK")) Serial.println("Connected");
  else Serial.println("Couldn't connect to WiFi");
}

void setMode(String mode) {
  Serial.println("Setting Mode = " + mode);
  Serial2.println("AT+CWMODE=" + mode);
  delay(1000);
  espRead();
}

The answer of arduino is below;

Resetting WiFi
Reset!
Desconectando WiFi
Connecting...
Connected
TCP Connection Ready
Sending Request...
Request Sent
13
10
This just in ... 

TCP Connection Closed

In google chrome, my server show this:
{“kw":0.93,“email”:"email@email.com”,“hw”:“1234”}
Whitout HTML code, only json text.

The complete answer of arduino is:

+IPD,4,570:HTTP/1.1 200 OK
Date: Tue, 23 Apr 2019 12:55:49 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 218
Connection: keep-alive
Cache-Control: private
Server: Microsoft-IIS/10.0
X-Provisioner-Version: v3.3.15-07082018
X-Domain-Checked: FALSE
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
X-App-Status: 1
X-Cache-Status: BYPASS

{"kw":0.93,"email":"email@email.com","hw":"1234"}

All rest of code is ok, I only need the last line, i tryed many of codes.

The example on the link below is the closest. But did not work

But did not work

Some code that I'm not going to go hunt for did something. If that something were what you expected, you wouldn't say that the code did not work.

But, what the code actually does, and what you expect it to do are mysteries.

I'm not a fan of mysteries.

@OP

Please, check if you are seeing in your Serial Monitor this:
{kw:0.93,email:email@email.com,hw:1234}

and not this:
{"kw":0.93,"email":"email@email.com","hw":"1234"}

Because I have simulated your case using two Arduinos; where, if the this: {"kw":0.93,"email":"email@email.com","hw":"1234"} is entered as a part of message, there is a compilation error.

In my simulation, I have taken that there are 15 sub-messages in your message including the '1-line gap' between the last two sub-messages.

Sender codes:

#include<SoftwareSerial.h>
SoftwareSerial mySerial(3, 4);
char myData[] = "+IPD,4,570:HTTP/1.1 200 OK\nDate: Tue, 23 Apr 2019 12:50:06 GMT\nContent-Type: text/html; charset=utf-8\nContent-Length: 51\nConnection: keep-alive\nCache-Control: private\nServer: Microsoft-IIS/10.0\nX-Provisioner-Version: v3.3.15-07082018\nX-Domain-Checked: FALSE\nX-AspNet-Version: 4.0.30319\nX-Powered-By: ASP.NET\nX-App-Status: 1\nX-Cache-Status: BYPASS\n\n{kw:0.93,email:email@email.com,hw:1234}\n";

void setup()
{
  Serial.begin(9600);
  mySerial.begin(9600);
}

void loop()
{
  Serial.println(myData);
  mySerial.print(myData);
  delay(1000);
}

Receiver Codes:

#include<SoftwareSerial.h>
SoftwareSerial mySerial(3, 4); //SRX=DPin-3, STX=DPin-4
int nlCounter=0;
char myArray[100] = "";

void setup()
{
 Serial.begin(9600);
 mySerial.begin(9600); 
}

void loop()
{
  byte n = mySerial.available();
  if(n !=0)
  {
    char x = mySerial.read();
    if(x == '\n')
    {
      nlCounter++;
      if (nlCounter == 14)
      {
        mySerial.readBytesUntil('\n', myArray, 100);
        Serial.println(myArray);
        nlCounter = 0;
        char myArray[100] = "";
      }
    }
  }
}

Sender Screenshot:

Receiver Screenshot:
sm101.png

sm101.png

Sorry Paul,

Realy, the code works, but dont in this problem,

Ive tryed between two arduino's, like Golam has mentioned, and this works, but dont work when I try to parse the result from the tcp.

Maybe the problem is in the CR an NL.

I've been looking for a solution for over a week, and only today I decide to post in this forum.

You can't do stuff like this

  if (Serial2.find("SEND OK")) Serial.println("Request Sent");
  //  while (!Serial2.available()) {};
  espRead();

because Serial2.find() will consume all the characters that espRead() is hoping to receive.

Even if there was no 'find() the code in espRead() will almost certainly require several iterations of loop() before it has a full message. In your case, every time that loop() repeats the various .find() calls will screw everything up.

Maybe the simplest way to solve that dilemma is to have a variable that keeps track of whether the "SEND OK" has been received and if it has then don't do any of the calls to .find() and only do the call to espRead(). Conversely, if the "SEND OK" has not been received don't call espRead().

If it was my project I think I would just use espRead() for everything and never use .find()

...R

Thanks for all.

The code works now, with this code:

while (Serial2.available())
  {
    String line = Serial2.readStringUntil('\r');


    if (lines_received == 19) {

      json = line;
      //Serial.println(json);
    }
    lines_received++;
    //Serial.print(lines_received);

    delay(1);

  }

}
    if (lines_received == 19) {

      json = line;
      //Serial.println(json);
    }

Bad idea. Some future change to the number of header lines the script outputs, and you're hosed.

The string of interest starts with a character that is present in no other lines. Make use of that fact, not the number of lines, to find the interesting line.