ESP8266 Query UPDATE MySQL con variable no funciona

Hola gente este es mi primer post y espero cumplir con todas las normas. :smiley:
Buscando en el foro encontré situaciones similares pero a través de un script PHP y yo preciso hacerlo desde el mismo sketch

Estoy usando el modulo ESP8266 con el ejemplo basic_select de la librería MySQL connector

Con ese ejemplo logro tomar el id de una tabla y mi idea es es un segundo paso hacer un UPDATE a la tabla según la clausula WHERE donde ahí es que uso la variable obtenida varidPedido pero de este modo no realiza el UPDATE pero tampoco me da error el Sketch.
Si yo remplazo la variable dentro de la query2 por un valor manual funciona, pero la idea es que este valor sea dinámico.

Esta es la segunda query agregada con la variable varidPedido dentro de WHERE

char query2[] = "UPDATE sitiocero.pedidos SET impreso_pedidos = 1 WHERE pedidos.id_pedidos = varidPedido";

Y este es el código completo

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <MySQL_Connection.h>
#include <MySQL_Cursor.h>

// Replace these with your WiFi network settings
const char* ssid = "redwifi"; //replace this with your WiFi network name
const char* password = "noselaclave"; //replace this with your WiFi network password

WiFiClient client;
MySQL_Connection conn((Client *)&client);


char query[] = "SELECT id_pedidos FROM sitiocero.pedidos WHERE impreso_pedidos = 0 ORDER BY id_pedidos ASC LIMIT 1";
//**************
//Segunda query para actualizar segun id obtenida
//**************
char query2[] = "UPDATE sitiocero.pedidos SET impreso_pedidos = 1 WHERE pedidos.id_pedidos = varidPedido";


IPAddress server_addr(192,168,0,4);          // MySQL server IP
char mysqluser[] = "ardu";           // MySQL user
char mysqlpassword[] = "ardu";       // MySQL password
char guardado = '0';


void setup()

{
  delay(1000);
  Serial.begin(115200);
  WiFi.begin(ssid, password);

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

  Serial.println("Ferpecto!");
  Serial.print("La ip es: ");
  Serial.println(WiFi.localIP());

  while (conn.connect(server_addr, 3306, mysqluser, mysqlpassword) != true) {
    delay(200);
    Serial.print ( "." );
  }

  Serial.println("");
  Serial.println("Connected to SQL Server!");

}

void loop()  {
row_values *row = NULL;
long varidPedido = 0;
delay(1000);
// Initiate the query class instance
MySQL_Cursor *cur_mem = new MySQL_Cursor(&conn);
// Execute the query
cur_mem->execute(query);
// Fetch the columns (required) but we don't use them.
column_names *columns = cur_mem->get_columns();
// Read the row (we are only expecting the one)
do {
row = cur_mem->get_next_row();
if (row != NULL) {
varidPedido = atol(row->values[0]);

}
} while (row != NULL);

//***********
//Llamo segunda query para grabar el dato segun id obtenida
//***********
cur_mem->execute(query2);
// Deleting the cursor also frees up memory used
//delete cur_mem;
// Show the result
Serial.print(" Id del pedido = ");
Serial.println(varidPedido);

Serial.println(query2);


  //MySQL_Cursor *cur_mem = new MySQL_Cursor(&conn);
  // Execute the query
  //cur_mem->execute(query2);
  // Note: since there are no results, we do not need to read any data
  // Deleting the cursor also frees up memory used
  delete cur_mem;



}

Espero puedan decirme el por que y si es que todo esta bien segun las normas.
Saludos

Proba cambiar esto :

char query2[] = "UPDATE sitiocero.pedidos SET impreso_pedidos = 1 WHERE pedidos.id_pedidos = varidPedido";

por :

char query2[] = "UPDATE sitiocero.pedidos SET impreso_pedidos = 1 WHERE pedidos.id_pedidos = %ld";

despues, declaras a myquery como char y antes de hacer execute query pones :

sprintf(myquery,query2,varidPedido);
cur_mem->execute(myquery);

