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: 2017年7月02日 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– Greenonline2017年07月02日 20:18:59 +00:00Commented Jul 2, 2017 at 20:18
-
1@Golckz Could you please provide more information. Tell us about the specifics. Make sure your question is clear.sa_leinad– sa_leinad2017年07月05日 12:33:27 +00:00Commented Jul 5, 2017 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– sa_leinad2017年07月05日 12:35:25 +00:00Commented Jul 5, 2017 at 12:35
1 Answer 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 0
s and/or 1
s, 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: 2017年7月02日 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: 2017年7月02日 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: 2017年7月02日 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: 2017年7月02日 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: 2017年7月02日 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– Chris Stratton2017年07月02日 21:05:01 +00:00Commented Jul 2, 2017 at 21:05
-
OK @ChrisStratton, thanks for your input. Maybe you would like to post your own answer, with your solution?Greenonline– Greenonline2017年07月02日 21:06:39 +00:00Commented Jul 2, 2017 at 21:06
-
1I 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– j0h2017年07月04日 00:11:06 +00:00Commented Jul 4, 2017 at 0:11
-
@jOh, Thanks. Yes, it is a most versatile libraryGreenonline– Greenonline2017年07月05日 11:30:10 +00:00Commented Jul 5, 2017 at 11:30