I am working with an esp8266, with the ubidots.h library and the http protocol, I use two devices, in one I send data to the server and in the other I receive and process them, in general I send 18 variables to the server and they take 2 seconds to arrive , but when requesting them in the other device it takes an average of 40 seconds, (2 or 3 seconds per variable), I am something new working with ubidots, I understand how multiple variables are sent at the same time, is there a way to receive all variables at the same time?
I send the variables with ubidots.add and ubidots.send, and to receive with ubidots.get (DEVICE_LABEL, LAB_SEND11), I do not pretend that it is in real time but for the project in which I work 40 seconds is a long time. thanks for your help
Good day @YesidGarcia
Thank you for reaching out to Ubidots, weâre glad that you are building an application with us.
To answer your questions:
If you use the HTTP protocol with the Ubidots library
, it is normal that reading the 18 variables from the second ESP8266 takes up to 40 seconds because it is sequential, and each GET query might take anywhere between 1 to 3 seconds. On top of that, as you have a STEM account, this type of account only allows 1 request per second. In addition to this, the ESP8266 HTTPâs library doesnât include a method to retrieve multiple variableâs last value at once.
With this being clear, Iâd like to recommend using the MQTT protocol in the second device (the one that receive the values from Ubidots), that way, you could subscribe to all the variables and get the updates almost instantaneously. Makes sense?
NOTE: Please refer to this link to know how to use the MQTT protocol with your ESP8266. Also, You must include the UbitosESPMQTT
library, please download it here. If you need to know anything else about how to use the MQTT protocol with Ubidots, please refer to this link.
However, the next week weâd share a code example of the MQTT subscription.
All the best,
Ăngela
Hello @YesidGarcia
Hereâs the code example of the MQTT subscription for your second device. This way, youâll be able to receive all variables at the same time.
//Include Libraries
#include "UbidotsESPMQTT.h"
//Define Constants
#define TOKEN "YOUR-UBIDOTS-TOKEN"
#define WIFINAME "YOUR-WIFI"
#define WIFIPASS "YOUR-WIFI-PASSWORD"
#define DEVICE_LABEL "YOUR-DEVICE-LABEL"
char *var_labels[] = {
"YOUR-VARIABLE-LABEL-1",
"YOUR-VARIABLE-LABEL-2",
"YOUR-VARIABLE-LABEL-3",
"YOUR-VARIABLE-LABEL-4"
// Add more variable labels here. Do not forget the comma ;)
};
#define DIMENSION_OF(x) (sizeof(x)/sizeof(x[0]))
float var_last_values[DIMENSION_OF(var_labels)] = {};
Ubidots client(TOKEN);
//Callback function
void callback(char* topic, byte* payload, unsigned int length) {
// Limitations: Variable label must not be the same as device label
char *topic_cpy = strdup(topic);
char *payload_str = (char *) malloc(length + sizeof(""));
char *topic_item = strtok(topic_cpy, "/");
char *label = NULL;
float value = NAN;
size_t index = DIMENSION_OF(var_labels);
size_t i;
memcpy(payload_str, payload, length);
payload_str[length] = '\0';
while ((NULL != topic_item) && (NULL == label)) {
for (i = 0; i < DIMENSION_OF(var_labels); i++) {
if (0 == strcmp(var_labels[i], topic_item)) {
label = topic_item;
value = atof((char *) payload);
index = i;
break;
}
}
topic_item = strtok(NULL, "/");
}
if (index < DIMENSION_OF(var_labels)) {
var_last_values[index] = value;
Serial.print(label);
Serial.print(": ");
Serial.println(value);
}
free(topic_cpy);
free(payload_str);
}
//Suscribe function
void subscribe_to_vars(char **labels, size_t n_labels) {
size_t i;
for (i = 0; i < n_labels; i++) {
char *label = labels[i];
client.ubidotsSubscribe(DEVICE_LABEL, label);
}
}
//Print last values function
void print_last_values(void) {
char str_buff[64] = "";
size_t i;
for (i = 0; i < DIMENSION_OF(var_labels); i++) {
snprintf(str_buff, sizeof(str_buff), "%s: %f", var_labels[i], var_last_values[i]);
Serial.println(str_buff);
}
}
//Main functions
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
client.setDebug(true); // Pass a true or false bool value to activate debug messages
client.wifiConnection(WIFINAME, WIFIPASS);
client.begin(callback);
subscribe_to_vars(var_labels, DIMENSION_OF(var_labels));
}
void loop() {
// put your main code here, to run repeatedly:
if (!client.connected()) {
client.reconnect();
subscribe_to_vars(var_labels, DIMENSION_OF(var_labels));
}
client.loop();
}
Please be aware that firstly, you need to define the constants of your code with your account information (in the below segment):
//Define Constants
#define TOKEN "YOUR-UBIDOTS-TOKEN"
#define WIFINAME "YOUR-WIFI"
#define WIFIPASS "YOUR-WIFI-PASSWORD"
#define DEVICE_LABEL "YOUR-DEVICE-LABEL"
char *var_labels[] = {
"YOUR-VARIABLE-LABEL-1",
"YOUR-VARIABLE-LABEL-2",
"YOUR-VARIABLE-LABEL-3",
"YOUR-VARIABLE-LABEL-4"
// Add more variable labels here. Do not forget the comma ;)
};
NOTE: Bear in mind that the Ubidots library only supports the ESP8266 platform version v.2.7.4. Please, when installing this platform, make sure that youâre using the correct version.
Let me know if you need anything else!
All the best,
Ăngela
We want to read multiple variable last value using HTTP/REST API. Please suggest efficient single call API.
regards,
Sunand
Hello Sunand and everyone,
To get the last value for multiple variables in a single call, you could use the Get Device Last Values Endpoint or the Raw Series Endpoint, however, itâs important to know that each has itâs own scope: the Device Last Values Endpoint gets the Last Values for each variable within a Device, while the Raw Series Endpoint gets the values for a list of variables (independent of which Device it comes from).
Device Last Values
GET https://industrial.api.ubidots.com/api/v2.0/devices/<device_key>/_/values/last
Where <device_key>
is replaced with the ID or label (prefix the label with ~) of the Device.
Raw Series
To make sure you only get the last value of each variable, you need to:
- Not specify the start or end keys
- Include the limit key with a value of 1
In that sense, your request would look something like this:
Endpoint
POST https://industrial.api.ubidots.com/api/v1.6/data/raw/series
Body
{
"variables": [
"62c4877hh8975656ccd7aa11",
"62c48886gj0866tg5f858c452",
"628j08y788768251dc355e15"
],
"columns": [
"value.value",
"timestamp"
],
"join_dataframes": "false",
"limit": 1
}
Where in the variables
object you specify the IDs of the variables that you want to get the data from, and in the columns
object you specify what data youâd like to get from the last Dot. In this example youâd get the value
and the timestamp
. If you also wanted to get the Dotâs context, then you would add the âvalue.context
â element
Best regards,
SebastiĂĄn
Dear @Sebastian
Thanks for prompt reply. With this API, the problem that I see that we need to pass variable IDs
As I mentioned earlier, we donât have variable IDs available in custom HTML. We work only with API labels (from our device). We want somewhat generic dashboard with customer HTML across devices. We can manage to change device token when we move dashboard. But, keeping track of 16 variable IDs for each device is a challenge.
We use v2.0 API to fetch all variable information. And then filter out relevant variableâs last values using API labels. It should be ok for us.
thanks,
Sunand