Tienes que reservar suficiente espacio para char query2[] y añadir el varidPedido con strcat

Aunque el esp8266 tiene bastante RAM, no viene demás recordar que cuando vamos a reservar memoria es mejor hacerlo dinamicamente y liberarla despues de usarla. Y evitar las variables globales, siempre que sea posible.

char query2[] = "UPDATE sitiocero.pedidos SET impreso_pedidos = 1 WHERE pedidos.id_pedidos = %ld";
  // Asigna a myquery el tamaño que tiene query2 + 10 caracteres para sustituir %ld

  char* myquery = new char[ sizeof(query2) + 10 ];
  sprintf(myquery,query2,varidPedido);
  cur_mem->execute(myquery);

  // libera la memoria
  delete myquery;

Mejor en vez de new declararlo solo local en la función y está.

Y el darosoft ya no da señales de vida. Seguro que ya lo ha solucionado

Guaaau, hay cantidades de respuestas. Muchas gracias.
Sigo con lo mismo pasa que pense que el foro me iba a avisar por correo jajaja.
Ya me pongo a probar y respondo para ver si lo podemos cerrar.
Gracias nuevamente

Bueno, el código funciono haciendo lo siguiente.

Asigne %ld a la consuta aunque no encontre que hace la "l" pero si "d" que devuelve un entero.

char query2[] = "UPDATE sitiocero.pedidos SET impreso_pedidos = 1 WHERE pedidos.id_pedidos = %ld";

Y despues hice lo de declarar un char para agregarlo a la cadena sprintf
y finalmente eliminar para liberar memoria.

  // Asigna a myquery el tamaño que tiene query2 + 10 caracteres para sustituir %ld

  char* myquery = new char[ sizeof(query2) + 10 ];
  sprintf(myquery,query2,varidPedido);
  cur_mem->execute(myquery);

  // libera la memoria
  delete myquery;

Hasta me anime a probar un procedimiento de MySQL y ahí dentro poner la variable de sprintf
y funciono.

char query2[] = "CALL sitiocero.2update(%d)";

Quedando el codigo de la siguiente manera.

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <MySQL_Connection.h>
#include <MySQL_Cursor.h>

// Replace these with your WiFi network settings
const char* ssid = "redwifi"; //replace this with your WiFi network name
const char* password = "clavewifi"; //replace this with your WiFi network password

WiFiClient client;
MySQL_Connection conn((Client *)&client);


char query[] = "SELECT id_pedidos FROM sitiocero.pedidos WHERE impreso_pedidos = 0 ORDER BY id_pedidos ASC LIMIT 1";
//Segunda query para actualizar segun id obtenida
char query2[] = "CALL sitiocero.2update(%d)";
char consultaUpdate[255];



IPAddress server_addr(192,168,0,9);          // MySQL server IP
char mysqluser[] = "usuario";           // MySQL user
char mysqlpassword[] = "clave";       // MySQL password


void setup()

{
  delay(1000);
  Serial.begin(115200);
  WiFi.begin(ssid, password);

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

  Serial.println("Ferpecto!");
  Serial.print("La ip es: ");
  Serial.println(WiFi.localIP());

  while (conn.connect(server_addr, 3306, mysqluser, mysqlpassword) != true) {
    delay(200);
  Serial.print ( "." );
  }

  Serial.println("");
  Serial.println("Connected to SQL Server!");

}

void loop()  {

row_values *row = NULL;
char varidPedido = 0;
delay(1000);

// Initiate the query class instance
MySQL_Cursor *cur_mem = new MySQL_Cursor(&conn);

// Execute the query
cur_mem->execute(query);

// Fetch the columns (required) but we don't use them.
column_names *columns = cur_mem->get_columns();

char* myquery = new char[ sizeof(query2) + 10];

// Read the row (we are only expecting the one)
do {
row = cur_mem->get_next_row();
if (row != NULL) {
  
varidPedido = atol(row->values[0]);

// Show the result
Serial.print(" Id del pedido = ");
Serial.println(varidPedido);
sprintf(myquery, query2, varidPedido);
Serial.println(myquery);

//****************
//imprimo consulta
//****************


}
} while (row != NULL);
sprintf(myquery, query2, varidPedido);

//***********
//Llamo segunda query para grabar el dato segun id obtenida
//***********
cur_mem->execute(myquery);

// Note: since there are no results, we do not need to read any data
// Deleting the cursor also frees up memory used
delete cur_mem;
delete myquery;

}

