[SOLVED] Wifly HTTP POST JSON getting 400 Bad Request


#1

Hi,

I have been trying to update variables through an Arduino UNO using Wifly Shield.
I am able to connect to the Ubidots page but keep getting 400 Bad Request. I believe this could be due to improper JSON encoding from my part but I am unable to resolve the issue. I tried to send a request with static value matching the API example and used Serial.Print() to test whether my JSON object is built properly. It seems to match the API example. Yet, my request is rejected. Please help. Thank you.

Here is my code, derived from Ubidots example.

#include <Arduino.h>
#include <SoftwareSerial.h>
#include <WiFly.h>
//-------------------------------------------------------------
//---------------------Network Configuration-------------------
//-------------------------------------------------------------
#define SSID      "myssid"
#define KEY       "mypwd"
#define AUTH      WIFLY_AUTH_WPA2_PSK

SoftwareSerial uart(2, 3);
WiFly wifly(uart);
unsigned long start_millis = 0;

void setup() {
  Serial.begin(9600);
  Serial.println("------- WIFLY HTTP --------");
  
  uart.begin(9600);
  if (!wifly.isAssociated(SSID)) {
  while (!wifly.join(SSID, KEY, AUTH)) 
  {    
      Serial.println("Failed to join " SSID);
      Serial.println("Wait 0.1 second and try again...");
      delay(100);
   }
    wifly.save();    
  }
}

void loop() {
  int reset = 0;
  
  int valor = 20;
  while ((save_value(valor)) < 0) 
  {
    reset++;
    if(reset == 10)
    {
      asm volatile ("  jmp 0");  
    }
  }

//   Uncomment for debug

  char r;
  while (wifly.receive((uint8_t *)&r, 1, 1000) == 1) 
  {    
    Serial.print(r);
  }
}
int save_value(int dato)
{
  char post_data_buf[32];
  String test="35.8";
  snprintf(post_data_buf, sizeof(post_data_buf), "{\"value\": \"35.8\"}\r\n");
  int len = strlen(post_data_buf);
  Serial.println(post_data_buf);
  char host[20];
  uint16_t port;
  
  
  if (!wifly.connect("things.ubidots.com", 80)) {
    Serial.println("Failed to connect.\r\n");
    return -2;
  }
  
  // Send request
  char buf[200];
  //dont forget change your id and your token

 snprintf(buf, sizeof(buf), "POST /api/v1.6/variables/5*********************c/values?token=i***************************A HTTP/1.1\r\nContent-Type: application/json\r\nContent-Length: %d\r\nHost: things.ubidots.com\r\n\n",strlen(post_data_buf));
    
  wifly.send(buf);
  //wifly.send("");
  // Send body
  if (post_data_buf != NULL) {
    wifly.send(post_data_buf);
  }
   wifly.send("\r\n");
   Serial.println(buf);
   return 0;
}

Besides the one in the code bit, I have also tried the following:

//snprintf(buf, sizeof(buf), "POST /api/v1.6/variables/5*********************c/values HTTP/1.1\r\nContent-Type: application/json\r\nContent-Length: %d\r\nX-Auth-Token: i***************************A\r\nHost: things.ubidots.com\r\n\r\n",strlen(post_data_buf));

//snprintf(buf, sizeof(buf), "POST /api/v1.6/variables/5*********************c/values/?token=i***************************AHTTP/1.1\r\nHost: things.ubidots.com\r\nContent-Type: application/json\r\nContent-Length: %d\r\n",17);

#2

Hey! I have a question what device are you using?


#3

Hi! I’m using Arduino UNO + Wifly Shield.


#4

But what wifly devices? RN, WizNet? You have a photo of your device?


#5

I seem to have made a terrible mistake.

It’s SeeedStudio Wifi Shield 2.0. Similar to this one but with integrated antenna: http://www.seeedstudio.com/depot/Wifi-Shield-p-1220.html

UPDATE:
This is the exact model: http://www.seeedstudio.com/depot/Wifi-Shield-V20-p-2505.html
It is also known as WiFly EZX.
It has as RN171 with Firmware Version 4.0.


#6

Relax don’t worry, by the way I have good news for you, I will a assemble a library for that device, because the old code was wrong, could you give me 30 to 45 minutes?


#7

Sure. I updated my previous reply with the link to the exact model.
Thanks a lot!!


#8

okay I finished the library, you can find it here
The arduino code for this library is simplier than old code.

#include <UbidotsWiFly.h>
#define TOKEN "your_token_here"
#define VARIABLE_NAME_2 "your_variable_name_here"
#define VARIABLE_NAME_2 "your_variable_name_here"
#define SSID      "myssid"
#define KEY       "mypwd"
#define AUTH      WIFLY_AUTH_WPA2_PSK

Ubidots client(TOKEN);

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  client.wifiConnection(SSID, PASS, AUTH);
}

void loop() {
  client.add(VARIABLE_NAME_1, value1);
  client.add(VARIABLE_NAME_2, value2);
  client.sendAll();
}

by the way, for our library you need to download the wifly library too, cya!!


#9

Hi, sorry for the late reply. I was a bit busy and I wanted to try the code first hand. Firstly, thanks for your time! I am able to send requests with the new code however there seems to be some problems still.

By default the code creates a new data source named WiFly_TAG/1.0.0 and it attempts to send a sample value that I set. However, it seems to return “Failed to connect.” many times and after letting it run for a while I noticed that the variable is only gets updated once. It seems that among the failed requests one succeeds while the rest do not make it through.

Could the high amount of “Failed to connect.” be due to sending requests too frequently? Or could it be that the connection does not get closed after the first successful request that the subsequent requests fail?

