HttpClient , request.body?

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.

request.hostname = “192.168.0.47”;
request.port = 80;
request.path = “/cgi-bin/test.py”;
//request.body = “{“key”:“value”}”;
request.body = “{’“volts”:12.3}”;

it is connecting , but not passing the key pair

Have you got the mixed single and double quotes on purpose?

request.body = "{\'"volts\":12.3}";

@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:

http_header_t headers[] = {
    { "Content-Type", "application/json" },
    { "Accept" , "*/*"},
    { NULL, NULL } // NOTE: Always terminate headers with NULL
};

:wink:

Yes ,I have included that and do get a replay from my server .

it looks like both request.hostname and request.ip connect to my server , it is post / get data using the request.body i’m having problems with.

@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?

[quote=“peekay123, post:5, topic:19989”]

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}”;

What are you seeing on the server side?

192.168.0.80 - - [12/Feb/2016:15:00:51 +0000] “GET /cgi-bin/test.py HTTP/1.0” 200 238 “-” "-"
192.168.0.80 - - [12/Feb/2016:15:12:58 +0000] “GET /cgi-bin/test.py HTTP/1.0” 200 238 “-” "-"
192.168.0.80 - - [12/Feb/2016:15:25:05 +0000] “GET /cgi-bin/test.py HTTP/1.0” 200 238 “-” "-"
192.168.0.80 - - [12/Feb/2016:15:37:12 +0000] “GET /cgi-bin/test.py HTTP/1.0” 200 238 “-” “-”

@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.

1 Like

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.

1 Like

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”;

2 Likes

@rickkas7 , tried your changes , but still not working , I`ll give up on it do a bit of reading and look with clear eyes later

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.

My cheat.

request.ip = IPAddress{ 192, 168, 0, 47 };
request.port = 80;
String added_bit="?volts=" + String(volts);
request.path = "/cgi-bin/test.cgi"+ added_bit;
2 Likes

Hi @peter_a

Requestb.in is a web service that you can use to inspect your HTTP requests. You go to

http://requestb.in

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.

2 Likes

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. :smile:

@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.

This worked great for one parameter!

What if I would like to send two or three parameters. How should I code this?

Thank you for your help!

Hi Andy,

I think it needs to follow the query parameters format like explained here:
https://branch.io/glossary/query-parameters/#:~:text=Query%20parameters%20are%20a%20defined,immediately%20by%20a%20query%20parameter.

To add multiple parameters, an ‘&’ is added in between each

Thank you @gusgonnet!

“&” does work. https://xxxxx?U=11&S=22&F=10

However, I am not sure how I can put this in “request.path”. I tried the code below, but it didn’t worked.

String added_bit="?U=" + String(11) & "S=" + String (22) & "F=" + String (10);
request.path = "/cgi-bin/test.cgi"+ added_bit;

I also tried below code, but no luck;

float U = 11;
float S = 22;
float F = 10;

char data[256];
snprintf(data, sizeof(data), "{\"U\": %f, \"S\": %f, \"F\": %f}", U, S, F);
request.path = "/cgi-bin/test.cgi"+ data;

You could try

int U = 11;
int S = 22;
int F = 10;

snprintf(data, sizeof(data), "/cgi-bin/test.cgi?U=%d&S=%d&F=%d", U, S, F);
request.path = data;
1 Like

Thank you, @ScruffR !

The code worked!

2 Likes