Algo extraño es que en lugar de imprimirme por serial el id de pedido me tira simbolos. No es necesario por que realiza bien la tarea pero me surgió esa duda

Y otra cosa es que si la primer consulta query la realizo como un procedimiento me da error

char query[] = "CALL sitiocero.1pedidos()";

Este es el error de salida por Serial

Error: 90 = Incorrect number of arguments for PROCEDURE sitiocero.1pedidos; expected 1, got 0.

Adjunto imagenes de como esta armado el procedimiento en MySQL, el error de salida por serial y el error de impresión de la id del pedido.

Gracias a todos, ahora tengo configurado para que me notifique de nuevas respuestas por correo :smiley:
Error con Procedimiento_1pedidos en Query

Rutina de MySQL

Salida serial con errores id pedido
Salida serial id pedido.jpg

Salida serial id pedido.jpg

Podrias probar este codigo ? ,solo hice un casteo de la variable char a String cuando imprime en el puerto serial

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <MySQL_Connection.h>
#include <MySQL_Cursor.h>

// Replace these with your WiFi network settings
const char* ssid = "redwifi"; //replace this with your WiFi network name
const char* password = "clavewifi"; //replace this with your WiFi network password

WiFiClient client;
MySQL_Connection conn((Client *)&client);


char query[] = "SELECT id_pedidos FROM sitiocero.pedidos WHERE impreso_pedidos = 0 ORDER BY id_pedidos ASC LIMIT 1";
//Segunda query para actualizar segun id obtenida
char query2[] = "CALL sitiocero.2update(%d)";
char consultaUpdate[255];



IPAddress server_addr(192,168,0,9);          // MySQL server IP
char mysqluser[] = "usuario";           // MySQL user
char mysqlpassword[] = "clave";       // MySQL password


void setup()

{
  delay(1000);
  Serial.begin(115200);
  WiFi.begin(ssid, password);

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

  Serial.println("Ferpecto!");
  Serial.print("La ip es: ");
  Serial.println(WiFi.localIP());

  while (conn.connect(server_addr, 3306, mysqluser, mysqlpassword) != true) {
    delay(200);
  Serial.print ( "." );
  }

  Serial.println("");
  Serial.println("Connected to SQL Server!");

}

void loop()  {

row_values *row = NULL;
char varidPedido = 0;
delay(1000);

// Initiate the query class instance
MySQL_Cursor *cur_mem = new MySQL_Cursor(&conn);

// Execute the query
cur_mem->execute(query);

// Fetch the columns (required) but we don't use them.
column_names *columns = cur_mem->get_columns();

char* myquery = new char[ sizeof(query2) + 10];

// Read the row (we are only expecting the one)
do {
row = cur_mem->get_next_row();
if (row != NULL) {
 
varidPedido = atol(row->values[0]);

// Show the result
Serial.print(" Id del pedido = ");
Serial.println(String(varidPedido));
sprintf(myquery, query2, varidPedido);
Serial.println(myquery);

//****************
//imprimo consulta
//****************


}
} while (row != NULL);
sprintf(myquery, query2, varidPedido);

//***********
//Llamo segunda query para grabar el dato segun id obtenida
//***********
cur_mem->execute(myquery);

// Note: since there are no results, we do not need to read any data
// Deleting the cursor also frees up memory used
delete cur_mem;
delete myquery;

}

Gracias Joaquin, pero sigue haciendo lo mismo.

castelarijoaquin:
Podrias probar este codigo ? ,solo hice un casteo de la variable char a String cuando imprime en el puerto serial

#include <ESP8266WiFi.h>

#include <WiFiClient.h>
#include <MySQL_Connection.h>
#include <MySQL_Cursor.h>