I have tried removing the data source and run again, Data Source name WiFly_TAG/1.0.0 is created again but the variable is only updated once.
I also tried modifying the code a bit to send to a particular data source that I already have. But the result is still same. Can you help? Thanks in advance.

#include "UbidotsWiFly.h"
#define TOKEN "i***************************A"
#define DS_NAME "myds"
#define VARIABLE_NAME_1 "temp" //5*********************c
#define VARIABLE_NAME_2 "humidity"
#define SSID      "myssid"
#define PASS      "mypwd"
#define AUTH      WIFLY_AUTH_WPA2_PSK

Ubidots client(TOKEN);
float value1;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  client.wifiConnection(SSID, PASS, AUTH);
  value1= 35.8;
}

void loop() {

  value1 += 0.1;
  client.setDatasourceName(DS_NAME);
  client.setDatasourceTag(DS_NAME);
  client.add(VARIABLE_NAME_1, value1);
  //client.add(VARIABLE_NAME_2, value2);
  client.sendAll();
}

#10

Mm give me one second i will see your problem now


#11

I fixed the problem, try now please


#12

Hi, it seems that the methods connected() and stop() are both not defined in the Wifly class, making the ubidots code unable to compile. However, I noticed that WifiClient.h has declarations for the said methods. So I figured that I could try implementing them in Wifly class and see how it goes. It didn’t go very well. I ended up getting garbage output in my Serial Monitor. The only legible part was “ERR: ?-Cmd”.

With that I decided to see how it works in the EthernetClient library. Both methods are defined quite differently there. I’m not sure if the difference is purely due to the fact that they are different devices or that the Wifly library has not fully implemented all the features from the Ethernet library. Hope you can shed some light on this.
Thank you again for your time and patience.


#13

Ok give me one seccond


#14

Fixed I, you can download the lastest library i fixed it using the WiFlyClient.h now it will work fine. By the way EthernetClient is very different method becaouse wifly use AT commands from device to Software Serial Uart of Arduino UNO
EDIT:

In addition your error is for AT commands my friend, the first command to WiFly is $$$ if you send another commad it will be return an error
:smiley:


#15

Hi,
Firstly, many thanks for the heads up on the fact that AT commands are in use.
It seems that the problem is not resolved yet. Running the new code results in a loop of these garbage characters:

WiFly/1.0|POST|i***************************A|rdmon=>temp:35.90000|end
WÿåÿÅÁþAÿMÿñÿåQÿ™ÿYÿÿ    ¥ÿÿMÿÕÿ{u•F“þsñÿ‘m¹=Ñeƒ:«þ.Áþƒþ0•ndWiFly/1.0|POST|i***************************A|rdmon=>temp:36.00000|end
cÿÍÿ5
ERR: ?-Cmd
<4.00> KFåÿÅþÁþAÿMÿñÿåQÿ™ÿYÿÿ   ¥ÿÿMÿaµÿ½ÿÕÿ3WiFly/1.0|POST|i***************************AR|rdmon=>temp:36.09999|end
c½ÿ•ÿ

Commenting out _client.stop(); leads to:

WiFly/1.0|POST|i***************************A|rdmon=>temp:35.90000|end
WÿåÿÅÁþAÿMÿñÿåQÿ™ÿYÿÿ¥ÿÿMÿÕÿ{u-F“þJIÿ“d{õþÑÿk›þËþƒþ      +‘ÿWiFly/1.0|POST|i***************************A|rdmon=>temp:36.00000|end

I cross-checked with the Wifly AT Command Reference at http://www.seeedstudio.com/wiki/images/b/be/WiFly-RN-UM.pdf

close\r

seems to be a valid AT command to close TCP connection. So, I can’t imagine why the shield is showing ERR: ?-Cmd. However, it seems that the problem is in fact there.


#16

Perhaps the Wifly library itself has problems? Despite the fact that the Seedstudio Wifly library has WiflyClient.h, none of the examples actually use it. I traced the commits in their repository but the files were not used at all at any point. To further confirm this, I also checked their Wiki for the product at
http://www. seeedstudio.com/wiki/Wifi_Shield_V2.0. The examples mostly send commands directly to the shield instead of using the WifiClient.h library.

I am not sure if I am able to fix the library and at the same time I can’t really ask you to help since the problem is not due to Ubidots. What I would appreciate is if you could show me an example of updating Ubidots through HTTP POST/GET requests via the HttpClient library which fortunately seems to work with the Wifly shield.

The initial code provided by Ubidots for Wifly was based on HttpClient as well. Perhaps the reason for that was due to the fact that the WiflyClient library was not working in the first place?
Does the Ubidots API allow updating variables through HTTP POST/GET? My initial code was receiving 400 Bad Requests. Thank you and sorry for the troubles.

p.s.
I am also looking into an alternative that involves sending the sensor values to a hosted PHP script through HTTP GET whereby I can construct the JSON object in PHP and submit to Ubidots via curl. This is just a backup plan but I’d appreciate any heads up in that aspect as well if it is not possible to update directly from Arduino. Thank you very much,


#17

MMM okay i will see that


#18

Ok I update the library you could try it?


#19

Hello, the library still does not work [CLOSHTTP/1.1 400 Bad Request]


#20

Hello @golato,

I’m going to review the library to verify if I can reproduce your issue. We’re are updating updating our libraries to give the best to you guys! :smiley: :smiley:

Also, if you desire you can build your own example without using the Ubidots Library; Reference to the Ubidots REST API to learn the structure of the request and use this example code which will serve you as guide to make the HTTP Request.

I hope this would help you.

All the best,
Maria C.