1

I want to control a relay by reading values from MySQL. I'm using an Arduino and an Ethernet shield. So far, I can get the response from server and get the value. I just need the value 10110110, but I get a response in the serial monitor like this:

HTTP/1.1 200 OK
Date: Sun, 02 Jul 2017 07:53:29 GMT
Server: Apache/2.2.14 (Win32) DAV/2 mod_ssl/2.2.14 OpenSSL/0.9.8l mod_autoindex_color PHP/5.3.1 mod_apreq2-20090110/2.7.1 mod_perl/2.0.4 Perl/v5.10.1
X-Powered-By: PHP/5.3.1
Content-Length: 13
Content-Type: text/html


<10110110>

How to remove this long response and get the value 10110110?

  • 2
    @ChrisStratton - With respect, please review the edits, to see who made what changes. This was a suggested edit, made by someone else, that I reviewed, accepted and improved the edit. Should I have rejected the edit? – Greenonline Jul 2 '17 at 20:18
  • 1
    @Golckz Could you please provide more information. Tell us about the specifics. Make sure your question is clear. – sa_leinad Jul 5 '17 at 12:33
  • What code have you used? Could you post it? What is the specific command that you use to request the value from the database? – sa_leinad Jul 5 '17 at 12:35
1

There are, obviously, a great number of ways that this can be achieved. The simple brute force way would be to have a series of if statements, looking for a sequence of eight consecutive 0s and/or 1s, and loop through the string containing the response.

Or you could loop through the response, using strcmp(), similar to what is described here: how to do like a grep in a sketch?

However, a more intelligent method would be to use pattern matching and regular expressions.

From New regular expression library released, Nick has provided a Regexp library. It uses Lua for the expression syntax, see string.find, for more details.

I am still playing with this code, but your sketch would need something like this:

#include <Regexp.h>
void setup ()
{
  Serial.begin (115200);
  Serial.println ();

  unsigned int index = 0;
  char buf [100];

  MatchState ms;
  ms.Target ("HTTP/1.1 200 OK\
Date: Sun, 02 Jul 2017 07:53:29 GMT\
Server: Apache/2.2.14 (Win32) DAV/2 mod_ssl/2.2.14 OpenSSL/0.9.8l mod_autoindex_color PHP/5.3.1 mod_apreq2-20090110/2.7.1 mod_perl/2.0.4 Perl/v5.10.1\
X-Powered-By: PHP/5.3.1\
Content-Length: 13\
Content-Type: text/html\
\
\
<10110110>");  // what to search

  while (true){
    char result = ms.Match ("^<([01][01][01][01][01][01][01][01])", 0);  // look for an eight bit binary digit
    if (result == REGEXP_MATCHED)
    {
      Serial.println ("-----");
      Serial.print ("Matched on: ");
      Serial.println (ms.GetMatch (buf));
      Serial.println ("Captures:");
      for (int j = 0; j < ms.level; j++)
         Serial.println (ms.GetCapture (buf, j));
      // move past matching string
      index = ms.MatchStart + ms.MatchLength;
    }  // end of match
    else 
      break;  // no match or regexp error

  } // end of while

}  // end of setup

void loop () {}

This code assumes that you are looking for a line beginning with < and captures an eight digit binary thereafter - as determined by the expression within the inner (), in the line:

    char result = ms.Match ("^<([01][01][01][01][01][01][01][01])", 0);  // look for an eight bit binary digit

So, it should output:

-----
Matched on: <10110110
Captures: 10110110
-----

Obviously, instead of just outputting the captured binary digits to the serial monitor, you need to save them for your relay control.


For neatness, you could replace

 ms.Target ("HTTP/1.1 200 OK\
Date: Sun, 02 Jul 2017 07:53:29 GMT\
Server: Apache/2.2.14 (Win32) DAV/2 mod_ssl/2.2.14 OpenSSL/0.9.8l mod_autoindex_color PHP/5.3.1 mod_apreq2-20090110/2.7.1 mod_perl/2.0.4 Perl/v5.10.1\
X-Powered-By: PHP/5.3.1\
Content-Length: 13\
Content-Type: text/html\
\
\
<10110110>");  // what to search