// Replace these with your WiFi network settings
const char* ssid = "redwifi"; //replace this with your WiFi network name
const char* password = "clavewifi"; //replace this with your WiFi network password

WiFiClient client;
MySQL_Connection conn((Client *)&client);

char query[] = "SELECT id_pedidos FROM sitiocero.pedidos WHERE impreso_pedidos = 0 ORDER BY id_pedidos ASC LIMIT 1";
//Segunda query para actualizar segun id obtenida
char query2[] = "CALL sitiocero.2update(%d)";
char consultaUpdate[255];

IPAddress server_addr(192,168,0,9);          // MySQL server IP
char mysqluser[] = "usuario";          // MySQL user
char mysqlpassword[] = "clave";      // MySQL password

void setup()

{
  delay(1000);
  Serial.begin(115200);
  WiFi.begin(ssid, password);

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

Serial.println("Ferpecto!");
  Serial.print("La ip es: ");
  Serial.println(WiFi.localIP());

while (conn.connect(server_addr, 3306, mysqluser, mysqlpassword) != true) {
    delay(200);
  Serial.print ( "." );
  }

Serial.println("");
  Serial.println("Connected to SQL Server!");

}

void loop()  {

row_values *row = NULL;
char varidPedido = 0;
delay(1000);

// Initiate the query class instance
MySQL_Cursor *cur_mem = new MySQL_Cursor(&conn);

// Execute the query
cur_mem->execute(query);

// Fetch the columns (required) but we don't use them.
column_names *columns = cur_mem->get_columns();

char* myquery = new char[ sizeof(query2) + 10];

// Read the row (we are only expecting the one)
do {
row = cur_mem->get_next_row();
if (row != NULL) {

varidPedido = atol(row->values[0]);

// Show the result
Serial.print(" Id del pedido = ");
Serial.println(String(varidPedido));
sprintf(myquery, query2, varidPedido);
Serial.println(myquery);

//****************
//imprimo consulta
//****************

}
} while (row != NULL);
sprintf(myquery, query2, varidPedido);

//***********
//Llamo segunda query para grabar el dato segun id obtenida
//***********
cur_mem->execute(myquery);

// Note: since there are no results, we do not need to read any data
// Deleting the cursor also frees up memory used
delete cur_mem;
delete myquery;

}

Asi seguro funciona, esta tomando el varidPedido como codigo ASCII y contiene simbolos segun el id Serial.println(varidPedido,DEC);

Funciona de maravilla !
Este es el resultado.
Nueva impresion Serial.jpg

Ahora me gustaría saber por que agregando la consulta query como procedimiento de almacenado da el error.

castelarijoaquin:
Asi seguro funciona, esta tomando el varidPedido como codigo ASCII y contiene simbolos segun el id Serial.println(varidPedido,DEC);

Nueva impresion Serial.jpg

Te dice claramente que no estas enviando los parametros al procedimiento, obtiene un cero cuando espera un 1. No te puedo ayudar mas sin el codigo del cambio que hiciste. Podrias publicar el procedimiento que estas llamando, para ver si le estas pasando los parametros que pide. O agregale un 1 como te esta pidiendo.

@castelarijoaquin
Tenes razon jaja, Bueno hice un par de pruebas y logre que me muestre la id del pedido.
Pero muestra el primer resultado y luego me da error, Arduino se resetea... vuelve a conectarse y cumple el ciclo nuevamente.

Codigo Completo.

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <MySQL_Connection.h>
#include <MySQL_Cursor.h>

// Replace these with your WiFi network settings
const char* ssid = "redwifi"; //replace this with your WiFi network name
const char* password = "clavewifi"; //replace this with your WiFi network password

WiFiClient client;
MySQL_Connection conn((Client *)&client);


char query[] = "CALL sitiocero.1pedidos(@p_idout)";
//char query[] = "SELECT id_pedidos FROM sitiocero.pedidos WHERE impreso_pedidos = 0 ORDER BY id_pedidos ASC LIMIT 1;";
//Segunda query para actualizar segun id obtenida
char query2[] = "CALL sitiocero.2update(%d)";
char consultaUpdate[255];



