¿Como hacer consultas a InfluxDB de varias columnas?

Hola!
Estoy intentando hacer consultas a una base de datos creada con InfluxDB y alojada en mi Raspberry.
Siguiendo el ejemplo de la librería de Tobias Schuerg y el post de un compañero de este foro, consigo las peticiones por defecto, pero al intentar aplicarlo a mi código, no consigo leer más de una columna.
No entiendo bien como hacer las consultas y por más que leo o busco en la red, no lo consigo.

Las consultas son algo así:

String query = "from(bucket: \"" INFLUXDB_BUCKET "\") |> range(start: -5s) |> filter(fn: (r) => r._measurement == \"Datos\""; 
 query += " and r._field == \"Hume\"";
 query += " and r.device == \""  DEVICE  "\")";

Yo quiero obtener 3 campos como Hume, pero no se hacer la petición. Mirando la documentación de InfluxDB no consigo aclararme.

/*
Prueba de consulta a la base de datos InfluxDB alojada en la Raspberry pi.
https://forum.arduino.cc/index.php?topic=691477.0
*/
#include <Arduino.h>
#include <config.h>
#include <InfluxDbClient.h>
#include <InfluxDbCloud.h>

// Set timezone string according to https://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html
// Examples:
//  Pacific Time: "PST8PDT"
//  Eastern: "EST5EDT"
//  Japanesse: "JST-9"
//  Central Europe: "CET-1CEST,M3.5.0,M10.5.0/3"
#define TZ_INFO "CET-1CEST,M3.5.0,M10.5.0/3"  //Zona horaria.

// InfluxDB client instance with preconfigured InfluxCloud certificate
InfluxDBClient client(INFLUXDB_URL, INFLUXDB_ORG, INFLUXDB_BUCKET, INFLUXDB_TOKEN, InfluxDbCloud2CACert);
 
void Valor() 
{
  // Construct a Flux query. r.measurement es el equivalente a "name" en la base de datos. r.field, los campos a listar
 String query = "from(bucket: \"" INFLUXDB_BUCKET "\") |> range(start: -5s) |> filter(fn: (r) => r._measurement == \"Datos\""; 
 query += " and r._field == \"Hume\"";
 query += " and r.device == \""  DEVICE  "\")";
 
 Serial.println("==== Listando resultados ====");
 
  // Print composed query
  Serial.print("Petición con: ");
  Serial.println(query);

  // Send query to the server and get result
  FluxQueryResult result = client.query(query);

  // Iterate over rows. Even there is just one row, next() must be called at least once.
  while (result.next()) 
  { 
    String ssid_sign = result.getValueByName("SSID").getString();  //Guardamos el valor del SSID en una variable.
    Serial.print ("El SSID es: ");
    Serial.println (ssid_sign);
    
    /*double hic = result.getValueByName("_value").getDouble();
    Serial.print ("El índice de calor es: ");
    Serial.print (hic);
    Serial.println ("ºC");*/

    double hume = result.getValueByName("_value").getDouble();
    Serial.print ("La humedad es: ");
    Serial.print (hume);
    Serial.println ("%");

    long rssi_sign = result.getValueByName("_value").getLong();
    Serial.print ("La RSSI es: ");
    Serial.print (rssi_sign);
    Serial.println ("dBm");

    // Get converted value for the _time column
      FluxDateTime time = result.getValueByName("_time").getDateTime();
    // Format date-time for printing
    // Format string according to http://www.cplusplus.com/reference/ctime/strftime/
      String timeStr = time.format("%F %T");

      Serial.print("La fecha de la medición es: ");
      Serial.println (timeStr);

   /* // Check for new grouping key
    if(result.hasTableChanged()) {
      Serial.println("Tabla:");
      Serial.print("  ");
      // Print all columns name
      for(String &name: result.getColumnsName()) {
        Serial.print(name);
        Serial.print(",");
      }
      Serial.println();
      Serial.print("  ");
      // Print all columns datatype
      for(String &tp: result.getColumnsDatatype()) {
        Serial.print(tp);
        Serial.print(",");
      }
      Serial.println();
    }
    Serial.print("  ");*/
    // Print values of the row
    /*for(FluxValue &val: result.getValues()) {
      // Check wheter the value is null
      if(!val.isNull()) {
        // Use raw string, unconverted value
        Serial.print(val.getRawValue());
      } else {
        // Print null value substite
        Serial.print("<null>");  
      }
      Serial.print(",");
    }
    Serial.println();*/
  }
  // Check if there was an error
  if(result.getError() != "") {
    Serial.print("Error en la petición: ");
    Serial.println(result.getError());
  }

  // Close the result
  result.close();
}

