Hi , having a little problems with HttpClient and trying to send a get or post request.
I am trying to send a key which is called volts and I have a string called volts for the value , i’ve tried many methods but can’t get it to work.
@peter_a, the request.hostname field is used when you have an URL to resolved. To specify the IP address directly, use request.ip = IPAddress{ 192, 168, 0, 47 };. Also, you haven’t specified a header specifying the content type like this:
@peter_a did you try and use request.bin to see what is actually being sent by the Photon? What are you seeing on the server side? Also, did you see @ScruffR comment above?
Sorry it is the first time I’ve used this library , so not seen request.bin referenced anywhere only used to serial debug response.status and response.body .
Yes I did see @ScruffR comment above , but had to rush out so didn’t have chance to comment on it, but tried mixing single and double quotes with the right syntax
eg request.body = “{‘volts’:12.3}”;
@peter_a, request.bin allows you to see what an http request is actually sending out.
The correct formatting for your JSON text requires “escaped” double quotes. Since you can’t normally include a double quote in a string, you need to escape it like this: \" (note the \ is the escape character). So your request.body above is almost correct and should be: request.body = "{\"volts\":12.3}";
This will translate to {“volts”: 12.3} or a JSON object volts with value 12.3.
From the server log, you’re issuing a GET call. The request.body is not used for a GET. You probably should be using post() if you’re sending data in the body.
How do i use request.bin ? , I can`t serial debug it or I just get 'struct http_request_t' has no member named 'bin'
Tried GET and POST with the same result , I can go it it firefox and cheat and type - http://192.168.0.47/cgi-bin/test.py?volts=12 and that works .
192.168.0.127 - - [12/Feb/2016:16:15:36 +0000] "GET /cgi-bin/test.py?volts=12 HTTP/1.1" 200 318 "-" "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:44.0) Gecko/20100101 Firefox/44.0"
I think I`m just going to have to RTFM , if there is one. and post my full code
// This #include statement was automatically added by the Particle IDE.
#include "HttpClient/HttpClient.h"
// This #include statement was automatically added by the Particle IDE.
#include "Adafruit_ADS1X15/Adafruit_ADS1X15.h"
Adafruit_ADS1115 ads; /* Use this for the 16-bit version */
HttpClient http;
// Headers currently need to be set at init, useful for API keys etc.
http_header_t headers[] = {
// { "Content-Type", "application/json" },
// { "Accept" , "application/json" },
{ "Accept" , "*/*"},
{ NULL, NULL } // NOTE: Always terminate headers will NULL
};
http_request_t request;
http_response_t response;
double volts;
int sleep_time;
void setup()
{
Serial.begin(9600);
pinMode(D2 , OUTPUT );
ads.setGain(GAIN_TWOTHIRDS); // 2/3x gain +/- 6.144V 1 bit = 3mV 0.1875mV (DEFAULT)
ads.begin();
}
void loop()
{
double multiplier = 0.1875F;
short adc0, adc1, adc2, adc3;
double av0, av1, av2, av3;
// adc0 = ads.readADC_SingleEnded(0); av0 = adc0 * multiplier;
// adc1 = ads.readADC_SingleEnded(1); av1 = adc1 * multiplier;
// adc2 = ads.readADC_SingleEnded(2); av2 = adc2 * multiplier;
adc3 = ads.readADC_SingleEnded(3); av3 = adc3 * multiplier;
volts = av3 / 1000;
Server_connect();
if (( Time.hour() >= 9 ) && ( Time.hour() <= 21 ))
{
sleep_time = 720;
}
else
{
sleep_time = 3600;
}
Particle.publish("Volts", String(volts) );
Particle.publish("Sleep_time", String(sleep_time) );
digitalWrite( D2 , HIGH ); delay(750); digitalWrite( D2 , LOW );
delay(1500);
digitalWrite( D2 , HIGH ); delay(750); digitalWrite( D2 , LOW );
//System.sleep(SLEEP_MODE_DEEP, sleep_time );
delay(600000);
}
void Server_connect()
{
double value2 = 455.12;
//request.hostname = "192.168.0.47";
request.ip = IPAddress{ 192, 168, 0, 47 };
request.port = 80;
request.path = "/cgi-bin/test.py";
request.body = "{\"volts\": " + String(volts) + ", \"variable2\": " + String(value2) + "}";
Serial.println(request.body);
// Get request
http.post(request, response, headers);
Serial.print("Application>\tResponse status: ");
Serial.println(response.status);
Serial.print("Application>\tHTTP Response Body: ");
Serial.println(response.body);
}
#! /usr/bin/python
import time
import cgi
import cgitb
cgitb.enable()
print "Content-type:text/html"
print
print "<html>"
print "<head><title>My cgi</title></head>"
print "<body>"
print "<h1>it works</h1>"
fo = open( "save.txt" , "a" )
now = time.ctime()
fo.write( now + "\n" )
fo.close()
form = cgi.FieldStorage()
if form.getvalue("volts"):
volts = form.getvalue("volts")
fo = open( "save.txt" , "a" )
fo.write( volts + "\n" )
fo.close()
print "</body>"
print "<html>"
Your test.py file is expecting form data, not JSON data. The form data can be either in the URL for a GET, like you used in your browser-based test, or URL encoded form arguments in the POST body.
Try changing the Content-Type header to application/x-www-form-urlencoded, method to post() and
request.body = “volts=12.3\r\n”;
Still don’t know how to use request.bin !!! , but I’ve found if you can`t do it one way CHEAT !!! , so got my working solution working in the end . I think my photon is not sending the body correct or MOST LICKLY my server is not set up correctly.
and create a temporary request bin that you can then point your Photon code to instead of your normal host. When you run the HTTP request on your Photon, you can go to requestb.in with a browser and your bin ID and see exactly what you are sending.
This is a great way to debug errant requests and web hooks.
I am scratching my head ,looking at the screen for almost two hours and figuring why
request.body = “{“key”:“value”}” cannot work… Your cheat just works… I edited the path and value and it works now.
Thank you.
@peter_a … Your information saved me many more hours of searching.
I’m using phant on a local esp8266 board so I won’t be able to access the particle cloud. I’ve been trying to figure out why the application/json wasn’t working. Your information was exactly what I needed.