IPAddress server_addr(192,168,0,9);          // MySQL server IP
char mysqluser[] = "usuario";           // MySQL user
char mysqlpassword[] = "clave";       // MySQL password


void setup()
{delay(500);Serial.begin(115200);WiFi.begin(ssid, password);Serial.println();Serial.print("Conectando");while (WiFi.status() != WL_CONNECTED){delay(500);Serial.print(".");}Serial.println("Ferpecto!");Serial.print("La ip es: ");Serial.println(WiFi.localIP());while (conn.connect(server_addr, 3306, mysqluser, mysqlpassword) != true) {delay(200);Serial.print ( "." );}Serial.println("");Serial.println("Connected to SQL Server!");}

void loop()  {

row_values *row = NULL;
char varidPedido = 0;
//delay(90);

// Initiate the query class instance
MySQL_Cursor *cur_mem = new MySQL_Cursor(&conn);

// Execute the query
cur_mem->execute(query);

// Fetch the columns (required) but we don't use them.
column_names *columns = cur_mem->get_columns();

char* myquery = new char[ sizeof(query2) + 10];

// Read the row (we are only expecting the one)
do {
row = cur_mem->get_next_row();

if (row != NULL) {
 
varidPedido = atol(row->values[0]);

// Show the result
Serial.print(" Id del pedido = ");
Serial.println(varidPedido,DEC);
//Serial.println(String(varidPedido));
sprintf(myquery, query2, varidPedido);
Serial.println(myquery);


}
} while (row != NULL);
sprintf(myquery, query2, varidPedido);

//***********
//Llamo segunda query para grabar el dato segun id obtenida
//***********
cur_mem->execute(myquery);

// Note: since there are no results, we do not need to read any data
// Deleting the cursor also frees up memory used
varidPedido = NULL;
delete cur_mem;
delete myquery;

}

Ahi deje el codigo con las 2 opciones de Query una con procedimiento y la otra manual.
Esta captura es el error por serial con la Query con procedimiento.

Y esta es una captura del procedimiento, Le configure para que la salida sea de tipo entero y funciono... pero como te comentaba detecta un id y luego en el proximo bucle da error, se desconecta y se vuelve a conectar para volver a realizar el ciclo nuevamente.

Si quieres saber donde se la pega el esp puedes analizar el volcado del stack.
Mira aquí para instalar el decodificador del volcado de la pila en el IDE de arduino. Te mostrará las funciones que se han ido llamando, la primera será loop y la ultima la que ha provocado la excepción. Bueno, creo recordar que se muestra al revés de como he dicho. Sirve para hacerse una idea de donde está fallando el programa.
Normalmente es un puntero que no apunta donde debería o que se ha quedado sin memoria.
El tipo de excepción lo puede ver aquí.

Es que creo que el error lo esta produciendo la librería mysql al no manejar bien la query, cuando es una llamada a procedimiento almacenado.

saludos.

harkonnen:
Si quieres saber donde se la pega el esp puedes analizar el volcado del stack.
Mira aquí para instalar el decodificador del volcado de la pila en el IDE de arduino. Te mostrará las funciones que se han ido llamando, la primera será loop y la ultima la que ha provocado la excepción. Bueno, creo recordar que se muestra al revés de como he dicho. Sirve para hacerse una idea de donde está fallando el programa.
Normalmente es un puntero que no apunta donde debería o que se ha quedado sin memoria.
El tipo de excepción lo puede ver aquí.

Es que creo que el error lo esta produciendo la librería mysql al no manejar bien la query, cuando es una llamada a procedimiento almacenado.

saludos.

Gracias, lo estuve investigando y parece ser tal cual... un error pero solo con procedimientos.
Gracias por tu info para hacerle un análisis mas en profundidad a la cuestión voy a analizarlo y avisar

Asegúrate que la librería MySQL funciona correctamente con el ESP8266. Mira los comentarios en Github a ver si si hay reportes similares.
Generalmente no eres el primero en experimentar algo, y nutrirse de la experiencia de los demás ahorra mucho tiempo.