void setup() 
{
  Serial.begin(9600);

  // Setup wifi
  WiFi.mode(WIFI_STA);
  wifiMulti.addAP(WIFI_SSID, WIFI_PASSWORD);

  Serial.print("Conectando a la red wifi");
  while (wifiMulti.run() != WL_CONNECTED) 
  {
    Serial.print(".");
    delay(500);
  }
  Serial.println();

  // Accurate time is necessary for certificate validation
  // For the fastest time sync find NTP servers in your area: https://www.pool.ntp.org/zone/
  // Syncing progress and the time will be printed to Serial
  timeSync(TZ_INFO, "pool.ntp.org", "time.nis.gov");

  Serial.println("WiFi conectada");
  Serial.println("IP: ");
  Serial.print(WiFi.localIP());

  Serial.println();

  // Check server connection
  if (client.validateConnection()) {
    Serial.print("Conectado a la base de datos InfluxDB: ");
    Serial.println(client.getServerUrl());
  }
  else {
    Serial.print("Error de conexión a la base de datos InfluxDB: ");
    Serial.println(client.getLastErrorMessage());
  }
}

void loop() 
{
  Valor();
  Serial.println("Espera 10s");
  delay(10000);
}

No se si debería hacer una petición por cada valor que quiera recuperar, pero dudo que sea lo correcto.
Este ejemplo son solo 4 valores que quiero recuperar, pero la idea es pasarlo a otro proyecto en el que he de recuperar unos 14 valores y hacer 14 peticiones no creo sea solución.
¿Alguien podría orientarme por donde continuar?
Gracias y un saludo!

Buenas, modificando la siguiente línea he avanzado algo.

String query = "from(bucket: \"" INFLUXDB_BUCKET "\") |> range(start: -10s)";

Consigo que me muestre las 3 lecturas solicitadas. Temperatura, humedad e índice de calor, a parte de la señal RSSI

==== Listando resultados ====
Petición con: from(bucket: "DHT22") |> range(start: -10s)
El SSID es: RedWifi
La humedad es: 16.67%
La temperatura es: 16.67ºC
El índice de calor es: 16.67ºC
La RSSI es: 0dBm
La fecha de la medición es: 2021-03-09 07:20:25
----------------------------------------------- //Separo para una mejor comprensión, en el monitor serie sale seguido.
El SSID es: RedWifi
La humedad es: 69.00%
La temperatura es: 69.00ºC
El índice de calor es: 69.00ºC
La RSSI es: 0dBm
La fecha de la medición es: 2021-03-09 07:20:25
-----------------------------------------------
El SSID es: RedWifi
La humedad es: 17.10%
La temperatura es: 17.10ºC
El índice de calor es: 17.10ºC
La RSSI es: 0dBm
La fecha de la medición es: 2021-03-09 07:20:25
-----------------------------------------------
El SSID es: RedWifi
La humedad es: 0.00%
La temperatura es: 0.00ºC
El índice de calor es: 0.00ºC
La RSSI es: -45dBm
La fecha de la medición es: 2021-03-09 07:20:25

Por lo que veo al estar en un bucle me muestra 4 veces los resultados. En cada muestra el valor es correcto solo para la primera variable, en la segunda, para la segunda variable...etc.

Mirando la documentación oficial de Influx para ver si se puede limitar los resultados de alguna manera, encontré la función limit()

String query = "from(bucket: \"" INFLUXDB_BUCKET "\") |> range(start: -10s) |> limit(n: 1)";

Pero el resultado es el mismo.
Sigo investigando :slight_smile:

Buenas!!
Ya está solucionado.
Pregunté al creador de la librería y me dio la solución.
Hay que usar la función de influxDB pivot()
Con ella nos da los resultados en la misma línea.

Quedaría algo así:

String query = "from(bucket: \"" INFLUXDB_BUCKET "\") |> range(start: -60s)";
  query += " |> filter(fn: (r) => r._measurement == \"Datos\" and (r._field == \"Hume\")";
  query += " or r._field == \"Temp\" or r._field == \"rssi\" or r._field == \"Hic\")";
  query += " |> pivot(rowKey:[\"_time\"], columnKey: [\"_field\"], valueColumn: \"_value\")";

Espero le sirva a alguien.

Saludos.

¡¡ Gracias por compartir la solución !!

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.