Go Down

Topic: Parsing strings (Read 193 times) previous topic - next topic

Nikola19992

So,how do I split +CCLK: "17/06/14,23:32:58+08" to a 23 hours and 32 minutes? I don't care too much about other things,how it's done?

PaulS

Quote
how it's done?
Depends on how it is stored.
The art of getting good answers lies in asking good questions.

econjack

Read Paul's tag line. We need to know if the text data is stored in a C string (e.g., a char array) or a String object. Most of us here are not big fans of the String class, so a char array is preferred. Assuming that's the case, investigate strtok(). A starting point might be here.

Nikola19992

Depends on how it is stored.
It's what I'll be recieving on Serial.I can make it a string easily,
 Time[Time0] = '\0';

econjack

We need to see the code you are using. Before posting it, however, please read the post at the top of this Forum by Nick Gammon about how to post properly here. Following his suggestions makes it easier for us to help you.

Nikola19992

I still haven't wrote code yet,because I don't know how.

PaulS

I still haven't wrote code yet,because I don't know how.
You can't write code to parse data you don't have.
The art of getting good answers lies in asking good questions.

jurs

#7
Jun 19, 2017, 05:24 pm Last Edit: Jun 19, 2017, 05:28 pm by jurs
So,how do I split +CCLK: "17/06/14,23:32:58+08" to a 23 hours and 32 minutes? I don't care too much about other things,how it's done?
Use sscanf() function

I's the opposite to sprintf() and scans a (nullterminated) string.

BulldogLowell

#8
Jun 19, 2017, 06:45 pm Last Edit: Jun 19, 2017, 06:45 pm by BulldogLowell
Use sscanf() function
so you send your module a request like this:

Code: [Select]
SomeSerial.println("AT+CCLK?");

you get back a string like this:

Code: [Select]
+CCLK: "17/06/14,23:32:58+08"
followed by:
Code: [Select]
OK

so you can parse your date/time like this:
Code: [Select]
#include <Time.h>
#include <TimeLib.h>
#define TIMEOUT_MILLIS 250

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

void loop()
{
  static int lastSecond = 60;
 
  // this block will request the time and wait for it to come back, or timeout
  uint32_t timerStart = millis();
  requestTime(Serial);  // you may be using software serial, put the name of the Software Serial instance instead of Serial
  while(!updateTime(Serial) && millis() - timerStart < TIMEOUT_MILLIS) // this blocks, waiting for the time to come back also, you may be using software serial, put the name of the Software Serial instance instead of Serial
  {
    // just wait a second for the time to come back from module
  }

  if(lastSecond != second())
  {
    char currentTime[32] ="";
    sprintf(currentTime, "%2d:%02d:%02d, %2d/%02d/%4d", hour(), minute(), second(), month(), day(), year());
    Serial.println(currentTime);
  }
  lastSecond = second();
}

bool updateTime(HardwareSerial& stream) // if you are using software serial, change this to (SoftwareSerial& stream)
{
  static char buffer[32];
  static byte idx = 0;
  if(stream.available())
  {
    buffer[idx++] = stream.read();
    buffer[idx] = '\0';
    if(strstr(buffer, "OK"))
    {
      Serial.println(buffer);
      TimeElements tm;
      int d, m, y, h, mn, s, number = sscanf(buffer, "%*[^\"]\"%2u%*c%2u%*c%2u,%2u:%2u:%2u+", &y, &m, &d, &h, &mn, &s);  // google sscanf()
      if(number != 6)
      {
        idx = 0;
        buffer[idx] = '\0';
        Serial.println("error getting time");
        return false;
      }
      tm.Year = 2000 + y - 1970;  //Unix Epoch
      tm.Month = m;
      tm.Day = d;
      tm.Hour = h;
      tm.Minute = mn;
      tm.Second = s;
      setTime(makeTime(tm));
      Serial.println(makeTime(tm));
      idx = 0;
      buffer[idx] = '\0';
      return true;
    }
  }
  return false;
}

void requestTime(HardwareSerial& stream)  // if you are using software serial, change this to (SoftwareSerial& stream)
{
  stream.println("AT+CCLK?");
}


try it using above code and entering this into the serial monitor:

Code: [Select]
+CCLK: "17/06/14,23:32:58+08" OK

you will see the output change, both date and time...

Robin2

There is a parse example in Serial Input Basics which may provide some ideas.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

econjack

I still haven't wrote code yet,because I don't know how.
Oh, I misunderstood. You want free consulting rather than an answer to a question.

Nikola19992


PaulMurrayCbr

So,how do I split +CCLK: "17/06/14,23:32:58+08" to a 23 hours and 32 minutes? I don't care too much about other things,how it's done?
Code: [Select]

char foo[] = "+CCLK: "17/06/14,23:32:58+08"; // input string

char *p = strchr(foo, ',') + 1; // point to the location one past the comma

p[3] = '\0'; // zap the colon with a nul terminator

int hours = atoi(p); // convert

p += 3; // move along three characters to the start of the minutes;
p[3] = '\0'; // zap the colon with a mul terminator
int minutes = atoi(p); // convert
http://paulmurraycbr.github.io/ArduinoTheOOWay.html

westfw

#13
Jun 20, 2017, 07:44 am Last Edit: Jun 20, 2017, 07:48 am by westfw
Quote
Code: [Select]
+CCLK: "17/06/14,23:32:58+08

I still haven't wrote code yet,because I don't know how.
First decision point:
decide whether you will read the whole string from Serial, or whether you are going to extract your hours/minutes form the data as it is received.

Skip the data (in string, or on the serial port) till you get past the comma.
Read number (from string or serial) into hours until you get to the colon.
skip the colon.
Read number into minutes until you get to the next colon.
Might be easier if both hours and minutes are always exactly two digits.

Robin2

well,actually yes
So did you study the code (complete programs) that I gave you freely in Reply #9 ?

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

Go Up