with

  char * str = "HTTP/1.1 200 OK\
    Date: Sun, 02 Jul 2017 07:53:29 GMT\
    Server: Apache/2.2.14 (Win32) DAV/2 mod_ssl/2.2.14 OpenSSL/0.9.8l mod_autoindex_color PHP/5.3.1 mod_apreq2-20090110/2.7.1 mod_perl/2.0.4 Perl/v5.10.1\
    X-Powered-By: PHP/5.3.1\
    Content-Length: 13\
    Content-Type: text/html\
    \
    \
    <10110110>";

  ms.Target (str);

Note the use of the backslashes at the ends of the lines. I've included them here, in order to get the test sketch to compile. You probably will not need them as you would be receiving the response from the server, and not providing an example string for testing.


Here is a working version, along with multiple test strings (input_str) and example match strings (match_str):

#include <Regexp.h>
void setup ()
{
  Serial.begin (9600);
//  Serial.begin (115200);
  Serial.println ();

  unsigned int index = 0;
  char buf [100];

// Simple test pair
//  char * input_str = "RGB:123";
//  char * match_str = "(%a)";

// Simulated MySQL responses
// Most basic
//  char * input_str = "<10110110>";
// Over two lines
//  char * input_str = "http\\n<10110110>";
// Full response
  char * input_str = "HTTP/1.1 200 OK\
    Date: Sun, 02 Jul 2017 07:53:29 GMT\
    Server: Apache/2.2.14 (Win32) DAV/2 mod_ssl/2.2.14 OpenSSL/0.9.8l mod_autoindex_color PHP/5.3.1 mod_apreq2-20090110/2.7.1 mod_perl/2.0.4 Perl/v5.10.1\
    X-Powered-By: PHP/5.3.1\
    Content-Length: 13\
    Content-Type: text/html\
    \
    \
    <10110110>";
// Full response with newlines
//  char * input_str = "HTTP/1.1 200 OK\\n\
    Date: Sun, 02 Jul 2017 07:53:29 GMT\\n\
    Server: Apache/2.2.14 (Win32) DAV/2 mod_ssl/2.2.14 OpenSSL/0.9.8l mod_autoindex_color PHP/5.3.1 mod_apreq2-20090110/2.7.1 mod_perl/2.0.4 Perl/v5.10.1\\n\
    X-Powered-By: PHP/5.3.1\\n\
    Content-Length: 13\\n\
    Content-Type: text/html\\n\
    \\n\
    \\n\
    <10110110>";
// Shorter version of full MySQL response with newlines
//  char * input_str = "Content-Type: text/html\\n\
    \\n\
    \\n\
    <10110110>";
// Shorter version of full MySQL response with newlines with no preceeding spaces
//  char * input_str = "Content-Type: text/html\\n\
\\n\
\\n\
<10110110>";

// Match strings for MySQL response, containing an eight bit binary number
// Match at beginning of line
//  char * match_str = "^<([01][01][01][01][01][01][01][01])";
// Match at beginning of line with multiple newline characters
  char * match_str = "[\n]*<([01][01][01][01][01][01][01][01])";
// Match at beginning of line with zero or one newline characters
//  char * match_str = "[\n]?<([01][01][01][01][01][01][01][01])";
// Match at anywhere
//  char * match_str = "<([01][01][01][01][01][01][01][01])";


  MatchState ms;

  while (true){
    char result = ms.Match (match_str, 0);

    if (result == REGEXP_MATCHED)
    {
      Serial.println ("-----");
      Serial.print ("Matched on: ");
      Serial.println (ms.GetMatch (buf));
      Serial.println ("Captures:");
      for (int j = 0; j < ms.level; j++)
         Serial.println (ms.GetCapture (buf, j));
      // move past matching string
      index = ms.MatchStart + ms.MatchLength;
    }  // end of match
    else 
      break;  // no match or regexp error

  } // end of while

}  // end of setup

void loop () {}

For the match_str line,

char * match_str = "[\n]*<([01][01][01][01][01][01][01][01])";

you may or may not need the caret (^) to match at the start of the line, and the [\n]* or [\n]?. See which combination works for you.

  • This is far more complicated than needed. Review the HTTP protocol, and what it says about body vs header. – Chris Stratton Jul 2 '17 at 21:05
  • OK @ChrisStratton, thanks for your input. Maybe you would like to post your own answer, with your solution? – Greenonline Jul 2 '17 at 21:06
  • 1
    I think it is a really great answer. you could utilize this response for a wide range of similar problems, and there is a great amount of detail. – j0h Jul 4 '17 at 0:11
  • @jOh, Thanks. Yes, it is a most versatile library – Greenonline Jul 5 '17 at 11:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.