Eigentlich ist diese strtok "Frickelei" nicht notwendig.
Beispieldatenbank:
create table data(
dev_id SMALLINT UNSIGNED not null,
winterval INT UNSIGNED not null,
wtime_min INT UNSIGNED not null,
wtime INT UNSIGNED not null,
dry_val INT UNSIGNED not null,
dev_name NCHAR VARCHAR(20) not null,
primary key(dev_id)
);
INSERT INTO data (dev_id, winterval, wtime_min, wtime, dry_val, dev_name )
VALUES
(0, 30000, 5000, 10000,400,'Vent.1'),
(1, 30000, 5000, 5000, 40, 'Vent.2');
Für jedes Ventil ist ein eigener Datensatz vorhanden.
Programm zum Auslesen:
#include <Arduino.h>
#include <WiFiManager.h> // https://github.com/tzapu/WiFiManager
#include <ESP32_MySQL.h> // https://github.com/Syafiqlim/ESP32_MySQL
#include "Credentials.h"
using uint = unsigned int;
class WateringDevice {
public:
WateringDevice(uint Id, uint WInterval, uint WTimeMin, uint WTime, uint DryValue, const char* Name = "default")
: Id {Id}, WInterval {WInterval}, WTimeMin {WTimeMin}, WTime {WTime}, DryValue {DryValue} {
strncpy(this->Name, Name, gc::MaxNameLengh);
}
void setId(uint Id) { this->Id = Id; }
void setWateringInterval(uint WInterval) { this->WInterval = WInterval; }
void setMinWateringTime(uint WTimeMin) { this->WTimeMin = WTimeMin; }
void setWateringTime(uint WTime) { this->WTime = WTime; }
void setDryValue(uint DryValue) { this->DryValue = DryValue; }
void setName(const char* Name) { strncpy(this->Name, Name, gc::MaxNameLengh); }
uint getId() const { return Id; }
uint getWateringInterval() const { return WInterval; }
uint getWateringTime() const { return WTime; }
uint getWateringTimeMin() const { return WTimeMin; }
uint getDryValue() const { return DryValue; }
const char* getName() const { return Name; }
private:
uint Id;
uint WInterval;
uint WTimeMin;
uint WTime;
uint DryValue;
char Name[gc::MaxNameLengh + 1];
};
WateringDevice Device[gc::MaxDevices] {
{0, 0, 0, 0, 0, "default"},
{0, 0, 0, 0, 0, "default"}
};
#define ESP32_MYSQL_DEBUG_PORT Serial
// Debug Level from 0 to 4
#define _ESP32_MYSQL_LOGLEVEL_ 1
// #define USING_HOST_NAME true
#if USING_HOST_NAME
// Optional using hostname
char Server[] = "xxxxx.com"; // change to your server's hostname/URL
#else
IPAddress Server(xxx, xxx, xxx, xxx);
#endif
WiFiManager Wm;
bool wifiConnect() {
WiFi.mode(WIFI_STA);
// WiFiManager, Local intialization. Once its business is done, there is no need to keep it around
Wm.setSTAStaticIPConfig(IPAddress(xxx, xxx, xxx, xxx), // Host IP
IPAddress(xxx, xxx, xxx, xxx), // Gateway
IPAddress(255, 255, 255, 0), // Netmask
IPAddress(xxx, xxx, xxx, xxx)); // DNS
Wm.setHostname("ESP32Dev");
bool Result = Wm.autoConnect("AutoConnectAP", "Geheim"); // Password protected ap
(!Result) ? Serial.println("Failed to connect") : Serial.println("connected...yeey :");
return Result;
}
template <size_t N> void runQueryResultSet(ESP32_MySQL_Connection& Conn, const char* Query, WateringDevice (&Dev)[N]) {
// Create an instance of the cursor passing in the connection
ESP32_MySQL_Query SqlQuery = ESP32_MySQL_Query(&Conn);
// Execute the Query
if (!SqlQuery.execute(Query)) {
Serial.println("Querying error");
return;
}
SqlQuery.get_columns(); // Must be executed if a data row is to be read out.
uint Idx {0};
row_values* Row {NULL};
do {
Row = SqlQuery.get_next_row();
if (Row != NULL) {
Dev[Idx].setId(atoi(Row->values[0]));
Dev[Idx].setWateringInterval(atoi(Row->values[1]));
Dev[Idx].setMinWateringTime(atoi(Row->values[2]));
Dev[Idx].setWateringTime(atoi(Row->values[3]));
Dev[Idx].setDryValue(atoi(Row->values[4]));
Dev[Idx].setName(Row->values[5]);
}
} while (Row != NULL && ++Idx < N);
}
void setup() {
Serial.begin(115200);
while (!Serial && millis() < 5000); // wait for serial port to connect
// Begin WiFi section
while (!wifiConnect()) { ; }
Serial.println("Connecting Database...");
ESP32_MySQL_Connection Connection((Client*)&client);
if (Connection.connectNonBlocking(Server, gc::ServerPort, MySQLUser, MySQLPassword) != RESULT_FAIL) {
delay(500);
runQueryResultSet(Connection, "Select * FROM esp32data.data ORDER BY dev_id", Device);
Connection.close(); // close the connection
} else {
Serial.println("\nConnect failed. Program halted!");
}
Wm.disconnect();
WiFi.mode(WIFI_OFF);
WiFi.setSleep(true);
delay(10);
}
void loop() {
for (size_t I {0}; I < gc::MaxDevices; ++I) {
Serial.print("Device Id: ");
Serial.println(Device[I].getId());
Serial.println(Device[I].getWateringInterval());
Serial.println(Device[I].getWateringTimeMin());
Serial.println(Device[I].getWateringTime());
Serial.println(Device[I].getDryValue());
Serial.println(Device[I].getName());
Serial.println();
}
delay(15000);
}
Eine Beispiel Credentials.h
#pragma once
char MySQLUser[] {"esp32user"}; // MySQL user login username
char MySQLPassword[] {"Password"}; // MySQL user login password
namespace gc {
const char* ACPassword {"ACPassword"};
constexpr size_t MaxDevices {2};
constexpr size_t MaxNameLengh {20};
constexpr size_t MaxQStringLength {50};
constexpr uint16_t ServerPort {3306};
constexpr char DefaultDatabase[] {"esp32data"};
constexpr char DefaultTable[] {"data"};
} // namespace gc
Funktioniert so ganz gut. Die Klasse WateringDevice ist aus dem Beispiel von @Combi hervorgegangen.