I have created an ESP8266 application to monitor 3 humidity/temp sensors in my attic.
The reading of the sensors works just fine so now I have to figure out how to actually send the data to my website server.
I created a simple PHP file which will read the data as if they came from a form and save to a text file for the time being. I have tested that it works by using an URL in my web browser like this:
OK, so I changed the code around a bit but it still does not verify:
void SendData(int sensor, float temp, float humid)
{
HTTPClient http;
String dataline; //Added this to build command outside of GET call
dataline = "source=" + sensor + "&temp=" + temp + "&humid=" + humid;
http.begin("http://www.mydomain.com/php/tempreport.php");
http.addHeader("Content-Type", "application/x-www-form-urlencoded");
int httpCode = http.GET(dataline);
if(httpCode != HTTP_CODE_OK)
{
SerialDebug.print("Error when sending to server: ");
SerialDebug.println(httpCode);
}
}
But I get this error output:
..\DHT_MONITOR.ino:250:34: error: invalid operands of types 'const char*' and 'const char [7]' to binary 'operator+'
dataline = "source=" + sensor + "&temp=" + temp + "&humid=" + humid;
^
..\DHT_MONITOR.ino:254:34: error: no matching function for call to 'HTTPClient::GET(String&)'
int httpCode = http.GET(dataline);
I have seen many examples where one can build strings containing textual representations of variables and tried to use this here, but I don't understand the error messages, can someone please explain what is the problem?
You should use POST. GET shouldn't have side effects. Just change your PHP script.
You can't use the '+' operator to concatenate char* (null terminated character arrays). You either have to use sprintf, or use Strings (String("source=") + sensor + "&temp=" + temp + "&humid=" + humid;).
Regarding POST vs GET, my first message showed my use of POST, but I changed that following the first reply....
Anyway, since the PHP script works fine from an URL containing the data as well as the file reference, maybe the code could be simplified to only have this:
The code builds without errors in any case, but I don't know the innards of a web request so just maybe it will not work in real life?
I see no point in separating the destination and data if they could be sent in one single transaction as a composite URL.
That would be the same as I do in FireFox...
BosseB:
I see no point in separating the destination and data if they could be sent in one single transaction as a composite URL.
That would be the same as I do in FireFox...
The HTTP specification requires you to use POST if a request has side effects (e.g. inserting temperature and humidity data into a database). GET requests should only retrieve information, without altering the internal state of the server.
You can of course choose not to follow the standard, but that will cause problems with caching and resubmission of the data.
Thank you for your help! Much appreciated!
While testing the PHP script I never got it to work from the URL line when I used POST in the data retrieval. With GET it was simple to extract the data items and write these to a file on the server.
Why should there be a difference between GET and POST depending on what the data are used for?
Currently I will dump the data items to a text file for later analysis, but in the end there might be a database table to receive them so it is easier to show excerpts of data for varying time intervals.
Request methods are considered "safe" if their defined semantics are
essentially read-only; i.e., the client does not request, and does
not expect, any state change on the origin server as a result of
applying a safe method to a target resource. Likewise, reasonable
use of a safe method is not expected to cause any harm, loss of
property, or unusual burden on the origin server.
This definition of safe methods does not prevent an implementation
from including behavior that is potentially harmful, that is not
entirely read-only, or that causes side effects while invoking a safe
method. What is important, however, is that the client did not
request that additional behavior and cannot be held accountable for
it. For example, most servers append request information to access
log files at the completion of every response, regardless of the
method, and that is considered safe even though the log storage might
become full and crash the server. Likewise, a safe request initiated
by selecting an advertisement on the Web will often have the side
effect of charging an advertising account.
Of the request methods defined by this specification, the GET, HEAD,
OPTIONS, and TRACE methods are defined to be safe.
The purpose of distinguishing between safe and unsafe methods is to
allow automated retrieval processes (spiders) and cache performance
optimization (pre-fetching) to work without fear of causing harm. In
addition, it allows a user agent to apply appropriate constraints on
the automated use of unsafe methods when processing potentially
untrusted content.
A user agent SHOULD distinguish between safe and unsafe methods when
presenting potential actions to a user, such that the user can be
made aware of an unsafe action before it is requested.
When a resource is constructed such that parameters within the
effective request URI have the effect of selecting an action, it is
the resource owner's responsibility to ensure that the action is
consistent with the request method semantics. For example, it is
common for Web-based content editing software to use actions within
query parameters, such as "page?do=delete". If the purpose of such a
resource is to perform an unsafe action, then the resource owner MUST
disable or disallow that action when it is accessed using a safe
request method. Failure to do so will result in unfortunate side
effects when automated processes perform a GET on every URI reference
for the sake of link maintenance, pre-fetching, building a search
index, etc.
Function SendData that sends the DHT values to the webserver php script:
/******************************************************
* This function sends measured data to a PHP script on
* the webserver where it is stored with a timestamp to
* a MySQL database or into a text file.
*******************************************************/
void SendData(int sensor, float temp, float humid)
{
HTTPClient http;
//Build call string:
String dataline = "http://<serverurl>/php/tempreport.php";
dataline += "?source=" + String(sensor);
dataline += "&temp=" + String(temp, 1); //2 decimal places
dataline += "&humid=" + String(humid, 1);
bool httpResult = http.begin(dataline);
if(!httpResult)
{
SerialDebug.println("Invalid HTTP request:");
SerialDebug.println(dataline);
}
else
{
int httpCode = http.GET();
if (httpCode > 0)
{ // Request has been made
SerialDebug.printf("HTTP status: %d Message: ", httpCode);
String payload = http.getString();
SerialDebug.println(payload);
}
else
{ // Request could not be made
SerialDebug.printf("HTTP request failed. Error: %s\r\n", http.errorToString(httpCode).c_str());
}
}
http.end();
}
My loop function:
void loop()
{
//Check if a new DHT reading is requested (once every interval ms):
unsigned long tickcount = millis();
if ((interval > 0) && ((unsigned long)(tickcount - lasttickcount) >= interval))
HandleDHTsensors(tickcount);
//Next follows other unrelated tasks not shown here
}
Not showing HandleDHTsensors() because of its size.
But basically it reads the sensors and for each successful read it makes one call like this for each sensor read: