[SOLVED] Hard time posting multiple varibles


#1

Hello,

First of all, Im really liking the ubidots platform and interface!
Im using an Arduino Mega 2560 whit a Arduino GSM shield V2
I have a school project where im working on a telemetry system.
Now ive sucseeded in sending 5 values.
However when I add a 6 value the whole code stops working.
its has probely something to do whit sending the data in a inefficent way, insted of making one request im making 5 individual (See below for post commands).
Also the code stops after a while then it says in the debug monitor: ‘‘Connection failed’’ (then I have to restart the arduino).
This has probely somting to do whit maken too many requests.
Now I want to make a http post string (with 6 up to 20 varibles im trying to make a http post ‘‘payload’’ according to this example: https://gist.github.com/mariacarlinahernandez/6ec0da04dea7f436e63aa5dc67e6496a.
I needed to modify the code quite a bit to get a response from the server. and i still cant send 2 values to ubidots.
Im getting this response: {“detail”: “JSON parse error - No JSON object could be decoded”}.
I cant use the commands like client.add and client.sendall because thats int the ethernet libary and im using the GSM (those commands would make it so mutch easier).
I cant use the curl function either because the arduino IDE does not support the command.
Can you provide me whit a example/solution thats expandable that will work in the Arduino IDE?

Kind regards,
Robert

PS. this is the post part for 5 varibles:

client.print(“POST /api/v1.6/variables/” + VoltageWebID + "/values HTTP/1.1\nContent-Type: application/json\nContent-Length: " + String(VoltageLenght) + "\nX-Auth-Token: " + WebToken + “\nHost: things.ubidots.com\n\n”);
client.println(VoltageString);

client.print(“POST /api/v1.6/variables/” + CurrentWebID + "/values HTTP/1.1\nContent-Type: application/json\nContent-Length: " + String(CurrentLenght) + "\nX-Auth-Token: " + WebToken + “\nHost: things.ubidots.com\n\n”);
client.println(CurrentString);

client.print(“POST /api/v1.6/variables/” + CurrentDischargeWebID + "/values HTTP/1.1\nContent-Type: application/json\nContent-Length: " + String(CurrentDischargeLenght) + "\nX-Auth-Token: " + WebToken + “\nHost: things.ubidots.com\n\n”);
client.println(CurrentDischargeString);

client.print(“POST /api/v1.6/variables/” + CurrentChargeWebID + "/values HTTP/1.1\nContent-Type: application/json\nContent-Length: " + String(CurrentChargeLenght) + "\nX-Auth-Token: " + WebToken + “\nHost: things.ubidots.com\n\n”);
client.println(CurrentChargeString);

client.print(“POST /api/v1.6/variables/” + StateOfChargeWebID + "/values HTTP/1.1\nContent-Type: application/json\nContent-Length: " + String(StateOfChargeLenght) + "\nX-Auth-Token: " + WebToken + “\nHost: things.ubidots.com\n\n”);
client.println(StateOfChargeString);


#2

Greetings @R_Bouw,

The example created by Maria is implemented to be uploaded to an Intel Edison so if you want to use it you have to adapt some parts of the code, i.e the method sprintf() allows the scape key “%f” in the Edison compiler but the Arduino’s compiler doesn’t.

I have adapted the Maria’s example to be ported to a NodeMCU, I think that it should work too in a GSM Shield but you will have to test it. Below I attach you the code.

/*************************************************************************************************
 * This Example sends harcoded data to Ubidots and serves as example for users that has devices
 * based on ESP8266 chips that we don't support with a library.
 * 
 * This example is given AS IT IS without any warranty
 * 
 * Made by Jose García.
 *************************************************************************************************/



/********************************
 * Libraries included
 *******************************/

#include <ESP8266WiFi.h>

/********************************
 * Constants and objects
 *******************************/

char const * SSID_NAME = "...."; // Put here your SSID name
char const * SSID_PASS = "...."; // Put here your password
char const * TOKEN = "....."; // Put here your TOKEN

char const * HTTPSERVER = "things.ubidots.com";

char const * DEVICE_LABEL = "test-device"; // Put here your device label

/* Put here your variable's labels*/
char const * VARIABLE_LABEL_1 = "var-test-1";
char const * VARIABLE_LABEL_2 = "var-test-2";
char const * VARIABLE_LABEL_3 = "var-test-3";
char const * VARIABLE_LABEL_4 = "var-test-4";
char const * VARIABLE_LABEL_5 = "var-test-5";
char const * VARIABLE_LABEL_6 = "var-test-6";

const int HTTPPORT = 80;

char const * USER_AGENT = "ESP8266";
char const * VERSION = "1.0";
char payload[700];
char topic[1000];

WiFiClient clientUbi;

// Space to store values to send
char str_val_1[30];
char str_val_2[30];
char str_val_3[30];
char str_val_4[30];
char str_val_5[30];
char str_val_6[30];

/********************************
 * Auxiliar Functions
 *******************************/

void SendToUbidots(char* payload) {

  int i = strlen(payload); 
  /* Builds the request POST - Please reference this link to know all the request's structures https://ubidots.com/docs/api/ */
  sprintf(topic, "POST /api/v1.6/devices/%s/?force=true HTTP/1.1\r\n", DEVICE_LABEL);
  sprintf(topic, "%sHost: things.ubidots.com\r\n", topic);
  sprintf(topic, "%sUser-Agent: %s/%s\r\n", topic, USER_AGENT, VERSION);
  sprintf(topic, "%sX-Auth-Token: %s\r\n", topic, TOKEN);
  sprintf(topic, "%sConnection: close\r\n", topic);
  sprintf(topic, "%sContent-Type: application/json\r\n", topic);
  sprintf(topic, "%sContent-Length: %d\r\n\r\n", topic, i);
  sprintf(topic, "%s%s\r\n", topic, payload);

  /* Connecting the client */
  clientUbi.connect(HTTPSERVER, HTTPPORT); 

  if (clientUbi.connected()) {
    /* Sends the request to the client */
    clientUbi.print(topic);
    Serial.println("Connected to Ubidots - POST");
  } else {
    Serial.println("Connection Failed ubidots - Try Again"); 
  }  
    
  /* Reads the response from the server */
  while (clientUbi.available()) {
    char c = clientUbi.read();
    //Serial.print(c); // Uncomment this line to visualize the response on the Serial Monitor
  }

  /* Disconnecting the client */
  clientUbi.stop();
}

/********************************
 * Main Functions
 *******************************/

void setup() {
  Serial.begin(115200);
  
  /* Connects to AP */
  WiFi.begin(SSID_NAME, SSID_PASS);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
    }

  WiFi.setAutoReconnect(true);
  Serial.println(F("WiFi connected"));
  Serial.println(F("IP address: "));
  Serial.println(WiFi.localIP());

}

void loop() {

  /* Adapt your value array following the structure specified at https://ubidots.com/docs/api/index.html#send-values-to-one-variable */
  
  /*---- Simulates the values of the sensors -----*/
  float sensor_value_1 = random(0, 1000)*1.0;
  float sensor_value_2 = random(0, 1000)*1.0;
  float sensor_value_3 = random(0, 1000)*1.0;
  float sensor_value_4 = random(0, 1000)*1.0;
  float sensor_value_5 = random(0, 1000)*1.0;
  float sensor_value_6 = random(0, 1000)*1.0;

  /*---- Transforms the values of the sensors to char type -----*/

  /* 4 is mininum width, 2 is precision; float value is copied onto str_val*/
  dtostrf(sensor_value_1, 4, 2, str_val_1);
  dtostrf(sensor_value_2, 4, 2, str_val_2);
  dtostrf(sensor_value_3, 4, 2, str_val_3);
  dtostrf(sensor_value_4, 4, 2, str_val_4);
  dtostrf(sensor_value_5, 4, 2, str_val_5);
  dtostrf(sensor_value_6, 4, 2, str_val_6);
  
  /* Builds the payload with structure: {"temperature":25.00,"humidity":50.00} for first 4 variables*/

  // Important: Avoid to send a very long char as it is very memory space costly, send small char arrays
  sprintf(payload, "{\"");
  sprintf(payload, "%s%s\":%s", payload, VARIABLE_LABEL_1, str_val_1);
  sprintf(payload, "%s,\"%s\":%s", payload, VARIABLE_LABEL_2, str_val_2);
  sprintf(payload, "%s,\"%s\":%s", payload, VARIABLE_LABEL_3, str_val_3);
  sprintf(payload, "%s,\"%s\":%s", payload, VARIABLE_LABEL_4, str_val_4);
  sprintf(payload, "%s}", payload);
  Serial.println(payload);

  /* Calls the Ubidots Function POST */
  SendToUbidots(payload);

  /* Builds the payload with structure: {"temperature":25.00,"humidity":50.00} for the rest of variables*/
  sprintf(payload, "%s", ""); //Cleans the content of the payload
  sprintf(payload, "{\"");
  sprintf(payload, "%s%s\":%s", payload, VARIABLE_LABEL_5, str_val_5);
  sprintf(payload, "%s,\"%s\":%s", payload, VARIABLE_LABEL_6, str_val_6);
  sprintf(payload, "%s}", payload);

  /* Calls the Ubidots Function POST */
  SendToUbidots(payload);
  
  delay(5000);
}

Regards


#3

Hello Jotathebest,

Thanks VERY VERY mutch!! :smiley: I could not have figured this out by myself.
Ill post the ‘‘modivided’’ code below if enyone has the same issue as I do.
Btw, I noticed how the code combines 4 values in to 1 request.
Is this the because Ubidots only accepts 4 values at a time or can I combine 6 values in 1 http request?

Greetings,
Robert


#4

Im posting the code in this message because I could not find out how to make a text box where I can put the code.

 #include <GSM.h>

 #define PINNUMBER "...."

 // APN data
 #define GPRS_APN       "....." // replace with your GPRS APN
 #define GPRS_LOGIN     ""    // replace with your GPRS login
 #define GPRS_PASSWORD  "" // replace with your GPRS password

 // initialize the library instance
 GSMClient client;
 GPRS gprs;
 GSM gsmAccess;

 char const * TOKEN = "......"; // Put here your TOKEN

 char const * HTTPSERVER = "things.ubidots.com";
 const int HTTPPORT = 80;

 char const * DEVICE_LABEL = "....."; // Put here your device label

 /* Put here your variable's labels*/
 char const * VARIABLE_LABEL_1 = "test-value-1";
 char const * VARIABLE_LABEL_2 = "test-value-2";
 char const * VARIABLE_LABEL_3 = "test-value-3";
 char const * VARIABLE_LABEL_4 = "test-value-4";
 char const * VARIABLE_LABEL_5 = "test-value-5";
 char const * VARIABLE_LABEL_6 = "test-value-6";

 char const * USER_AGENT = "ArduinoGSM";
 char const * VERSION = "1.0";
 char payload[700];
 char topic[1000];

 // Space to store values to send
 char str_val_1[30];
 char str_val_2[30];
 char str_val_3[30];
 char str_val_4[30];
 char str_val_5[30];
 char str_val_6[30];

 bool NotConnected;
 /********************************
    Auxiliar Functions
  *******************************/

 void SendToUbidots(char* payload) {

   int i = strlen(payload);
   /* Builds the request POST - Please reference this link to know all the request's structures https://ubidots.com/docs/api/ */
   sprintf(topic, "POST /api/v1.6/devices/%s/?force=true HTTP/1.1\r\n", DEVICE_LABEL);
   sprintf(topic, "%sHost: things.ubidots.com\r\n", topic);
   sprintf(topic, "%sUser-Agent: %s/%s\r\n", topic, USER_AGENT, VERSION);
   sprintf(topic, "%sX-Auth-Token: %s\r\n", topic, TOKEN);
   sprintf(topic, "%sConnection: close\r\n", topic);
   sprintf(topic, "%sContent-Type: application/json\r\n", topic);
   sprintf(topic, "%sContent-Length: %d\r\n\r\n", topic, i);
   sprintf(topic, "%s%s\r\n", topic, payload);

   /* Connecting the client */
   //client.connect(HTTPSERVER, HTTPPORT);

   if (client.connect("things.ubidots.com", 80)) {
     /* Sends the request to the client */
     client.print(topic);
     Serial.println("Connected to Ubidots - POST");
   }
   else {
     Serial.println("Connection Failed ubidots - Try Again");
   }
   /* Reads the response from the server */
   while (client.available())
   {
     char c = client.read();
     Serial.print(c);
   }

   /* Disconnecting the client */
   client.stop();
 }

 /********************************
    Main Functions
  *******************************/

 void setup() {
   Serial.begin(115200);
   NotConnected = 1;                                           //On powerup the shiel is not connected
   Serial.println("Starting Connecting Sequence");
   while (NotConnected) {                                      //Starting Connecting whit GSM Network (APN, Login and password).
     if ((gsmAccess.begin(PINNUMBER) == GSM_READY) & (gprs.attachGPRS(GPRS_APN, GPRS_LOGIN, GPRS_PASSWORD) == GPRS_READY)) {
       NotConnected = false;
     } else {
       Serial.println("Not connected");
       delay(1000);
     }
   }
 }

 void loop() {

   /* Adapt your value array following the structure specified at https://ubidots.com/docs/api/index.html#send-values-to-one-variable */

   /*---- Simulates the values of the sensors -----*/
   float sensor_value_1 = 1;
   float sensor_value_2 = 2;
   float sensor_value_3 = 3;
   float sensor_value_4 = 4;
   float sensor_value_5 = 5;
   float sensor_value_6 = 6;

   /*---- Transforms the values of the sensors to char type -----*/

   /* 4 is mininum width, 2 is precision; float value is copied onto str_val*/
   dtostrf(sensor_value_1, 4, 2, str_val_1);
   dtostrf(sensor_value_2, 4, 2, str_val_2);
   dtostrf(sensor_value_3, 4, 2, str_val_3);
   dtostrf(sensor_value_4, 4, 2, str_val_4);
   dtostrf(sensor_value_5, 4, 2, str_val_5);
   dtostrf(sensor_value_6, 4, 2, str_val_6);

   /* Builds the payload with structure: {"temperature":25.00,"humidity":50.00} for first 4 variables*/

   // Important: Avoid to send a very long char as it is very memory space costly, send small char arrays
   sprintf(payload, "{\"");
   sprintf(payload, "%s%s\":%s", payload, VARIABLE_LABEL_1, str_val_1);
   sprintf(payload, "%s,\"%s\":%s", payload, VARIABLE_LABEL_2, str_val_2);
   sprintf(payload, "%s,\"%s\":%s", payload, VARIABLE_LABEL_3, str_val_3);
   sprintf(payload, "%s,\"%s\":%s", payload, VARIABLE_LABEL_4, str_val_4);
   sprintf(payload, "%s}", payload);
   Serial.println(payload);

   /* Calls the Ubidots Function POST */
   SendToUbidots(payload);

   /* Builds the payload with structure: {"temperature":25.00,"humidity":50.00} for the rest of variables*/
   sprintf(payload, "%s", ""); //Cleans the content of the payload
   sprintf(payload, "{\"");
   sprintf(payload, "%s%s\":%s", payload, VARIABLE_LABEL_5, str_val_5);
   sprintf(payload, "%s,\"%s\":%s", payload, VARIABLE_LABEL_6, str_val_6);
   sprintf(payload, "%s}", payload);

   /* Calls the Ubidots Function POST */
   SendToUbidots(payload);

   delay(5000);
 }

#5

Hello @R_Bouw, Ubidots has not variable’s limit when you construct an array of values, I send only four in the code to avoid memory management issues in the device, remember that the Arduino boards, ESP8266, NodeMCU, etc are microcontrollers with a very low memory space so you should not build very long arrays to be sent, we would say that it is a limitation of the device, not of Ubidots.

Regards


#6

Hello @jotathebest,

Okay, Thanks A LOT for your help!
(I just saw it was also explained in the code, sorry for asking)
My issu has been solved! :smiley:

Greetings,

Robert


#7

We’re happy to read that you solved your issue!:grinning:

Best Regards,
Maria C.