First Commit
This commit is contained in:
82
libraries/MySQL_Connector_Arduino/CHANGES.txt
Normal file
82
libraries/MySQL_Connector_Arduino/CHANGES.txt
Normal file
@@ -0,0 +1,82 @@
|
||||
CHANGES
|
||||
=======
|
||||
This file contains a brief summary of changes made from previous versions of
|
||||
the connector.
|
||||
|
||||
1.2.0 - March 2020
|
||||
------------------
|
||||
* Added connect with default database.
|
||||
* Added rows effected, last insert id.
|
||||
* Stability and speed improvements.
|
||||
* Removed infinite wait in read_packet() if connection dropped.
|
||||
Merged wait_for_client() and wait_for_data() into one
|
||||
universal wait_for_bytes(int).
|
||||
* Improved connect() speed.
|
||||
* Improved sending queries speed.
|
||||
Sending the whole buffer at a time (not byte by byte).
|
||||
* Fixed bug with check_ok_packet() return value.
|
||||
check_ok_packet() simplified to get_packet_type().
|
||||
* Added checks for buffer validity in places it is going to be used.
|
||||
Improved stability on "incorrect" methods calls.
|
||||
* Restored WITH_SELECT, but defined by default.
|
||||
* Added DEBUG define to avoid prints to Serial port.
|
||||
Useful when Serial is used to communicate with sensors.
|
||||
* Added example for ESP8266.
|
||||
|
||||
1.1.1a - January 2016
|
||||
---------------------
|
||||
* Minor issue with deprecated #import fixed. No new functionality.
|
||||
|
||||
1.1.0a - January 2016
|
||||
---------------------
|
||||
* Major redesign of classes. Now have separate connection and cursor classes
|
||||
* Removed WITH_SELECT, WITH_WIFI, etc. to avoid confusion and simplify
|
||||
* Renamed many methods to correspond with traditional MySQL connector
|
||||
nomenclature
|
||||
* Added more error handling for lossy networks
|
||||
* Memory deallocation methods consolidated (see examples)
|
||||
* More, smaller examples added
|
||||
* Documentation updated
|
||||
|
||||
1.0.4ga - July 2015
|
||||
--------------------
|
||||
* Fixed a defect in the get_next_row() method.
|
||||
* Added the reference manual. Yippee!
|
||||
|
||||
1.0.3rc - March 2015
|
||||
--------------------
|
||||
* Code has been changed slightly to help with long latency issues over
|
||||
wifi and slow connections.
|
||||
* A new cleanup method was added to cleanup a final OK packet after a
|
||||
stored procedure call with a result.
|
||||
* Code now compiles without errors for the latest Beta Arduino IDE
|
||||
(const error).
|
||||
|
||||
1.0.2b - April 2014
|
||||
-------------------
|
||||
* The WITH_SELECT is turned *OFF* by default. If you want to use select
|
||||
queries, be sure to uncomment this in the mysql.h file.
|
||||
* Reduced memory use! The library has been trimmed to save memory.
|
||||
- All static strings moved to PROGMEM strings
|
||||
- Unused structures removed (e.g. ok_packet)
|
||||
- Moved more methods not needed to optional compilation
|
||||
|
||||
1.0.1b - February 2014
|
||||
----------------------
|
||||
* Added disconnect() method for disconnecting from server.
|
||||
* Improved error handling for dropped packets.
|
||||
* Better error handling for lost connections and out of memory detection.
|
||||
|
||||
1.0.0b - October 2013
|
||||
---------------------
|
||||
* Improved support for result sets (select queries)
|
||||
* Added conditional compile for use with select queries. If you don't use
|
||||
select queries, comment out WITH_SELECT in mysql.h to save some memory.
|
||||
* Added support for WiFi shield using conditional compilation.
|
||||
* New version() method to check version of the connector.
|
||||
* Simplified, single-file download
|
||||
|
||||
Initial Release - April 2013
|
||||
----------------------------
|
||||
* Basic query capability
|
||||
* Basic result set handling
|
||||
9
libraries/MySQL_Connector_Arduino/README.md
Normal file
9
libraries/MySQL_Connector_Arduino/README.md
Normal file
@@ -0,0 +1,9 @@
|
||||
MySQL Connector/Arduino
|
||||
=======================
|
||||
Have you ever wanted to connect your Arduino project to a database to either store the data you've collected or retrieve data saved to trigger events in your sketch? Well, now you can connect your Arduino project directly to a MySQL server without using an intermediate computer or a web- or cloud-based service. Having direct access to a database server means you can store data acquired from your project as well as check values stored in tables on the server.
|
||||
|
||||
This also means you can setup your own, local MySQL server to store your data further removing the need for Internet connectivity. If that is not an issue, you can still connect to and store data on a MySQL server via your network, Internet, or even in the cloud!
|
||||
|
||||
The MySQL Connector/Arduino is a library that permits you to do exactly that and more!
|
||||
|
||||
See the all new [wiki documentation](https://github.com/ChuckBell/MySQL_Connector_Arduino/wiki) for how to get starting using the library.
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
MySQL Connector/Arduino Example : basic insert
|
||||
|
||||
This example demonstrates how to issue an INSERT query to store data in a
|
||||
table. For this, we will create a special database and table for testing.
|
||||
The following are the SQL commands you will need to run in order to setup
|
||||
your database for running this sketch.
|
||||
|
||||
CREATE DATABASE test_arduino;
|
||||
CREATE TABLE test_arduino.hello_arduino (
|
||||
num integer primary key auto_increment,
|
||||
message char(40),
|
||||
recorded timestamp
|
||||
);
|
||||
|
||||
Here we see one database and a table with three fields; a primary key that
|
||||
is an auto_increment, a string, and a timestamp. This will demonstrate how
|
||||
to save a date and time of when the row was inserted, which can help you
|
||||
determine when data was recorded or updated.
|
||||
|
||||
For more information and documentation, visit the wiki:
|
||||
https://github.com/ChuckBell/MySQL_Connector_Arduino/wiki.
|
||||
|
||||
INSTRUCTIONS FOR USE
|
||||
|
||||
1) Create the database and table as shown above.
|
||||
2) Change the address of the server to the IP address of the MySQL server
|
||||
3) Change the user and password to a valid MySQL user and password
|
||||
4) Connect a USB cable to your Arduino
|
||||
5) Select the correct board and port
|
||||
6) Compile and upload the sketch to your Arduino
|
||||
7) Once uploaded, open Serial Monitor (use 115200 speed) and observe
|
||||
8) After the sketch has run for some time, open a mysql client and issue
|
||||
the command: "SELECT * FROM test_arduino.hello_arduino" to see the data
|
||||
recorded. Note the field values and how the database handles both the
|
||||
auto_increment and timestamp fields for us. You can clear the data with
|
||||
"DELETE FROM test_arduino.hello_arduino".
|
||||
|
||||
Note: The MAC address can be anything so long as it is unique on your network.
|
||||
|
||||
Created by: Dr. Charles A. Bell
|
||||
*/
|
||||
#include <Ethernet.h>
|
||||
#include <MySQL_Connection.h>
|
||||
#include <MySQL_Cursor.h>
|
||||
|
||||
byte mac_addr[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
|
||||
|
||||
IPAddress server_addr(10,0,1,35); // IP of the MySQL *server* here
|
||||
char user[] = "root"; // MySQL user login username
|
||||
char password[] = "secret"; // MySQL user login password
|
||||
|
||||
// Sample query
|
||||
char INSERT_SQL[] = "INSERT INTO test_arduino.hello_arduino (message) VALUES ('Hello, Arduino!')";
|
||||
|
||||
EthernetClient client;
|
||||
MySQL_Connection conn((Client *)&client);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
while (!Serial); // wait for serial port to connect
|
||||
Ethernet.begin(mac_addr);
|
||||
Serial.println("Connecting...");
|
||||
if (conn.connect(server_addr, 3306, user, password)) {
|
||||
delay(1000);
|
||||
}
|
||||
else
|
||||
Serial.println("Connection failed.");
|
||||
}
|
||||
|
||||
|
||||
void loop() {
|
||||
delay(2000);
|
||||
|
||||
Serial.println("Recording data.");
|
||||
|
||||
// Initiate the query class instance
|
||||
MySQL_Cursor *cur_mem = new MySQL_Cursor(&conn);
|
||||
// Execute the query
|
||||
cur_mem->execute(INSERT_SQL);
|
||||
// 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;
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
MySQL Connector/Arduino Example : connect by wifi
|
||||
|
||||
This example demonstrates how to connect to a MySQL server from an
|
||||
Arduino using an Arduino-compatible Wifi shield. Note that "compatible"
|
||||
means it must conform to the Ethernet class library or be a derivative
|
||||
with the same classes and methods.
|
||||
|
||||
For more information and documentation, visit the wiki:
|
||||
https://github.com/ChuckBell/MySQL_Connector_Arduino/wiki.
|
||||
|
||||
INSTRUCTIONS FOR USE
|
||||
|
||||
1) Change the address of the server to the IP address of the MySQL server
|
||||
2) Change the user and password to a valid MySQL user and password
|
||||
3) Change the SSID and pass to match your WiFi network
|
||||
4) Connect a USB cable to your Arduino
|
||||
5) Select the correct board and port
|
||||
6) Compile and upload the sketch to your Arduino
|
||||
7) Once uploaded, open Serial Monitor (use 115200 speed) and observe
|
||||
|
||||
If you do not see messages indicating you have a connection, refer to the
|
||||
manual for troubleshooting tips. The most common issues are the server is
|
||||
not accessible from the network or the user name and password is incorrect.
|
||||
|
||||
Created by: Dr. Charles A. Bell
|
||||
*/
|
||||
#include <ESP8266WiFi.h> // Use this for WiFi instead of Ethernet.h
|
||||
#include <MySQL_Connection.h>
|
||||
#include <MySQL_Cursor.h>
|
||||
|
||||
IPAddress server_addr(10,0,1,35); // IP of the MySQL *server* here
|
||||
char user[] = "root"; // MySQL user login username
|
||||
char password[] = "secret"; // MySQL user login password
|
||||
|
||||
// Sample query
|
||||
char INSERT_SQL[] = "INSERT INTO test_arduino.hello_arduino (message) VALUES ('Hello, Arduino!')";
|
||||
|
||||
// WiFi card example
|
||||
char ssid[] = "your-ssid"; // your SSID
|
||||
char pass[] = "ssid-password"; // your SSID Password
|
||||
|
||||
WiFiClient client; // Use this for WiFi instead of EthernetClient
|
||||
MySQL_Connection conn(&client);
|
||||
MySQL_Cursor* cursor;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial); // wait for serial port to connect. Needed for Leonardo only
|
||||
|
||||
// Begin WiFi section
|
||||
Serial.printf("\nConnecting to %s", ssid);
|
||||
WiFi.begin(ssid, pass);
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
delay(500);
|
||||
Serial.print(".");
|
||||
}
|
||||
|
||||
// print out info about the connection:
|
||||
Serial.println("\nConnected to network");
|
||||
Serial.print("My IP address is: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
|
||||
Serial.print("Connecting to SQL... ");
|
||||
if (conn.connect(server_addr, 3306, user, password))
|
||||
Serial.println("OK.");
|
||||
else
|
||||
Serial.println("FAILED.");
|
||||
|
||||
// create MySQL cursor object
|
||||
cursor = new MySQL_Cursor(&conn);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
if (conn.connected())
|
||||
cursor->execute(INSERT_SQL);
|
||||
|
||||
delay(5000);
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
MySQL Connector/Arduino Example : basic select
|
||||
|
||||
This example demonstrates how to issue a SELECT query with no parameters
|
||||
and use the data returned. For this, we use the Cursor class to execute
|
||||
the query and get the results.
|
||||
|
||||
It demonstrates who methods for running queries. The first allows you to
|
||||
allocate memory for the cursor and later reclaim it, the second shows how
|
||||
to use a single instance of the cursor use throughout a sketch.
|
||||
|
||||
NOTICE: You must download and install the World sample database to run
|
||||
this sketch unaltered. See http://dev.mysql.com/doc/index-other.html.
|
||||
|
||||
CAUTION: Don't mix and match the examples. Use one or the other in your
|
||||
own sketch -- you'll get compilation errors at the least.
|
||||
|
||||
For more information and documentation, visit the wiki:
|
||||
https://github.com/ChuckBell/MySQL_Connector_Arduino/wiki.
|
||||
|
||||
INSTRUCTIONS FOR USE
|
||||
|
||||
1) Change the address of the server to the IP address of the MySQL server
|
||||
2) Change the user and password to a valid MySQL user and password
|
||||
3) Connect a USB cable to your Arduino
|
||||
4) Select the correct board and port
|
||||
5) Compile and upload the sketch to your Arduino
|
||||
6) Once uploaded, open Serial Monitor (use 115200 speed) and observe
|
||||
|
||||
Note: The MAC address can be anything so long as it is unique on your network.
|
||||
|
||||
Created by: Dr. Charles A. Bell
|
||||
*/
|
||||
#include <Ethernet.h>
|
||||
#include <MySQL_Connection.h>
|
||||
#include <MySQL_Cursor.h>
|
||||
|
||||
byte mac_addr[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
|
||||
|
||||
IPAddress server_addr(10,0,1,35); // IP of the MySQL *server* here
|
||||
char user[] = "root"; // MySQL user login username
|
||||
char password[] = "secret"; // MySQL user login password
|
||||
|
||||
// Sample query
|
||||
char query[] = "SELECT population FROM world.city WHERE name = 'New York'";
|
||||
|
||||
EthernetClient client;
|
||||
MySQL_Connection conn((Client *)&client);
|
||||
// Create an instance of the cursor passing in the connection
|
||||
MySQL_Cursor cur = MySQL_Cursor(&conn);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
while (!Serial); // wait for serial port to connect
|
||||
Ethernet.begin(mac_addr);
|
||||
Serial.println("Connecting...");
|
||||
if (conn.connect(server_addr, 3306, user, password)) {
|
||||
delay(1000);
|
||||
}
|
||||
else
|
||||
Serial.println("Connection failed.");
|
||||
}
|
||||
|
||||
|
||||
void loop() {
|
||||
row_values *row = NULL;
|
||||
long head_count = 0;
|
||||
|
||||
delay(1000);
|
||||
|
||||
Serial.println("1) Demonstrating using a cursor dynamically allocated.");
|
||||
// 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) {
|
||||
head_count = atol(row->values[0]);
|
||||
}
|
||||
} while (row != NULL);
|
||||
// Deleting the cursor also frees up memory used
|
||||
delete cur_mem;
|
||||
|
||||
// Show the result
|
||||
Serial.print(" NYC pop = ");
|
||||
Serial.println(head_count);
|
||||
|
||||
delay(500);
|
||||
|
||||
Serial.println("2) Demonstrating using a local, global cursor.");
|
||||
// Execute the query
|
||||
cur.execute(query);
|
||||
// Fetch the columns (required) but we don't use them.
|
||||
cur.get_columns();
|
||||
// Read the row (we are only expecting the one)
|
||||
do {
|
||||
row = cur.get_next_row();
|
||||
if (row != NULL) {
|
||||
head_count = atol(row->values[0]);
|
||||
}
|
||||
} while (row != NULL);
|
||||
// Now we close the cursor to free any memory
|
||||
cur.close();
|
||||
|
||||
// Show the result but this time do some math on it
|
||||
Serial.print(" NYC pop = ");
|
||||
Serial.println(head_count);
|
||||
Serial.print(" NYC pop increased by 12 = ");
|
||||
Serial.println(head_count+12);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
MySQL Connector/Arduino Example : complex insert
|
||||
|
||||
This example demonstrates how to issue an INSERT query to store data in a
|
||||
table using data from variables in our sketch. In this case, we supply the
|
||||
values dynamically.
|
||||
|
||||
This sketch simulates storing data from a sensor in a table.
|
||||
|
||||
For this, we will create a special database and table for testing.
|
||||
The following are the SQL commands you will need to run in order to setup
|
||||
your database for running this sketch.
|
||||
|
||||
CREATE DATABASE test_arduino;
|
||||
CREATE TABLE test_arduino.hello_sensor (
|
||||
num integer primary key auto_increment,
|
||||
message char(40),
|
||||
sensor_num integer,
|
||||
value float,
|
||||
recorded timestamp
|
||||
);
|
||||
|
||||
Here we have a table that contains an auto_increment primary key, a text
|
||||
field, a field to identify the sensor, the value read, and timestamp of
|
||||
the recorded data.
|
||||
|
||||
Note: Since this sketch uses test data, we place the INSERT in the setup()
|
||||
method so that it runs only once. Typically, you would have the
|
||||
INSERT in the loop() method after your code to read from the sensor.
|
||||
|
||||
For more information and documentation, visit the wiki:
|
||||
https://github.com/ChuckBell/MySQL_Connector_Arduino/wiki.
|
||||
|
||||
INSTRUCTIONS FOR USE
|
||||
|
||||
1) Create the database and table as shown above.
|
||||
2) Change the address of the server to the IP address of the MySQL server
|
||||
3) Change the user and password to a valid MySQL user and password
|
||||
4) Connect a USB cable to your Arduino
|
||||
5) Select the correct board and port
|
||||
6) Compile and upload the sketch to your Arduino
|
||||
7) Once uploaded, open Serial Monitor (use 115200 speed) and observe
|
||||
8) After the sketch has run for some time, open a mysql client and issue
|
||||
the command: "SELECT * FROM test_arduino.hello_sensor" to see the data
|
||||
recorded. Note the field values and how the database handles both the
|
||||
auto_increment and timestamp fields for us. You can clear the data with
|
||||
"DELETE FROM test_arduino.hello_sensor".
|
||||
|
||||
Note: The MAC address can be anything so long as it is unique on your network.
|
||||
|
||||
Created by: Dr. Charles A. Bell
|
||||
*/
|
||||
#include <Ethernet.h>
|
||||
#include <MySQL_Connection.h>
|
||||
#include <MySQL_Cursor.h>
|
||||
|
||||
byte mac_addr[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
|
||||
|
||||
IPAddress server_addr(10,0,1,35); // IP of the MySQL *server* here
|
||||
char user[] = "root"; // MySQL user login username
|
||||
char password[] = "secret"; // MySQL user login password
|
||||
|
||||
// Sample query
|
||||
char INSERT_DATA[] = "INSERT INTO test_arduino.hello_sensor (message, sensor_num, value) VALUES ('%s',%d,%s)";
|
||||
char query[128];
|
||||
char temperature[10];
|
||||
|
||||
EthernetClient client;
|
||||
MySQL_Connection conn((Client *)&client);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
while (!Serial); // wait for serial port to connect
|
||||
Ethernet.begin(mac_addr);
|
||||
Serial.println("Connecting...");
|
||||
if (conn.connect(server_addr, 3306, user, password)) {
|
||||
delay(1000);
|
||||
// Initiate the query class instance
|
||||
MySQL_Cursor *cur_mem = new MySQL_Cursor(&conn);
|
||||
// Save
|
||||
dtostrf(50.125, 1, 1, temperature);
|
||||
sprintf(query, INSERT_DATA, "test sensor", 24, temperature);
|
||||
// Execute the query
|
||||
cur_mem->execute(query);
|
||||
// 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;
|
||||
Serial.println("Data recorded.");
|
||||
}
|
||||
else
|
||||
Serial.println("Connection failed.");
|
||||
conn.close();
|
||||
}
|
||||
|
||||
|
||||
void loop() {
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
MySQL Connector/Arduino Example : complex select
|
||||
|
||||
This example demonstrates how to issue a SELECT query with parameters that
|
||||
we provide from code. Thus, it demonstrates how to build query parameters
|
||||
dynamically.
|
||||
|
||||
Notice also the sketch demonstrates how to read columns and rows from
|
||||
the result set. Study this example until you are familiar with how to
|
||||
do this before writing your own sketch to read and consume query results.
|
||||
|
||||
For more information and documentation, visit the wiki:
|
||||
https://github.com/ChuckBell/MySQL_Connector_Arduino/wiki.
|
||||
|
||||
NOTICE: You must download and install the World sample database to run
|
||||
this sketch unaltered. See http://dev.mysql.com/doc/index-other.html.
|
||||
|
||||
INSTRUCTIONS FOR USE
|
||||
|
||||
1) Change the address of the server to the IP address of the MySQL server
|
||||
2) Change the user and password to a valid MySQL user and password
|
||||
3) Connect a USB cable to your Arduino
|
||||
4) Select the correct board and port
|
||||
5) Compile and upload the sketch to your Arduino
|
||||
6) Once uploaded, open Serial Monitor (use 115200 speed) and observe
|
||||
|
||||
Note: The MAC address can be anything so long as it is unique on your network.
|
||||
|
||||
Created by: Dr. Charles A. Bell
|
||||
*/
|
||||
#include <Ethernet.h>
|
||||
#include <MySQL_Connection.h>
|
||||
#include <MySQL_Cursor.h>
|
||||
|
||||
byte mac_addr[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
|
||||
|
||||
IPAddress server_addr(10,0,1,35); // IP of the MySQL *server* here
|
||||
char user[] = "root"; // MySQL user login username
|
||||
char password[] = "secret"; // MySQL user login password
|
||||
|
||||
// Sample query
|
||||
//
|
||||
// Notice the "%lu" - that's a placeholder for the parameter we will
|
||||
// supply. See sprintf() documentation for more formatting specifier
|
||||
// options
|
||||
const char QUERY_POP[] = "SELECT name, population FROM world.city WHERE population > %lu ORDER BY population DESC;";
|
||||
char query[128];
|
||||
|
||||
EthernetClient client;
|
||||
MySQL_Connection conn((Client *)&client);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
while (!Serial); // wait for serial port to connect
|
||||
Ethernet.begin(mac_addr);
|
||||
Serial.println("Connecting...");
|
||||
if (conn.connect(server_addr, 3306, user, password)) {
|
||||
delay(1000);
|
||||
}
|
||||
else
|
||||
Serial.println("Connection failed.");
|
||||
}
|
||||
|
||||
|
||||
void loop() {
|
||||
delay(1000);
|
||||
|
||||
Serial.println("> Running SELECT with dynamically supplied parameter");
|
||||
|
||||
// Initiate the query class instance
|
||||
MySQL_Cursor *cur_mem = new MySQL_Cursor(&conn);
|
||||
// Supply the parameter for the query
|
||||
// Here we use the QUERY_POP as the format string and query as the
|
||||
// destination. This uses twice the memory so another option would be
|
||||
// to allocate one buffer for all formatted queries or allocate the
|
||||
// memory as needed (just make sure you allocate enough memory and
|
||||
// free it when you're done!).
|
||||
sprintf(query, QUERY_POP, 9000000);
|
||||
// Execute the query
|
||||
cur_mem->execute(query);
|
||||
// Fetch the columns and print them
|
||||
column_names *cols = cur_mem->get_columns();
|
||||
for (int f = 0; f < cols->num_fields; f++) {
|
||||
Serial.print(cols->fields[f]->name);
|
||||
if (f < cols->num_fields-1) {
|
||||
Serial.print(',');
|
||||
}
|
||||
}
|
||||
Serial.println();
|
||||
// Read the rows and print them
|
||||
row_values *row = NULL;
|
||||
do {
|
||||
row = cur_mem->get_next_row();
|
||||
if (row != NULL) {
|
||||
for (int f = 0; f < cols->num_fields; f++) {
|
||||
Serial.print(row->values[f]);
|
||||
if (f < cols->num_fields-1) {
|
||||
Serial.print(',');
|
||||
}
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
} while (row != NULL);
|
||||
// Deleting the cursor also frees up memory used
|
||||
delete cur_mem;
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
MySQL Connector/Arduino Example : connect
|
||||
|
||||
This example demonstrates how to connect to a MySQL server from an
|
||||
Arduino using an Arduino-compatible Ethernet shield. Note that "compatible"
|
||||
means it must conform to the Ethernet class library or be a derivative
|
||||
with the same classes and methods.
|
||||
|
||||
For more information and documentation, visit the wiki:
|
||||
https://github.com/ChuckBell/MySQL_Connector_Arduino/wiki.
|
||||
|
||||
INSTRUCTIONS FOR USE
|
||||
|
||||
1) Change the address of the server to the IP address of the MySQL server
|
||||
2) Change the user and password to a valid MySQL user and password
|
||||
3) Connect a USB cable to your Arduino
|
||||
4) Select the correct board and port
|
||||
5) Compile and upload the sketch to your Arduino
|
||||
6) Once uploaded, open Serial Monitor (use 115200 speed) and observe
|
||||
|
||||
If you do not see messages indicating you have a connection, refer to the
|
||||
manual for troubleshooting tips. The most common issues are the server is
|
||||
not accessible from the network or the user name and password is incorrect.
|
||||
|
||||
Note: The MAC address can be anything so long as it is unique on your network.
|
||||
|
||||
Created by: Dr. Charles A. Bell
|
||||
*/
|
||||
#include <Ethernet.h>
|
||||
#include <MySQL_Connection.h>
|
||||
|
||||
byte mac_addr[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
|
||||
|
||||
IPAddress server_addr(10,0,1,35); // IP of the MySQL *server* here
|
||||
char user[] = "root"; // MySQL user login username
|
||||
char password[] = "secret"; // MySQL user login password
|
||||
|
||||
EthernetClient client;
|
||||
MySQL_Connection conn((Client *)&client);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
while (!Serial); // wait for serial port to connect
|
||||
Ethernet.begin(mac_addr);
|
||||
Serial.println("Connecting...");
|
||||
if (conn.connect(server_addr, 3306, user, password)) {
|
||||
delay(1000);
|
||||
// You would add your code here to run a query once on startup.
|
||||
}
|
||||
else
|
||||
Serial.println("Connection failed.");
|
||||
conn.close();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
MySQL Connector/Arduino Example : connect by hostname
|
||||
|
||||
This example demonstrates how to connect to a MySQL server resolving the
|
||||
hostname for cases when you do not know the IP address of the server or
|
||||
it changes because it is in the cloud.
|
||||
|
||||
For more information and documentation, visit the wiki:
|
||||
https://github.com/ChuckBell/MySQL_Connector_Arduino/wiki.
|
||||
|
||||
INSTRUCTIONS FOR USE
|
||||
|
||||
1) Change the hostname variable to the hostname of the MySQL server
|
||||
2) Change the user and password to a valid MySQL user and password
|
||||
3) Connect a USB cable to your Arduino
|
||||
4) Select the correct board and port
|
||||
5) Compile and upload the sketch to your Arduino
|
||||
6) Once uploaded, open Serial Monitor (use 115200 speed) and observe
|
||||
|
||||
If you do not see messages indicating you have a connection, refer to the
|
||||
manual for troubleshooting tips. The most common issues are the server is
|
||||
not accessible from the network or the user name and password is incorrect.
|
||||
|
||||
Note: The MAC address can be anything so long as it is unique on your network.
|
||||
|
||||
Created by: Dr. Charles A. Bell
|
||||
*/
|
||||
#include <Ethernet.h>
|
||||
#include <MySQL_Connection.h>
|
||||
#include <Dns.h>
|
||||
|
||||
byte mac_addr[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
|
||||
|
||||
char hostname[] = "www.google.com"; // change to your server's hostname/URL
|
||||
char user[] = "root"; // MySQL user login username
|
||||
char password[] = "secret"; // MySQL user login password
|
||||
|
||||
IPAddress server_ip;
|
||||
EthernetClient client;
|
||||
MySQL_Connection conn((Client *)&client);
|
||||
DNSClient dns_client; // DNS instance
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
while (!Serial); // wait for serial port to connect
|
||||
Ethernet.begin(mac_addr);
|
||||
// Begin DNS lookup
|
||||
dns_client.begin(Ethernet.dnsServerIP());
|
||||
dns_client.getHostByName(hostname, server_ip);
|
||||
Serial.println(server_ip);
|
||||
// End DNS lookup
|
||||
Serial.println("Connecting...");
|
||||
if (conn.connect(server_ip, 3306, user, password)) {
|
||||
delay(1000);
|
||||
// You would add your code here to run a query once on startup.
|
||||
}
|
||||
else
|
||||
Serial.println("Connection failed.");
|
||||
conn.close();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
MySQL Connector/Arduino Example : connect with default database
|
||||
|
||||
This example demonstrates how to connect to a MySQL server and specifying
|
||||
the default database when connecting.
|
||||
|
||||
For more information and documentation, visit the wiki:
|
||||
https://github.com/ChuckBell/MySQL_Connector_Arduino/wiki.
|
||||
|
||||
INSTRUCTIONS FOR USE
|
||||
|
||||
1) Change the address of the server to the IP address of the MySQL server
|
||||
2) Change the user and password to a valid MySQL user and password
|
||||
3) Connect a USB cable to your Arduino
|
||||
4) Select the correct board and port
|
||||
5) Compile and upload the sketch to your Arduino
|
||||
6) Once uploaded, open Serial Monitor (use 115200 speed) and observe
|
||||
|
||||
If you do not see messages indicating you have a connection, refer to the
|
||||
manual for troubleshooting tips. The most common issues are the server is
|
||||
not accessible from the network or the user name and password is incorrect.
|
||||
|
||||
Note: The MAC address can be anything so long as it is unique on your network.
|
||||
|
||||
Created by: Dr. Charles A. Bell
|
||||
*/
|
||||
#include <Ethernet.h>
|
||||
#include <MySQL_Connection.h>
|
||||
|
||||
byte mac_addr[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
|
||||
|
||||
IPAddress server_addr(10,0,1,35); // IP of the MySQL *server* here
|
||||
char user[] = "root"; // MySQL user login username
|
||||
char password[] = "secret"; // MySQL user login password
|
||||
char default_db = "test_arduino;
|
||||
|
||||
EthernetClient client;
|
||||
MySQL_Connection conn((Client *)&client);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
while (!Serial); // wait for serial port to connect
|
||||
Ethernet.begin(mac_addr);
|
||||
Serial.println("Connecting...");
|
||||
if (conn.connect(server_addr, 3306, user, password, default_db)) {
|
||||
delay(1000);
|
||||
// You would add your code here to run a query once on startup.
|
||||
}
|
||||
else
|
||||
Serial.println("Connection failed.");
|
||||
conn.close();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
MySQL Connector/Arduino Example : connect and disconnect (close)
|
||||
|
||||
This example demonstrates how to use the connection to open at the start
|
||||
of a loop, perform some query, then close the connection. Use this technique
|
||||
for solutions that must sleep for a long period or otherwise require
|
||||
additional processing or delays. The connect/close pair allow you to
|
||||
control how long the connection is open and thus reduce the amount of
|
||||
time a connection is held open. It also helps for lossy connections.
|
||||
|
||||
This example demonstrates how to connect to a MySQL server and specifying
|
||||
the default database when connecting.
|
||||
|
||||
For more information and documentation, visit the wiki:
|
||||
https://github.com/ChuckBell/MySQL_Connector_Arduino/wiki.
|
||||
|
||||
INSTRUCTIONS FOR USE
|
||||
|
||||
1) Change the address of the server to the IP address of the MySQL server
|
||||
2) Change the user and password to a valid MySQL user and password
|
||||
3) Connect a USB cable to your Arduino
|
||||
4) Select the correct board and port
|
||||
5) Compile and upload the sketch to your Arduino
|
||||
6) Once uploaded, open Serial Monitor (use 115200 speed) and observe
|
||||
|
||||
Created by: Dr. Charles A. Bell
|
||||
*/
|
||||
#include <Ethernet.h>
|
||||
#include <MySQL_Connection.h>
|
||||
#include <MySQL_Cursor.h>
|
||||
|
||||
byte mac_addr[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
|
||||
|
||||
IPAddress server_addr(10,0,1,35); // IP of the MySQL *server* here
|
||||
char user[] = "root"; // MySQL user login username
|
||||
char password[] = "secret"; // MySQL user login password
|
||||
|
||||
EthernetClient client;
|
||||
MySQL_Connection conn((Client *)&client);
|
||||
MySQL_Cursor cur = MySQL_Cursor(&conn);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
while (!Serial); // wait for serial port to connect
|
||||
Ethernet.begin(mac_addr);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
Serial.println("Sleeping...");
|
||||
delay(2000);
|
||||
Serial.println("Connecting...");
|
||||
if (conn.connect(server_addr, 3306, user, password)) {
|
||||
delay(500);
|
||||
Serial.println("Running a query");
|
||||
cur.execute("SHOW DATABASES"); // execute a query
|
||||
cur.show_results(); // show the results
|
||||
cur.close(); // close the cursor
|
||||
conn.close(); // close the connection
|
||||
} else {
|
||||
Serial.println("Connect failed. Trying again on next iteration.");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
MySQL Connector/Arduino Example : connect by wifi
|
||||
|
||||
This example demonstrates how to connect to a MySQL server from an
|
||||
Arduino using an Arduino-compatible Wifi shield. Note that "compatible"
|
||||
means it must conform to the Ethernet class library or be a derivative
|
||||
with the same classes and methods.
|
||||
|
||||
For more information and documentation, visit the wiki:
|
||||
https://github.com/ChuckBell/MySQL_Connector_Arduino/wiki.
|
||||
|
||||
INSTRUCTIONS FOR USE
|
||||
|
||||
1) Change the address of the server to the IP address of the MySQL server
|
||||
2) Change the user and password to a valid MySQL user and password
|
||||
3) Change the SSID and pass to match your WiFi network
|
||||
4) Connect a USB cable to your Arduino
|
||||
5) Select the correct board and port
|
||||
6) Compile and upload the sketch to your Arduino
|
||||
7) Once uploaded, open Serial Monitor (use 115200 speed) and observe
|
||||
|
||||
If you do not see messages indicating you have a connection, refer to the
|
||||
manual for troubleshooting tips. The most common issues are the server is
|
||||
not accessible from the network or the user name and password is incorrect.
|
||||
|
||||
Note: The MAC address can be anything so long as it is unique on your network.
|
||||
|
||||
Created by: Dr. Charles A. Bell
|
||||
*/
|
||||
#include <WiFi.h> // Use this for WiFi instead of Ethernet.h
|
||||
#include <MySQL_Connection.h>
|
||||
#include <MySQL_Cursor.h>
|
||||
|
||||
byte mac_addr[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
|
||||
|
||||
IPAddress server_addr(10,0,1,35); // IP of the MySQL *server* here
|
||||
char user[] = "root"; // MySQL user login username
|
||||
char password[] = "secret"; // MySQL user login password
|
||||
|
||||
// WiFi card example
|
||||
char ssid[] = "horse_pen"; // your SSID
|
||||
char pass[] = "noname"; // your SSID Password
|
||||
|
||||
WiFiClient client; // Use this for WiFi instead of EthernetClient
|
||||
MySQL_Connection conn((Client *)&client);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
while (!Serial); // wait for serial port to connect. Needed for Leonardo only
|
||||
|
||||
// Begin WiFi section
|
||||
int status = WiFi.begin(ssid, pass);
|
||||
if ( status != WL_CONNECTED) {
|
||||
Serial.println("Couldn't get a wifi connection");
|
||||
while(true);
|
||||
}
|
||||
// print out info about the connection:
|
||||
else {
|
||||
Serial.println("Connected to network");
|
||||
IPAddress ip = WiFi.localIP();
|
||||
Serial.print("My IP address is: ");
|
||||
Serial.println(ip);
|
||||
}
|
||||
// End WiFi section
|
||||
|
||||
Serial.println("Connecting...");
|
||||
if (conn.connect(server_addr, 3306, user, password)) {
|
||||
delay(1000);
|
||||
}
|
||||
else
|
||||
Serial.println("Connection failed.");
|
||||
conn.close();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
MySQL Connector/Arduino Example : connect by wifi using WiFi 101 shield
|
||||
|
||||
This example demonstrates how to connect to a MySQL server from an
|
||||
Arduino using using the new WiFi Shield 101 from arduino.cc.
|
||||
|
||||
For more information and documentation, visit the wiki:
|
||||
https://github.com/ChuckBell/MySQL_Connector_Arduino/wiki.
|
||||
|
||||
INSTRUCTIONS FOR USE
|
||||
|
||||
1) Change the address of the server to the IP address of the MySQL server
|
||||
2) Change the user and password to a valid MySQL user and password
|
||||
3) Change the SSID and pass to match your WiFi network
|
||||
4) Connect a USB cable to your Arduino
|
||||
5) Select the correct board and port
|
||||
6) Compile and upload the sketch to your Arduino
|
||||
7) Once uploaded, open Serial Monitor (use 115200 speed) and observe
|
||||
|
||||
If you do not see messages indicating you have a connection, refer to the
|
||||
manual for troubleshooting tips. The most common issues are the server is
|
||||
not accessible from the network or the user name and password is incorrect.
|
||||
|
||||
Note: The MAC address can be anything so long as it is unique on your network.
|
||||
|
||||
Created by: Dr. Charles A. Bell
|
||||
*/
|
||||
#include <SPI.h>
|
||||
#include <WiFi101.h>
|
||||
#include <MySQL_Connection.h>
|
||||
#include <MySQL_Cursor.h>
|
||||
|
||||
byte mac_addr[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
|
||||
|
||||
IPAddress server_addr(10,0,1,35); // IP of the MySQL *server* here
|
||||
char user[] = "root"; // MySQL user login username
|
||||
char password[] = "secret"; // MySQL user login password
|
||||
|
||||
// WiFi card example
|
||||
char ssid[] = "horse_pen"; // your SSID
|
||||
char pass[] = "noname"; // your SSID Password
|
||||
|
||||
WiFiClient client;
|
||||
MySQL_Connection conn((Client *)&client);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
while (!Serial); // wait for serial port to connect
|
||||
|
||||
// Begin WiFi section
|
||||
int status = WiFi.begin(ssid, pass);
|
||||
if ( status != WL_CONNECTED) {
|
||||
Serial.println("Couldn't get a wifi connection");
|
||||
while(true);
|
||||
}
|
||||
// print out info about the connection:
|
||||
else {
|
||||
Serial.println("Connected to network");
|
||||
IPAddress ip = WiFi.localIP();
|
||||
Serial.print("My IP address is: ");
|
||||
Serial.println(ip);
|
||||
}
|
||||
// End WiFi section
|
||||
|
||||
Serial.println("Connecting...");
|
||||
if (conn.connect(server_addr, 3306, user, password)) {
|
||||
delay(1000);
|
||||
}
|
||||
else
|
||||
Serial.println("Connection failed.");
|
||||
conn.close();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
MySQL Connector/Arduino Example : query with PROGMEM strings
|
||||
|
||||
This example demonstrates how to issue queries using strings stored in
|
||||
PROGMEM. As you will see, you need only add a parameter to the execute()
|
||||
method in the cursor class, const and PROGMEM to the string declaration
|
||||
and add the #include <avr/pgmspace.h> directive.
|
||||
|
||||
For more information and documentation, visit the wiki:
|
||||
https://github.com/ChuckBell/MySQL_Connector_Arduino/wiki.
|
||||
|
||||
NOTICE: You must download and install the World sample database to run
|
||||
this sketch unaltered. See http://dev.mysql.com/doc/index-other.html.
|
||||
|
||||
INSTRUCTIONS FOR USE
|
||||
|
||||
1) Change the address of the server to the IP address of the MySQL server
|
||||
2) Change the user and password to a valid MySQL user and password
|
||||
3) Connect a USB cable to your Arduino
|
||||
4) Select the correct board and port
|
||||
5) Compile and upload the sketch to your Arduino
|
||||
6) Once uploaded, open Serial Monitor (use 115200 speed) and observe
|
||||
|
||||
Note: The MAC address can be anything so long as it is unique on your network.
|
||||
|
||||
Created by: Dr. Charles A. Bell
|
||||
*/
|
||||
#include <Ethernet.h>
|
||||
#include <MySQL_Connection.h>
|
||||
#include <MySQL_Cursor.h>
|
||||
#include <avr/pgmspace.h>
|
||||
|
||||
byte mac_addr[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
|
||||
|
||||
IPAddress server_addr(10,0,1,35); // IP of the MySQL *server* here
|
||||
char user[] = "root"; // MySQL user login username
|
||||
char password[] = "secret"; // MySQL user login password
|
||||
|
||||
// Sample query
|
||||
const char PROGMEM query[] = "SELECT * FROM world.city LIMIT 12";
|
||||
|
||||
EthernetClient client;
|
||||
MySQL_Connection conn((Client *)&client);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
while (!Serial); // wait for serial port to connect
|
||||
Ethernet.begin(mac_addr);
|
||||
Serial.println("Connecting...");
|
||||
if (conn.connect(server_addr, 3306, user, password)) {
|
||||
delay(1000);
|
||||
}
|
||||
else
|
||||
Serial.println("Connection failed.");
|
||||
}
|
||||
|
||||
|
||||
void loop() {
|
||||
delay(2000);
|
||||
|
||||
Serial.println("\nRunning SELECT from PROGMEM and printing results\n");
|
||||
|
||||
// Initiate the query class instance
|
||||
MySQL_Cursor *cur_mem = new MySQL_Cursor(&conn);
|
||||
// Execute the query with the PROGMEM option
|
||||
cur_mem->execute(query, true);
|
||||
// Show the results
|
||||
cur_mem->show_results();
|
||||
// Deleting the cursor also frees up memory used
|
||||
delete cur_mem;
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
MySQL Connector/Arduino Example : query results
|
||||
|
||||
This example demonstrates how to issue a SELECT query and how to read columns
|
||||
and rows from the result set. Study this example until you are familiar with how to
|
||||
do this before writing your own sketch to read and consume query results.
|
||||
|
||||
For more information and documentation, visit the wiki:
|
||||
https://github.com/ChuckBell/MySQL_Connector_Arduino/wiki.
|
||||
|
||||
NOTICE: You must download and install the World sample database to run
|
||||
this sketch unaltered. See http://dev.mysql.com/doc/index-other.html.
|
||||
|
||||
INSTRUCTIONS FOR USE
|
||||
|
||||
1) Change the address of the server to the IP address of the MySQL server
|
||||
2) Change the user and password to a valid MySQL user and password
|
||||
3) Connect a USB cable to your Arduino
|
||||
4) Select the correct board and port
|
||||
5) Compile and upload the sketch to your Arduino
|
||||
6) Once uploaded, open Serial Monitor (use 115200 speed) and observe
|
||||
|
||||
Note: The MAC address can be anything so long as it is unique on your network.
|
||||
|
||||
Created by: Dr. Charles A. Bell
|
||||
*/
|
||||
#include <Ethernet.h>
|
||||
#include <MySQL_Connection.h>
|
||||
#include <MySQL_Cursor.h>
|
||||
|
||||
byte mac_addr[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
|
||||
|
||||
IPAddress server_addr(10,0,1,35); // IP of the MySQL *server* here
|
||||
char user[] = "root"; // MySQL user login username
|
||||
char password[] = "secret"; // MySQL user login password
|
||||
|
||||
// Sample query
|
||||
char query[] = "SELECT * FROM world.city LIMIT 12";
|
||||
|
||||
EthernetClient client;
|
||||
MySQL_Connection conn((Client *)&client);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
while (!Serial); // wait for serial port to connect
|
||||
Ethernet.begin(mac_addr);
|
||||
Serial.println("Connecting...");
|
||||
if (conn.connect(server_addr, 3306, user, password)) {
|
||||
delay(1000);
|
||||
}
|
||||
else
|
||||
Serial.println("Connection failed.");
|
||||
}
|
||||
|
||||
|
||||
void loop() {
|
||||
delay(2000);
|
||||
|
||||
Serial.println("\nRunning SELECT and printing results\n");
|
||||
|
||||
// Initiate the query class instance
|
||||
MySQL_Cursor *cur_mem = new MySQL_Cursor(&conn);
|
||||
// Execute the query
|
||||
cur_mem->execute(query);
|
||||
// Fetch the columns and print them
|
||||
column_names *cols = cur_mem->get_columns();
|
||||
for (int f = 0; f < cols->num_fields; f++) {
|
||||
Serial.print(cols->fields[f]->name);
|
||||
if (f < cols->num_fields-1) {
|
||||
Serial.print(", ");
|
||||
}
|
||||
}
|
||||
Serial.println();
|
||||
// Read the rows and print them
|
||||
row_values *row = NULL;
|
||||
do {
|
||||
row = cur_mem->get_next_row();
|
||||
if (row != NULL) {
|
||||
for (int f = 0; f < cols->num_fields; f++) {
|
||||
Serial.print(row->values[f]);
|
||||
if (f < cols->num_fields-1) {
|
||||
Serial.print(", ");
|
||||
}
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
} while (row != NULL);
|
||||
// Deleting the cursor also frees up memory used
|
||||
delete cur_mem;
|
||||
}
|
||||
82
libraries/MySQL_Connector_Arduino/examples/reboot/reboot.ino
Normal file
82
libraries/MySQL_Connector_Arduino/examples/reboot/reboot.ino
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
MySQL Connector/Arduino Example : reboot if connection lost
|
||||
|
||||
This example demonstrates how to reboot an Arduino if connection to the
|
||||
server is lost for a period of time.
|
||||
|
||||
For more information and documentation, visit the wiki:
|
||||
https://github.com/ChuckBell/MySQL_Connector_Arduino/wiki.
|
||||
|
||||
INSTRUCTIONS FOR USE
|
||||
|
||||
1) Change the address of the server to the IP address of the MySQL server
|
||||
2) Change the user and password to a valid MySQL user and password
|
||||
3) Connect a USB cable to your Arduino
|
||||
4) Select the correct board and port
|
||||
5) Compile and upload the sketch to your Arduino
|
||||
6) Once uploaded, open Serial Monitor (use 115200 speed) and observe
|
||||
|
||||
To test the reboot, unplug your Ethernet cable once you see "disconnected"
|
||||
then wait for the timeout. Once the Arduino reboots, plug the cable in again
|
||||
and you should see the query processing resume.
|
||||
|
||||
Created by: Dr. Charles A. Bell
|
||||
*/
|
||||
#include <Ethernet.h>
|
||||
#include <MySQL_Connection.h>
|
||||
#include <MySQL_Cursor.h>
|
||||
|
||||
byte mac_addr[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
|
||||
|
||||
IPAddress server_addr(10,0,1,35); // IP of the MySQL *server* here
|
||||
char user[] = "root"; // MySQL user login username
|
||||
char password[] = "secret"; // MySQL user login password
|
||||
|
||||
EthernetClient client;
|
||||
MySQL_Connection conn((Client *)&client);
|
||||
MySQL_Cursor cur = MySQL_Cursor(&conn);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
while (!Serial); // wait for serial port to connect
|
||||
Ethernet.begin(mac_addr);
|
||||
}
|
||||
|
||||
// Begin reboot code
|
||||
int num_fails; // variable for number of failure attempts
|
||||
#define MAX_FAILED_CONNECTS 5 // maximum number of failed connects to MySQL
|
||||
|
||||
void soft_reset() {
|
||||
asm volatile("jmp 0");
|
||||
}
|
||||
// End reboot code
|
||||
|
||||
void loop() {
|
||||
Serial.println("Sleeping...");
|
||||
delay(1000);
|
||||
if (conn.connected()) {
|
||||
Serial.println("Running a query");
|
||||
cur.execute("SHOW DATABASES"); // execute a query
|
||||
cur.show_results(); // show the results
|
||||
cur.close(); // close the cursor
|
||||
conn.close(); // close the connection
|
||||
num_fails = 0; // reset failures
|
||||
delay(3000);
|
||||
} else {
|
||||
Serial.println("Connecting...");
|
||||
if (conn.connect(server_addr, 3306, user, password)) {
|
||||
delay(500);
|
||||
} else {
|
||||
num_fails++;
|
||||
Serial.println("Connect failed!");
|
||||
if (num_fails == MAX_FAILED_CONNECTS) {
|
||||
Serial.println("Ok, that's it. I'm outta here. Rebooting...");
|
||||
delay(2000);
|
||||
// Here we tell the Arduino to reboot by redirecting the instruction
|
||||
// pointer to the "top" or position 0. This is a soft reset and may
|
||||
// not solve all hardware-related lockups.
|
||||
soft_reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
The documentation for the connector has been moved to the wiki page on Github. For more information and documentation, visit the wiki:
|
||||
|
||||
https://github.com/ChuckBell/MySQL_Connector_Arduino/wiki.
|
||||
|
||||
5
libraries/MySQL_Connector_Arduino/keywords.txt
Normal file
5
libraries/MySQL_Connector_Arduino/keywords.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
connect KEYWORD2
|
||||
execute KEYWORD2
|
||||
show_results KEYWORD2
|
||||
connected KEYWORD2
|
||||
field_struct KEYWORD3
|
||||
9
libraries/MySQL_Connector_Arduino/library.properties
Normal file
9
libraries/MySQL_Connector_Arduino/library.properties
Normal file
@@ -0,0 +1,9 @@
|
||||
name=MySQL Connector Arduino
|
||||
version=1.2.0
|
||||
author=Dr. Charles Bell <chuck.bell@oracle.com>
|
||||
maintainer=Dr. Charles Bell <chuck.bell@oracle.com>
|
||||
sentence=Connects Arduino using Arduino Ethernet-compatible shields including the Ethernet Shield and WiFi Shield.
|
||||
paragraph=You can use this library to connect your Arduino project directly to a MySQL server without using an intermediate computer or a web- or cloud-based service. Having direct access to a database server means you can store data acquired from your project as well as check values stored in tables on the server. This also means you can setup your own, local MySQL server to store your data further removing the need for Internet connectivity. If that is not an issue, you can still connect to and store data on a MySQL server via your network, Internet, or even in the cloud!
|
||||
category=Communication
|
||||
url=https://github.com/ChuckBell/MySQL_Connector_Arduino/wiki
|
||||
architectures=*
|
||||
116
libraries/MySQL_Connector_Arduino/src/MySQL_Connection.cpp
Normal file
116
libraries/MySQL_Connector_Arduino/src/MySQL_Connection.cpp
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
Copyright (c) 2012, 2016 Oracle and/or its affiliates. All rights reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
MySQL_Connection.cpp - Library for communicating with a MySQL Server over
|
||||
Ethernet. (formerly mysql.cpp)
|
||||
|
||||
Change History:
|
||||
|
||||
Version 1.0.0a Created by Dr. Charles A. Bell, April 2012.
|
||||
Version 1.0.0b Updated by Dr. Charles A. Bell, October 2013.
|
||||
Version 1.0.1b Updated by Dr. Charles A. Bell, February 2014.
|
||||
Version 1.0.2b Updated by Dr. Charles A. Bell, April 2014.
|
||||
Version 1.0.3rc Updated by Dr. Charles A. Bell, March 2015.
|
||||
Version 1.0.4ga Updated by Dr. Charles A. Bell, July 2015.
|
||||
Version 1.1.0a Created by Dr. Charles A. Bell, January 2016.
|
||||
Version 1.1.1a Created by Dr. Charles A. Bell, January 2016.
|
||||
Version 1.1.2b Created by Dr. Charles A. Bell, November 2016.
|
||||
Version 1.2.0 Created by Dr. Charles A. Bell, March 2020.
|
||||
*/
|
||||
#include <Arduino.h>
|
||||
#include <MySQL_Connection.h>
|
||||
#include <MySQL_Encrypt_Sha1.h>
|
||||
|
||||
#define MAX_CONNECT_ATTEMPTS 3
|
||||
#define CONNECT_DELAY_MS 500
|
||||
#define SUCCESS 1
|
||||
|
||||
const char CONNECTED[] PROGMEM = "Connected to server version ";
|
||||
const char DISCONNECTED[] PROGMEM = "Disconnected.";
|
||||
|
||||
/*
|
||||
connect - Connect to a MySQL server.
|
||||
|
||||
This method is used to connect to a MySQL server. It will attempt to
|
||||
connect to the server as a client retrying up to MAX_CONNECT_ATTEMPTS.
|
||||
This permits the possibility of longer than normal network lag times
|
||||
for wireless networks. You can adjust MAX_CONNECT_ATTEMPTS to suit
|
||||
your environment.
|
||||
|
||||
server[in] IP address of the server as IPAddress type
|
||||
port[in] port number of the server
|
||||
user[in] user name
|
||||
password[in] (optional) user password
|
||||
db[in] (optional) default database
|
||||
|
||||
Returns boolean - True = connection succeeded
|
||||
*/
|
||||
boolean MySQL_Connection::connect(IPAddress server, int port, char *user,
|
||||
char *password, char *db)
|
||||
{
|
||||
int connected = 0;
|
||||
int retries = MAX_CONNECT_ATTEMPTS;
|
||||
|
||||
// Retry up to MAX_CONNECT_ATTEMPTS times.
|
||||
while (retries--)
|
||||
{
|
||||
Serial.println("...trying...");
|
||||
connected = client->connect(server, port);
|
||||
if (connected != SUCCESS) {
|
||||
Serial.print("...got: ");
|
||||
Serial.print(connected);
|
||||
Serial.println(" retrying...");
|
||||
delay(CONNECT_DELAY_MS);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (connected != SUCCESS)
|
||||
return false;
|
||||
|
||||
read_packet();
|
||||
parse_handshake_packet();
|
||||
send_authentication_packet(user, password, db);
|
||||
read_packet();
|
||||
if (get_packet_type() != MYSQL_OK_PACKET) {
|
||||
parse_error_packet();
|
||||
return false;
|
||||
}
|
||||
|
||||
show_error(CONNECTED);
|
||||
|
||||
Serial.println(server_version);
|
||||
|
||||
free(server_version); // don't need it anymore
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
close - cancel the connection
|
||||
|
||||
This method closes the connection to the server and frees up any memory
|
||||
used in the buffer.
|
||||
*/
|
||||
void MySQL_Connection::close()
|
||||
{
|
||||
if (connected())
|
||||
{
|
||||
client->flush();
|
||||
client->stop();
|
||||
show_error(DISCONNECTED, true);
|
||||
}
|
||||
}
|
||||
52
libraries/MySQL_Connector_Arduino/src/MySQL_Connection.h
Normal file
52
libraries/MySQL_Connector_Arduino/src/MySQL_Connection.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
Copyright (c) 2012, 2016 Oracle and/or its affiliates. All rights reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
MySQL_Connection.h - Library for communicating with a MySQL Server over
|
||||
Ethernet. (formerly mysql.h)
|
||||
|
||||
This header file defines a connection class for connecting to a MySQL
|
||||
server.
|
||||
|
||||
Change History:
|
||||
|
||||
Version 1.0.0a Created by Dr. Charles A. Bell, April 2012.
|
||||
Version 1.0.0b Updated by Dr. Charles A. Bell, October 2013.
|
||||
Version 1.0.1b Updated by Dr. Charles A. Bell, February 2014.
|
||||
Version 1.0.2b Updated by Dr. Charles A. Bell, April 2014.
|
||||
Version 1.0.3rc Updated by Dr. Charles A. Bell, March 2015.
|
||||
Version 1.0.4ga Updated by Dr. Charles A. Bell, July 2015.
|
||||
Version 1.1.0a Created by Dr. Charles A. Bell, January 2016.
|
||||
Version 1.1.1a Created by Dr. Charles A. Bell, January 2016.
|
||||
Version 1.1.2b Created by Dr. Charles A. Bell, November 2016.
|
||||
Version 1.2.0 Created by Dr. Charles A. Bell, March 2020.
|
||||
*/
|
||||
#ifndef MYSQL_CONNECTION_H
|
||||
#define MYSQL_CONNECTION_H
|
||||
|
||||
#include <MySQL_Packet.h>
|
||||
|
||||
class MySQL_Connection : public MySQL_Packet {
|
||||
public:
|
||||
MySQL_Connection(Client *client_instance) :
|
||||
MySQL_Packet(client_instance) {}
|
||||
boolean connect(IPAddress server, int port, char *user, char *password,
|
||||
char *db=NULL);
|
||||
int connected() { return client->connected(); }
|
||||
const char *version() { return MYSQL_VERSION_STR; }
|
||||
void close();
|
||||
};
|
||||
|
||||
#endif
|
||||
542
libraries/MySQL_Connector_Arduino/src/MySQL_Cursor.cpp
Normal file
542
libraries/MySQL_Connector_Arduino/src/MySQL_Cursor.cpp
Normal file
@@ -0,0 +1,542 @@
|
||||
/*
|
||||
Copyright (c) 2012, 2016 Oracle and/or its affiliates. All rights reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
MySQL_Cursor.cpp - Run queries on a MySQL Server
|
||||
|
||||
Change History:
|
||||
|
||||
Version 1.0.0a Created by Dr. Charles A. Bell, April 2012.
|
||||
Version 1.0.0b Updated by Dr. Charles A. Bell, October 2013.
|
||||
Version 1.0.1b Updated by Dr. Charles A. Bell, February 2014.
|
||||
Version 1.0.2b Updated by Dr. Charles A. Bell, April 2014.
|
||||
Version 1.0.3rc Updated by Dr. Charles A. Bell, March 2015.
|
||||
Version 1.0.4ga Updated by Dr. Charles A. Bell, July 2015.
|
||||
Version 1.1.0a Created by Dr. Charles A. Bell, January 2016.
|
||||
Version 1.1.1a Created by Dr. Charles A. Bell, January 2016.
|
||||
Version 1.1.2b Created by Dr. Charles A. Bell, November 2016.
|
||||
Version 1.2.0 Created by Dr. Charles A. Bell, March 2020.
|
||||
*/
|
||||
#include <MySQL_Cursor.h>
|
||||
|
||||
const char BAD_MOJO[] PROGMEM = "Bad mojo. EOF found reading column header.";
|
||||
const char ROWS[] PROGMEM = " rows in result.";
|
||||
const char READ_COLS[] PROGMEM = "ERROR: You must read the columns first!";
|
||||
const char NOT_CONNECTED[] PROGMEM = "ERROR: Class requires connected server.";
|
||||
|
||||
/*
|
||||
Constructor
|
||||
|
||||
Requires an instance of the MySQL_Connection class to communicate with a
|
||||
MySQL server.
|
||||
|
||||
connection[in] Connection to a MySQL server - must be connected.
|
||||
*/
|
||||
MySQL_Cursor::MySQL_Cursor(MySQL_Connection *connection) {
|
||||
conn = connection;
|
||||
#ifdef WITH_SELECT
|
||||
columns.num_fields = 0;
|
||||
for (int f = 0; f < MAX_FIELDS; f++) {
|
||||
columns.fields[f] = NULL;
|
||||
row.values[f] = NULL;
|
||||
}
|
||||
columns_read = false;
|
||||
rows_affected = -1;
|
||||
last_insert_id = -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Destructor
|
||||
*/
|
||||
MySQL_Cursor::~MySQL_Cursor() {
|
||||
#ifdef WITH_SELECT
|
||||
close();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
execute - Execute a SQL statement
|
||||
|
||||
This method executes the query specified as a character array. It copies
|
||||
the query to the local buffer then calls the execute_query() method to
|
||||
execute the query.
|
||||
|
||||
If a result set is available after the query executes, the field
|
||||
packets and rows can be read separately using the get_field() and
|
||||
get_row() methods.
|
||||
|
||||
query[in] SQL statement (using normal memory access)
|
||||
progmem[in] True if string is in program memory
|
||||
|
||||
Returns boolean - True = a result set is available for reading
|
||||
*/
|
||||
boolean MySQL_Cursor::execute(const char *query, boolean progmem)
|
||||
{
|
||||
int query_len; // length of query
|
||||
|
||||
if (!conn->connected()) {
|
||||
conn->show_error(NOT_CONNECTED, true);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (progmem) {
|
||||
query_len = (int)strlen_P(query);
|
||||
} else {
|
||||
query_len = (int)strlen(query);
|
||||
}
|
||||
if (conn->buffer != NULL)
|
||||
free(conn->buffer);
|
||||
|
||||
conn->buffer = (byte *)malloc(query_len+5);
|
||||
|
||||
// Write query to packet
|
||||
if (progmem) {
|
||||
for (int c = 0; c < query_len; c++)
|
||||
conn->buffer[c+5] = pgm_read_byte_near(query+c);
|
||||
} else {
|
||||
memcpy(&conn->buffer[5], query, query_len);
|
||||
}
|
||||
|
||||
// Send the query
|
||||
return execute_query(query_len);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
execute_query - execute a query
|
||||
|
||||
This method sends the query string to the server and waits for a
|
||||
response. If the result is a result set, it returns true, if it is
|
||||
an error, it processes the error packet and prints the error via
|
||||
Serial.print(). If it is an Ok packet, it parses the packet and
|
||||
returns false.
|
||||
|
||||
query_len[in] Number of bytes in the query string
|
||||
|
||||
Returns boolean - true = result set available,
|
||||
false = no result set returned.
|
||||
*/
|
||||
boolean MySQL_Cursor::execute_query(int query_len)
|
||||
{
|
||||
if (!conn->buffer)
|
||||
return false;
|
||||
|
||||
// Reset the rows affected and last insert id before query.
|
||||
rows_affected = -1;
|
||||
last_insert_id = -1;
|
||||
|
||||
conn->store_int(&conn->buffer[0], query_len+1, 3);
|
||||
conn->buffer[3] = byte(0x00);
|
||||
conn->buffer[4] = byte(0x03); // command packet
|
||||
|
||||
// Send the query
|
||||
conn->client->write((uint8_t*)conn->buffer, query_len + 5);
|
||||
conn->client->flush();
|
||||
|
||||
// Read a response packet and check it for Ok or Error.
|
||||
conn->read_packet();
|
||||
int res = conn->get_packet_type();
|
||||
if (res == MYSQL_ERROR_PACKET) {
|
||||
conn->parse_error_packet();
|
||||
return false;
|
||||
} else if (res == MYSQL_OK_PACKET || res == MYSQL_EOF_PACKET) {
|
||||
// Read the rows affected and last insert id.
|
||||
int loc1 = conn->buffer[5]; // Location of rows affected
|
||||
int loc2 = 5;
|
||||
if (loc1 < 252) {
|
||||
loc2++;
|
||||
} else if (loc1 == 252) {
|
||||
loc2 += 2;
|
||||
} else if (loc1 == 253) {
|
||||
loc2 += 3;
|
||||
} else {
|
||||
loc2 += 8;
|
||||
}
|
||||
rows_affected = conn->read_lcb_int(5);
|
||||
if (rows_affected > 0) {
|
||||
last_insert_id = conn->read_lcb_int(loc2);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Not an Ok packet, so we now have the result set to process.
|
||||
#ifdef WITH_SELECT
|
||||
columns_read = false;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#ifdef WITH_SELECT
|
||||
/*
|
||||
Close
|
||||
|
||||
Takes care of removing allocated memory.
|
||||
*/
|
||||
void MySQL_Cursor::close() {
|
||||
free_columns_buffer();
|
||||
free_row_buffer();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
get_columns - Get a list of the columns (fields)
|
||||
|
||||
This method returns an instance of the column_names structure
|
||||
that contains an array of fields.
|
||||
|
||||
Note: you should call free_columns_buffer() after consuming
|
||||
the field data to free memory.
|
||||
*/
|
||||
column_names *MySQL_Cursor::get_columns() {
|
||||
free_columns_buffer();
|
||||
free_row_buffer();
|
||||
num_cols = 0;
|
||||
if (get_fields()) {
|
||||
columns_read = true;
|
||||
return &columns;
|
||||
}
|
||||
else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
get_next_row - Iterator for reading rows from a result set
|
||||
|
||||
This method returns an instance of a structure (row_values)
|
||||
that contains an array of strings representing the row
|
||||
values returned from the server.
|
||||
|
||||
The caller can use the values however needed - by first
|
||||
converting them to a specific type or as a string.
|
||||
*/
|
||||
row_values *MySQL_Cursor::get_next_row() {
|
||||
int res = 0;
|
||||
|
||||
free_row_buffer();
|
||||
|
||||
// Read the rows
|
||||
res = get_row_values();
|
||||
if (res != MYSQL_EOF_PACKET) {
|
||||
return &row;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
show_results - Show a result set from the server via Serial.print
|
||||
|
||||
This method reads a result from the server and displays it via the
|
||||
via the Serial.print methods. It can be used in cases where
|
||||
you may want to issue a SELECT or SHOW and see the results on your
|
||||
computer from the Arduino.
|
||||
|
||||
It is also a good example of how to read a result set from the
|
||||
because it uses the public methods designed to return result
|
||||
sets from the server.
|
||||
*/
|
||||
void MySQL_Cursor::show_results() {
|
||||
column_names *cols;
|
||||
int rows = 0;
|
||||
|
||||
// Get the columns
|
||||
cols = get_columns();
|
||||
if (cols == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int f = 0; f < columns.num_fields; f++) {
|
||||
Serial.print(columns.fields[f]->name);
|
||||
if (f < columns.num_fields-1)
|
||||
Serial.print(',');
|
||||
}
|
||||
Serial.println();
|
||||
|
||||
// Read the rows
|
||||
while (get_next_row()) {
|
||||
rows++;
|
||||
for (int f = 0; f < columns.num_fields; f++) {
|
||||
Serial.print(row.values[f]);
|
||||
if (f < columns.num_fields-1)
|
||||
Serial.print(',');
|
||||
}
|
||||
free_row_buffer();
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
// Report how many rows were read
|
||||
Serial.print(rows);
|
||||
conn->show_error(ROWS, true);
|
||||
free_columns_buffer();
|
||||
|
||||
// Free any post-query messages in queue for stored procedures
|
||||
clear_ok_packet();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
clear_ok_packet - clear last Ok packet (if present)
|
||||
|
||||
This method reads the header and status to see if this is an Ok packet.
|
||||
If it is, it reads the packet and discards it. This is useful for
|
||||
processing result sets from stored procedures.
|
||||
|
||||
Returns False if the packet was not an Ok packet.
|
||||
*/
|
||||
bool MySQL_Cursor::clear_ok_packet() {
|
||||
int num = 0;
|
||||
|
||||
do {
|
||||
num = conn->client->available();
|
||||
if (num > 0) {
|
||||
conn->read_packet();
|
||||
if (conn->get_packet_type() != MYSQL_OK_PACKET) {
|
||||
conn->parse_error_packet();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} while (num > 0);
|
||||
rows_affected = -1;
|
||||
last_insert_id = -1;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
free_columns_buffer - Free memory allocated for column names
|
||||
|
||||
This method frees the memory allocated during the get_columns()
|
||||
method.
|
||||
|
||||
NOTICE: Failing to call this method after calling get_columns()
|
||||
and consuming the column names, types, etc. will result
|
||||
in a memory leak. The size of the leak will depend on
|
||||
the size of the combined column names (bytes).
|
||||
*/
|
||||
void MySQL_Cursor::free_columns_buffer() {
|
||||
// clear the columns
|
||||
for (int f = 0; f < MAX_FIELDS; f++) {
|
||||
if (columns.fields[f] != NULL) {
|
||||
free(columns.fields[f]->db);
|
||||
free(columns.fields[f]->table);
|
||||
free(columns.fields[f]->name);
|
||||
free(columns.fields[f]);
|
||||
}
|
||||
columns.fields[f] = NULL;
|
||||
}
|
||||
num_cols = 0;
|
||||
columns_read = false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
free_row_buffer - Free memory allocated for row values
|
||||
|
||||
This method frees the memory allocated during the get_next_row()
|
||||
method.
|
||||
|
||||
NOTICE: You must call this method at least once after you
|
||||
have consumed the values you wish to process. Failing
|
||||
to do will result in a memory leak equal to the sum
|
||||
of the length of values and one byte for each max cols.
|
||||
*/
|
||||
void MySQL_Cursor::free_row_buffer() {
|
||||
// clear the row
|
||||
for (int f = 0; f < MAX_FIELDS; f++) {
|
||||
if (row.values[f] != NULL) {
|
||||
free(row.values[f]);
|
||||
}
|
||||
row.values[f] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
read_string - Retrieve a string from the buffer
|
||||
|
||||
This reads a string from the buffer. It reads the length of the string
|
||||
as the first byte.
|
||||
|
||||
offset[in] offset from start of buffer
|
||||
|
||||
Returns string - String from the buffer
|
||||
*/
|
||||
char *MySQL_Cursor::read_string(int *offset) {
|
||||
char *str;
|
||||
int len_bytes = conn->get_lcb_len(conn->buffer[*offset]);
|
||||
int len = conn->read_int(*offset, len_bytes);
|
||||
if (len == 251) {
|
||||
// This is a null field.
|
||||
str = (char *)malloc(5);
|
||||
strncpy(str, "NULL", 4);
|
||||
str[4] = 0x00;
|
||||
*offset += len_bytes;
|
||||
} else {
|
||||
str = (char *)malloc(len+1);
|
||||
strncpy(str, (char *)&conn->buffer[*offset+len_bytes], len);
|
||||
str[len] = 0x00;
|
||||
*offset += len_bytes+len;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
get_field - Read a field from the server
|
||||
|
||||
This method reads a field packet from the server. Field packets are
|
||||
defined as:
|
||||
|
||||
Bytes Name
|
||||
----- ----
|
||||
n (Length Coded String) catalog
|
||||
n (Length Coded String) db
|
||||
n (Length Coded String) table
|
||||
n (Length Coded String) org_table
|
||||
n (Length Coded String) name
|
||||
n (Length Coded String) org_name
|
||||
1 (filler)
|
||||
2 charsetnr
|
||||
4 length
|
||||
1 type
|
||||
2 flags
|
||||
1 decimals
|
||||
2 (filler), always 0x00
|
||||
n (Length Coded Binary) default
|
||||
|
||||
Note: the sum of all db, column, and field names must be < 255 in length
|
||||
*/
|
||||
int MySQL_Cursor::get_field(field_struct *fs) {
|
||||
int len_bytes;
|
||||
int len;
|
||||
int offset;
|
||||
|
||||
// Read field packets until EOF
|
||||
conn->read_packet();
|
||||
if (conn->buffer && conn->buffer[4] != MYSQL_EOF_PACKET) {
|
||||
// calculate location of db
|
||||
len_bytes = conn->get_lcb_len(4);
|
||||
len = conn->read_int(4, len_bytes);
|
||||
offset = 4+len_bytes+len;
|
||||
fs->db = read_string(&offset);
|
||||
// get table
|
||||
fs->table = read_string(&offset);
|
||||
// calculate location of name
|
||||
len_bytes = conn->get_lcb_len(offset);
|
||||
len = conn->read_int(offset, len_bytes);
|
||||
offset += len_bytes+len;
|
||||
fs->name = read_string(&offset);
|
||||
return 0;
|
||||
}
|
||||
return MYSQL_EOF_PACKET;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
get_row - Read a row from the server and store it in the buffer
|
||||
|
||||
This reads a single row and stores it in the buffer. If there are
|
||||
no more rows, it returns MYSQL_EOF_PACKET. A row packet is defined as
|
||||
follows.
|
||||
|
||||
Bytes Name
|
||||
----- ----
|
||||
n (Length Coded String) (column value)
|
||||
...
|
||||
|
||||
Note: each column is store as a length coded string concatenated
|
||||
as a single stream
|
||||
|
||||
Returns integer - MYSQL_EOF_PACKET if no more rows, 0 if more rows available
|
||||
*/
|
||||
int MySQL_Cursor::get_row() {
|
||||
// Read row packets
|
||||
conn->read_packet();
|
||||
if (conn->buffer && conn->buffer[4] != MYSQL_EOF_PACKET)
|
||||
return 0;
|
||||
return MYSQL_EOF_PACKET;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
get_fields - reads the fields from the read buffer
|
||||
|
||||
This method is used to read the field names, types, etc.
|
||||
from the read buffer and store them in the columns structure
|
||||
in the class.
|
||||
*/
|
||||
boolean MySQL_Cursor::get_fields()
|
||||
{
|
||||
int num_fields = 0;
|
||||
int res = 0;
|
||||
|
||||
if (conn->buffer == NULL) {
|
||||
return false;
|
||||
}
|
||||
num_fields = conn->buffer[4]; // From result header packet
|
||||
columns.num_fields = num_fields;
|
||||
num_cols = num_fields; // Save this for later use
|
||||
for (int f = 0; f < num_fields; f++) {
|
||||
field_struct *field = (field_struct *)malloc(sizeof(field_struct));
|
||||
res = get_field(field);
|
||||
if (res == MYSQL_EOF_PACKET) {
|
||||
conn->show_error(BAD_MOJO, true);
|
||||
return false;
|
||||
}
|
||||
columns.fields[f] = field;
|
||||
}
|
||||
conn->read_packet(); // EOF packet
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
get_row_values - reads the row values from the read buffer
|
||||
|
||||
This method is used to read the row column values
|
||||
from the read buffer and store them in the row structure
|
||||
in the class.
|
||||
*/
|
||||
int MySQL_Cursor::get_row_values() {
|
||||
int res = 0;
|
||||
int offset = 0;
|
||||
|
||||
// It is an error to try to read rows before columns
|
||||
// are read.
|
||||
if (!columns_read) {
|
||||
conn->show_error(READ_COLS, true);
|
||||
return MYSQL_EOF_PACKET;
|
||||
}
|
||||
// Drop any row data already read
|
||||
free_row_buffer();
|
||||
|
||||
// Read a row
|
||||
res = get_row();
|
||||
if (res != MYSQL_EOF_PACKET) {
|
||||
offset = 4;
|
||||
for (int f = 0; f < num_cols; f++) {
|
||||
row.values[f] = read_string(&offset);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif // WITH_SELECT
|
||||
106
libraries/MySQL_Connector_Arduino/src/MySQL_Cursor.h
Normal file
106
libraries/MySQL_Connector_Arduino/src/MySQL_Cursor.h
Normal file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
Copyright (c) 2012, 2016 Oracle and/or its affiliates. All rights reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
MySQL_Cursor.h - Run queries on a MySQL Server
|
||||
|
||||
This header file defines a cursor class for running queries on a MySQL
|
||||
server. You can issue any command using SQL statements for inserting or
|
||||
retrieving data.
|
||||
|
||||
Change History:
|
||||
|
||||
Version 1.0.0a Created by Dr. Charles A. Bell, April 2012.
|
||||
Version 1.0.0b Updated by Dr. Charles A. Bell, October 2013.
|
||||
Version 1.0.1b Updated by Dr. Charles A. Bell, February 2014.
|
||||
Version 1.0.2b Updated by Dr. Charles A. Bell, April 2014.
|
||||
Version 1.0.3rc Updated by Dr. Charles A. Bell, March 2015.
|
||||
Version 1.0.4ga Updated by Dr. Charles A. Bell, July 2015.
|
||||
Version 1.1.0a Created by Dr. Charles A. Bell, January 2016.
|
||||
Version 1.1.1a Created by Dr. Charles A. Bell, January 2016.
|
||||
Version 1.1.2b Created by Dr. Charles A. Bell, November 2016.
|
||||
Version 1.2.0 Created by Dr. Charles A. Bell, March 2020.
|
||||
*/
|
||||
#ifndef MYSQL_QUERY_H
|
||||
#define MYSQL_QUERY_H
|
||||
|
||||
#include <MySQL_Connection.h>
|
||||
|
||||
#define WITH_SELECT // Comment this if you don't need SELECT queries.
|
||||
// Reduces memory footprint of the library.
|
||||
#define MAX_FIELDS 0x20 // Maximum number of fields. Reduce to save memory. Default=32
|
||||
|
||||
#ifdef WITH_SELECT
|
||||
// Structure for retrieving a field (minimal implementation).
|
||||
typedef struct {
|
||||
char *db;
|
||||
char *table;
|
||||
char *name;
|
||||
} field_struct;
|
||||
|
||||
// Structure for storing result set metadata.
|
||||
typedef struct {
|
||||
int num_fields; // actual number of fields
|
||||
field_struct *fields[MAX_FIELDS];
|
||||
} column_names;
|
||||
|
||||
// Structure for storing row data.
|
||||
typedef struct {
|
||||
char *values[MAX_FIELDS];
|
||||
} row_values;
|
||||
#endif // WITH_SELECT
|
||||
|
||||
class MySQL_Cursor {
|
||||
public:
|
||||
MySQL_Cursor(MySQL_Connection *connection);
|
||||
~MySQL_Cursor();
|
||||
boolean execute(const char *query, boolean progmem=false);
|
||||
|
||||
private:
|
||||
boolean execute_query(int query_len);
|
||||
|
||||
#ifdef WITH_SELECT
|
||||
public:
|
||||
void close();
|
||||
column_names *get_columns();
|
||||
row_values *get_next_row();
|
||||
void show_results();
|
||||
int get_rows_affected() { return rows_affected; }
|
||||
int get_last_insert_id() { return last_insert_id; }
|
||||
|
||||
private:
|
||||
void free_columns_buffer();
|
||||
void free_row_buffer();
|
||||
bool clear_ok_packet();
|
||||
|
||||
char *read_string(int *offset);
|
||||
int get_field(field_struct *fs);
|
||||
int get_row();
|
||||
boolean get_fields();
|
||||
int get_row_values();
|
||||
column_names *query_result();
|
||||
|
||||
boolean columns_read;
|
||||
int num_cols;
|
||||
column_names columns;
|
||||
row_values row;
|
||||
int rows_affected;
|
||||
int last_insert_id;
|
||||
#endif
|
||||
|
||||
MySQL_Connection *conn;
|
||||
};
|
||||
|
||||
#endif
|
||||
141
libraries/MySQL_Connector_Arduino/src/MySQL_Encrypt_Sha1.cpp
Normal file
141
libraries/MySQL_Connector_Arduino/src/MySQL_Encrypt_Sha1.cpp
Normal file
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* GNU GPL v3
|
||||
*
|
||||
* This file is part of the code entitled, "cryptosuite" available at
|
||||
* https://code.google.com/p/cryptosuite/. The file was copied from that
|
||||
* repository and renamed for use in Connector/Arduino to preserve
|
||||
* compatibility and protect against namespace collisions for users who
|
||||
* want to use the full cryptosuite functionality. For Connector/Arduino
|
||||
* all that is needed is this one sha1 class.
|
||||
*
|
||||
* Note: #defines renamed to prevent collisions
|
||||
*/
|
||||
#include <string.h>
|
||||
#include "MySQL_Encrypt_Sha1.h"
|
||||
|
||||
#define MYSQL_SHA1_K0 0x5a827999
|
||||
#define MYSQL_SHA1_K20 0x6ed9eba1
|
||||
#define MYSQL_SHA1_K40 0x8f1bbcdc
|
||||
#define MYSQL_SHA1_K60 0xca62c1d6
|
||||
|
||||
const uint8_t sha1InitState[] PROGMEM = {
|
||||
0x01,0x23,0x45,0x67, // H0
|
||||
0x89,0xab,0xcd,0xef, // H1
|
||||
0xfe,0xdc,0xba,0x98, // H2
|
||||
0x76,0x54,0x32,0x10, // H3
|
||||
0xf0,0xe1,0xd2,0xc3 // H4
|
||||
};
|
||||
|
||||
void Encrypt_SHA1::init(void) {
|
||||
memcpy_P(state.b,sha1InitState,HASH_LENGTH);
|
||||
byteCount = 0;
|
||||
bufferOffset = 0;
|
||||
}
|
||||
|
||||
uint32_t Encrypt_SHA1::rol32(uint32_t number, uint8_t bits) {
|
||||
return ((number << bits) | (number >> (32-bits)));
|
||||
}
|
||||
|
||||
void Encrypt_SHA1::hashBlock() {
|
||||
// SHA1 only for now
|
||||
uint8_t i;
|
||||
uint32_t a,b,c,d,e,t;
|
||||
|
||||
a=state.w[0];
|
||||
b=state.w[1];
|
||||
c=state.w[2];
|
||||
d=state.w[3];
|
||||
e=state.w[4];
|
||||
for (i=0; i<80; i++) {
|
||||
if (i>=16) {
|
||||
t = buffer.w[(i+13)&15] ^ buffer.w[(i+8)&15] ^ buffer.w[(i+2)&15] ^ buffer.w[i&15];
|
||||
buffer.w[i&15] = rol32(t,1);
|
||||
}
|
||||
if (i<20) {
|
||||
t = (d ^ (b & (c ^ d))) + MYSQL_SHA1_K0;
|
||||
} else if (i<40) {
|
||||
t = (b ^ c ^ d) + MYSQL_SHA1_K20;
|
||||
} else if (i<60) {
|
||||
t = ((b & c) | (d & (b | c))) + MYSQL_SHA1_K40;
|
||||
} else {
|
||||
t = (b ^ c ^ d) + MYSQL_SHA1_K60;
|
||||
}
|
||||
t+=rol32(a,5) + e + buffer.w[i&15];
|
||||
e=d;
|
||||
d=c;
|
||||
c=rol32(b,30);
|
||||
b=a;
|
||||
a=t;
|
||||
}
|
||||
state.w[0] += a;
|
||||
state.w[1] += b;
|
||||
state.w[2] += c;
|
||||
state.w[3] += d;
|
||||
state.w[4] += e;
|
||||
}
|
||||
|
||||
void Encrypt_SHA1::addUncounted(uint8_t data) {
|
||||
buffer.b[bufferOffset ^ 3] = data;
|
||||
bufferOffset++;
|
||||
if (bufferOffset == BLOCK_LENGTH) {
|
||||
hashBlock();
|
||||
bufferOffset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
size_t Encrypt_SHA1::write(uint8_t data) {
|
||||
++byteCount;
|
||||
addUncounted(data);
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t Encrypt_SHA1::write(uint8_t* data, int length) {
|
||||
for (int i=0; i<length; i++) {
|
||||
write(data[i]);
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
void Encrypt_SHA1::pad() {
|
||||
// Implement SHA-1 padding (fips180-2 §5.1.1)
|
||||
|
||||
// Pad with 0x80 followed by 0x00 until the end of the block
|
||||
addUncounted(0x80);
|
||||
while (bufferOffset != 56) addUncounted(0x00);
|
||||
|
||||
// Append length in the last 8 bytes
|
||||
addUncounted(0); // We're only using 32 bit lengths
|
||||
addUncounted(0); // But SHA-1 supports 64 bit lengths
|
||||
addUncounted(0); // So zero pad the top bits
|
||||
addUncounted(byteCount >> 29); // Shifting to multiply by 8
|
||||
addUncounted(byteCount >> 21); // as SHA-1 supports bitstreams as well as
|
||||
addUncounted(byteCount >> 13); // byte.
|
||||
addUncounted(byteCount >> 5);
|
||||
addUncounted(byteCount << 3);
|
||||
}
|
||||
|
||||
|
||||
uint8_t* Encrypt_SHA1::result(void) {
|
||||
// Pad to complete the last block
|
||||
pad();
|
||||
|
||||
// Swap byte order back
|
||||
for (int i=0; i<5; i++) {
|
||||
uint32_t a,b;
|
||||
a=state.w[i];
|
||||
b=a<<24;
|
||||
b|=(a<<8) & 0x00ff0000;
|
||||
b|=(a>>8) & 0x0000ff00;
|
||||
b|=a>>24;
|
||||
state.w[i]=b;
|
||||
}
|
||||
|
||||
// Return pointer to hash (20 characters)
|
||||
return state.b;
|
||||
}
|
||||
|
||||
|
||||
#define HMAC_IPAD 0x36
|
||||
#define HMAC_OPAD 0x5c
|
||||
|
||||
Encrypt_SHA1 Sha1;
|
||||
54
libraries/MySQL_Connector_Arduino/src/MySQL_Encrypt_Sha1.h
Normal file
54
libraries/MySQL_Connector_Arduino/src/MySQL_Encrypt_Sha1.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* GNU GPL v3
|
||||
*
|
||||
* This file is part of the code entitled, "cryptosuite" available at
|
||||
* https://code.google.com/p/cryptosuite/. The file was copied from that
|
||||
* repository and renamed for use in Connector/Arduino to preserve
|
||||
* compatibility and protect against namespace collisions for users who
|
||||
* want to use the full cryptosuite functionality. For Connector/Arduino
|
||||
* all that is needed is this one sha1 class.
|
||||
*/
|
||||
#ifndef ENCRYPT_SHA1_H
|
||||
#define ENCRYPT_SHA1_H
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "Print.h"
|
||||
|
||||
#define HASH_LENGTH 20
|
||||
#define BLOCK_LENGTH 64
|
||||
|
||||
union _buffer {
|
||||
uint8_t b[BLOCK_LENGTH];
|
||||
uint32_t w[BLOCK_LENGTH/4];
|
||||
};
|
||||
union _state {
|
||||
uint8_t b[HASH_LENGTH];
|
||||
uint32_t w[HASH_LENGTH/4];
|
||||
};
|
||||
|
||||
class Encrypt_SHA1 : public Print
|
||||
{
|
||||
public:
|
||||
void init(void);
|
||||
void initHmac(const uint8_t* secret, int secretLength);
|
||||
uint8_t* result(void);
|
||||
virtual size_t write(uint8_t);
|
||||
virtual size_t write(uint8_t* data, int length);
|
||||
using Print::write;
|
||||
private:
|
||||
void pad();
|
||||
void addUncounted(uint8_t data);
|
||||
void hashBlock();
|
||||
uint32_t rol32(uint32_t number, uint8_t bits);
|
||||
_buffer buffer;
|
||||
uint8_t bufferOffset;
|
||||
_state state;
|
||||
uint32_t byteCount;
|
||||
uint8_t keyBuffer[BLOCK_LENGTH];
|
||||
uint8_t innerHash[HASH_LENGTH];
|
||||
|
||||
};
|
||||
|
||||
extern Encrypt_SHA1 Sha1;
|
||||
|
||||
#endif
|
||||
573
libraries/MySQL_Connector_Arduino/src/MySQL_Packet.cpp
Normal file
573
libraries/MySQL_Connector_Arduino/src/MySQL_Packet.cpp
Normal file
@@ -0,0 +1,573 @@
|
||||
/*
|
||||
Copyright (c) 2012, 2016 Oracle and/or its affiliates. All rights reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
MySQL_Packet.cpp - Packet library for communicating with a MySQL Server
|
||||
|
||||
Change History:
|
||||
|
||||
Version 1.0.0a Created by Dr. Charles A. Bell, April 2012.
|
||||
Version 1.0.0b Updated by Dr. Charles A. Bell, October 2013.
|
||||
Version 1.0.1b Updated by Dr. Charles A. Bell, February 2014.
|
||||
Version 1.0.2b Updated by Dr. Charles A. Bell, April 2014.
|
||||
Version 1.0.3rc Updated by Dr. Charles A. Bell, March 2015.
|
||||
Version 1.0.4ga Updated by Dr. Charles A. Bell, July 2015.
|
||||
Version 1.1.0a Created by Dr. Charles A. Bell, January 2016.
|
||||
Version 1.1.1a Created by Dr. Charles A. Bell, January 2016.
|
||||
Version 1.1.2b Created by Dr. Charles A. Bell, November 2016.
|
||||
Version 1.2.0 Created by Dr. Charles A. Bell, March 2020.
|
||||
*/
|
||||
#include <Arduino.h>
|
||||
#include <MySQL_Packet.h>
|
||||
#include <MySQL_Encrypt_Sha1.h>
|
||||
|
||||
#define MYSQL_DATA_TIMEOUT 3000 // Wifi client wait in milliseconds
|
||||
#define MYSQL_WAIT_INTERVAL 300 // WiFi client wait interval
|
||||
|
||||
/*
|
||||
Constructor
|
||||
|
||||
Initialize the buffer and store client instance.
|
||||
*/
|
||||
MySQL_Packet::MySQL_Packet(Client *client_instance) {
|
||||
buffer = NULL;
|
||||
client = client_instance;
|
||||
}
|
||||
|
||||
/*
|
||||
show_error
|
||||
|
||||
Print the curent error message.
|
||||
|
||||
msg[in] Message to print
|
||||
EOL[in] True if we print EOLN character
|
||||
*/
|
||||
void MySQL_Packet::show_error(const char *msg, bool EOL) {
|
||||
#ifdef DEBUG
|
||||
char pos;
|
||||
while ((pos = pgm_read_byte(msg))) {
|
||||
Serial.print(pos);
|
||||
msg++;
|
||||
}
|
||||
if (EOL)
|
||||
Serial.println();
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
send_authentication_packet
|
||||
|
||||
This method builds a response packet used to respond to the server's
|
||||
challenge packet (called the handshake packet). It includes the user
|
||||
name and password scrambled using the SHA1 seed from the handshake
|
||||
packet. It also sets the character set (default is 8 which you can
|
||||
change to meet your needs).
|
||||
|
||||
Note: you can also set the default database in this packet. See
|
||||
the code before for a comment on where this happens.
|
||||
|
||||
The authentication packet is defined as follows.
|
||||
|
||||
Bytes Name
|
||||
----- ----
|
||||
4 client_flags
|
||||
4 max_packet_size
|
||||
1 charset_number
|
||||
23 (filler) always 0x00...
|
||||
n (Null-Terminated String) user
|
||||
n (Length Coded Binary) scramble_buff (1 + x bytes)
|
||||
n (Null-Terminated String) databasename (optional)
|
||||
|
||||
user[in] User name
|
||||
password[in] password
|
||||
db[in] default database
|
||||
*/
|
||||
void MySQL_Packet::send_authentication_packet(char *user, char *password,
|
||||
char *db)
|
||||
{
|
||||
if (buffer != NULL)
|
||||
free(buffer);
|
||||
|
||||
buffer = (byte *)malloc(256);
|
||||
|
||||
int size_send = 4;
|
||||
|
||||
// client flags
|
||||
buffer[size_send] = byte(0x0D);
|
||||
buffer[size_send+1] = byte(0xa6);
|
||||
buffer[size_send+2] = byte(0x03);
|
||||
buffer[size_send+3] = byte(0x00);
|
||||
size_send += 4;
|
||||
|
||||
// max_allowed_packet
|
||||
buffer[size_send] = 0;
|
||||
buffer[size_send+1] = 0;
|
||||
buffer[size_send+2] = 0;
|
||||
buffer[size_send+3] = 1;
|
||||
size_send += 4;
|
||||
|
||||
// charset - default is 8
|
||||
buffer[size_send] = byte(0x08);
|
||||
size_send += 1;
|
||||
for(int i = 0; i < 24; i++)
|
||||
buffer[size_send+i] = 0x00;
|
||||
size_send += 23;
|
||||
|
||||
// user name
|
||||
memcpy((char *)&buffer[size_send], user, strlen(user));
|
||||
size_send += strlen(user) + 1;
|
||||
buffer[size_send-1] = 0x00;
|
||||
|
||||
// password - see scramble password
|
||||
byte *scramble = (uint8_t *)malloc(20);
|
||||
if (scramble_password(password, scramble)) {
|
||||
buffer[size_send] = 0x14;
|
||||
size_send += 1;
|
||||
for (int i = 0; i < 20; i++)
|
||||
buffer[i+size_send] = scramble[i];
|
||||
size_send += 20;
|
||||
buffer[size_send] = 0x00;
|
||||
}
|
||||
free(scramble);
|
||||
|
||||
if (db) {
|
||||
memcpy((char *)&buffer[size_send], db, strlen(db));
|
||||
size_send += strlen(db) + 1;
|
||||
buffer[size_send-1] = 0x00;
|
||||
} else {
|
||||
buffer[size_send+1] = 0x00;
|
||||
size_send += 1;
|
||||
}
|
||||
|
||||
// Write packet size
|
||||
int p_size = size_send - 4;
|
||||
store_int(&buffer[0], p_size, 3);
|
||||
buffer[3] = byte(0x01);
|
||||
|
||||
// Write the packet
|
||||
client->write((uint8_t*)buffer, size_send);
|
||||
client->flush();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
scramble_password - Build a SHA1 scramble of the user password
|
||||
|
||||
This method uses the password hash seed sent from the server to
|
||||
form a SHA1 hash of the password. This is used to send back to
|
||||
the server to complete the challenge and response step in the
|
||||
authentication handshake.
|
||||
|
||||
password[in] User's password in clear text
|
||||
pwd_hash[in] Seed from the server
|
||||
|
||||
Returns boolean - True = scramble succeeded
|
||||
*/
|
||||
boolean MySQL_Packet::scramble_password(char *password, byte *pwd_hash) {
|
||||
byte *digest;
|
||||
byte hash1[20];
|
||||
byte hash2[20];
|
||||
byte hash3[20];
|
||||
byte pwd_buffer[40];
|
||||
|
||||
if (strlen(password) == 0)
|
||||
return false;
|
||||
|
||||
// hash1
|
||||
Sha1.init();
|
||||
Sha1.print(password);
|
||||
digest = Sha1.result();
|
||||
memcpy(hash1, digest, 20);
|
||||
|
||||
// hash2
|
||||
Sha1.init();
|
||||
Sha1.write(hash1, 20);
|
||||
digest = Sha1.result();
|
||||
memcpy(hash2, digest, 20);
|
||||
|
||||
// hash3 of seed + hash2
|
||||
Sha1.init();
|
||||
memcpy(pwd_buffer, &seed, 20);
|
||||
memcpy(pwd_buffer+20, hash2, 20);
|
||||
Sha1.write(pwd_buffer, 40);
|
||||
digest = Sha1.result();
|
||||
memcpy(hash3, digest, 20);
|
||||
|
||||
// XOR for hash4
|
||||
for (int i = 0; i < 20; i++)
|
||||
pwd_hash[i] = hash1[i] ^ hash3[i];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
wait_for_bytes - Wait until data is available for reading
|
||||
|
||||
This method is used to permit the connector to respond to servers
|
||||
that have high latency or execute long queries. The timeout is
|
||||
set by MYSQL_DATA_TIMEOUT. Adjust this value to match the performance of
|
||||
your server and network.
|
||||
|
||||
It is also used to read how many bytes in total are available from the
|
||||
server. Thus, it can be used to know how large a data burst is from
|
||||
the server.
|
||||
|
||||
bytes_need[in] Bytes count to wait for
|
||||
|
||||
Returns integer - Number of bytes available to read.
|
||||
*/
|
||||
int MySQL_Packet::wait_for_bytes(int bytes_need)
|
||||
{
|
||||
const long wait_till = millis() + MYSQL_DATA_TIMEOUT;
|
||||
int num = 0;
|
||||
long now = 0;
|
||||
|
||||
do
|
||||
{
|
||||
now = millis();
|
||||
num = client->available();
|
||||
if (num < bytes_need)
|
||||
delay(MYSQL_WAIT_INTERVAL);
|
||||
else
|
||||
break;
|
||||
} while (now < wait_till);
|
||||
|
||||
if (num == 0 && now >= wait_till)
|
||||
client->stop();
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
/*
|
||||
read_packet - Read a packet from the server and store it in the buffer
|
||||
|
||||
This method reads the bytes sent by the server as a packet. All packets
|
||||
have a packet header defined as follows.
|
||||
|
||||
Bytes Name
|
||||
----- ----
|
||||
3 Packet Length
|
||||
1 Packet Number
|
||||
|
||||
Thus, the length of the packet (not including the packet header) can
|
||||
be found by reading the first 4 bytes from the server then reading
|
||||
N bytes for the packet payload.
|
||||
*/
|
||||
void MySQL_Packet::read_packet() {
|
||||
byte local[4];
|
||||
|
||||
if (buffer) {
|
||||
free(buffer);
|
||||
buffer = NULL;
|
||||
}
|
||||
|
||||
// Read packet header
|
||||
if (wait_for_bytes(4) < 4) {
|
||||
show_error(READ_TIMEOUT, true);
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < 4; i++)
|
||||
local[i] = client->read();
|
||||
|
||||
// Get packet length
|
||||
packet_len = local[0];
|
||||
packet_len += (local[1] << 8);
|
||||
packet_len += ((uint32_t)local[2] << 16);
|
||||
|
||||
// We must wait for slow arriving packets for Ethernet shields only.
|
||||
/*
|
||||
if (wait_for_bytes(packet_len) < packet_len) {
|
||||
show_error(READ_TIMEOUT, true);
|
||||
return;
|
||||
}
|
||||
*/
|
||||
// Check for valid packet.
|
||||
if (packet_len < 0) {
|
||||
show_error(PACKET_ERROR, true);
|
||||
packet_len = 0;
|
||||
}
|
||||
buffer = (byte *)malloc(packet_len+4);
|
||||
if (buffer == NULL) {
|
||||
show_error(MEMORY_ERROR, true);
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < 4; i++)
|
||||
buffer[i] = local[i];
|
||||
|
||||
for (int i = 4; i < packet_len+4; i++)
|
||||
buffer[i] = client->read();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
parse_handshake_packet - Decipher the server's challenge data
|
||||
|
||||
This method reads the server version string and the seed from the
|
||||
server. The handshake packet is defined as follows.
|
||||
|
||||
Bytes Name
|
||||
----- ----
|
||||
1 protocol_version
|
||||
n (Null-Terminated String) server_version
|
||||
4 thread_id
|
||||
8 scramble_buff
|
||||
1 (filler) always 0x00
|
||||
2 server_capabilities
|
||||
1 server_language
|
||||
2 server_status
|
||||
2 server capabilities (two upper bytes)
|
||||
1 length of the scramble seed
|
||||
10 (filler) always 0
|
||||
n rest of the plugin provided data
|
||||
(at least 12 bytes)
|
||||
1 \0 byte, terminating the second part of
|
||||
a scramble seed
|
||||
*/
|
||||
void MySQL_Packet::parse_handshake_packet() {
|
||||
if (!buffer)
|
||||
return;
|
||||
|
||||
int i = 5;
|
||||
do {
|
||||
i++;
|
||||
} while (buffer[i-1] != 0x00);
|
||||
|
||||
server_version = (char *)malloc(i-5);
|
||||
strncpy(server_version, (char *)&buffer[5], i-5);
|
||||
|
||||
// Capture the first 8 characters of seed
|
||||
i += 4; // Skip thread id
|
||||
for (int j = 0; j < 8; j++) {
|
||||
seed[j] = buffer[i+j];
|
||||
}
|
||||
|
||||
// Capture rest of seed
|
||||
i += 27; // skip ahead
|
||||
for (int j = 0; j < 12; j++) {
|
||||
seed[j+8] = buffer[i+j];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
parse_error_packet - Display the error returned from the server
|
||||
|
||||
This method parses an error packet from the server and displays the
|
||||
error code and text via Serial.print. The error packet is defined
|
||||
as follows.
|
||||
|
||||
Note: the error packet is already stored in the buffer since this
|
||||
packet is not an expected response.
|
||||
|
||||
Bytes Name
|
||||
----- ----
|
||||
1 field_count, always = 0xff
|
||||
2 errno
|
||||
1 (sqlstate marker), always '#'
|
||||
5 sqlstate (5 characters)
|
||||
n message
|
||||
*/
|
||||
void MySQL_Packet::parse_error_packet() {
|
||||
#ifdef DEBUG
|
||||
Serial.print("Error: ");
|
||||
Serial.print(read_int(5, 2));
|
||||
Serial.print(" = ");
|
||||
|
||||
if (!buffer)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < packet_len-9; i++)
|
||||
Serial.print((char)buffer[i+13]);
|
||||
Serial.println(".");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
get_packet_type - Returns the packet type received from the server.
|
||||
|
||||
Bytes Name
|
||||
----- ----
|
||||
1 (Length Coded Binary) field_count, always = 0
|
||||
1-9 (Length Coded Binary) affected_rows
|
||||
1-9 (Length Coded Binary) insert_id
|
||||
2 server_status
|
||||
2 warning_count
|
||||
n (until end of packet) message
|
||||
|
||||
Returns integer - 0 = successful parse, packet type if not an Ok packet
|
||||
*/
|
||||
int MySQL_Packet::get_packet_type() {
|
||||
if (!buffer)
|
||||
return -1;
|
||||
|
||||
int type = buffer[4];
|
||||
return type;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
get_lcb_len - Retrieves the length of a length coded binary value
|
||||
|
||||
This reads the first byte from the offset into the buffer and returns
|
||||
the number of bytes (size) that the integer consumes. It is used in
|
||||
conjunction with read_int() to read length coded binary integers
|
||||
from the buffer.
|
||||
|
||||
Returns integer - number of bytes integer consumes
|
||||
*/
|
||||
int MySQL_Packet::get_lcb_len(int offset) {
|
||||
if (!buffer)
|
||||
return 0;
|
||||
|
||||
int read_len = buffer[offset];
|
||||
if (read_len > 250) {
|
||||
// read type:
|
||||
byte type = buffer[offset+1];
|
||||
if (type == 0xfc)
|
||||
read_len = 2;
|
||||
else if (type == 0xfd)
|
||||
read_len = 3;
|
||||
else if (type == 0xfe)
|
||||
read_len = 8;
|
||||
} else {
|
||||
read_len = 1;
|
||||
}
|
||||
return read_len;
|
||||
}
|
||||
|
||||
/*
|
||||
read_int - Retrieve an integer from the buffer in size bytes.
|
||||
|
||||
This reads an integer from the buffer at offset position indicated for
|
||||
the number of bytes specified (size).
|
||||
|
||||
offset[in] offset from start of buffer
|
||||
size[in] number of bytes to use to store the integer
|
||||
|
||||
Returns integer - integer from the buffer
|
||||
*/
|
||||
int MySQL_Packet::read_int(int offset, int size) {
|
||||
int value = 0;
|
||||
int new_size = 0;
|
||||
if (!buffer)
|
||||
return -1;
|
||||
if (size == 0)
|
||||
new_size = get_lcb_len(offset);
|
||||
if (size == 1)
|
||||
return buffer[offset];
|
||||
new_size = size;
|
||||
int shifter = (new_size - 1) * 8;
|
||||
for (int i = new_size; i > 0; i--) {
|
||||
value += (buffer[i-1] << shifter);
|
||||
shifter -= 8;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
store_int - Store an integer value into a byte array of size bytes.
|
||||
|
||||
This writes an integer into the buffer at the current position of the
|
||||
buffer. It will transform an integer of size to a length coded binary
|
||||
form where 1-3 bytes are used to store the value (set by size).
|
||||
|
||||
buff[in] pointer to location in internal buffer where the
|
||||
integer will be stored
|
||||
value[in] integer value to be stored
|
||||
size[in] number of bytes to use to store the integer
|
||||
*/
|
||||
void MySQL_Packet::store_int(byte *buff, long value, int size) {
|
||||
memset(buff, 0, size);
|
||||
if (value < 0xff)
|
||||
buff[0] = (byte)value;
|
||||
else if (value < 0xffff) {
|
||||
buff[0] = (byte)value;
|
||||
buff[1] = (byte)(value >> 8);
|
||||
} else if (value < 0xffffff) {
|
||||
buff[0] = (byte)value;
|
||||
buff[1] = (byte)(value >> 8);
|
||||
buff[2] = (byte)(value >> 16);
|
||||
} else if (value < 0xffffff) {
|
||||
buff[0] = (byte)value;
|
||||
buff[1] = (byte)(value >> 8);
|
||||
buff[2] = (byte)(value >> 16);
|
||||
buff[3] = (byte)(value >> 24);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
read_lcb_int - Read an integer with len encoded byte
|
||||
|
||||
This reads an integer from the buffer looking at the first byte in the offset
|
||||
as the encoded length of the integer.
|
||||
|
||||
offset[in] offset from start of buffer
|
||||
|
||||
Returns integer - integer from the buffer
|
||||
*/
|
||||
int MySQL_Packet::read_lcb_int(int offset) {
|
||||
int len_size = 0;
|
||||
int size = 0;
|
||||
int value = 0;
|
||||
if (!buffer)
|
||||
return -1;
|
||||
len_size = buffer[offset];
|
||||
if (len_size < 252) {
|
||||
return buffer[offset];
|
||||
} else if (len_size == 252) {
|
||||
len_size = 2;
|
||||
} else if (len_size == 253) {
|
||||
len_size = 3;
|
||||
} else {
|
||||
len_size = 8;
|
||||
}
|
||||
int shifter = (len_size-1) * 8;
|
||||
for (int i = len_size; i > 0; i--) {
|
||||
value += (buffer[offset+i] << shifter);
|
||||
shifter -= 8;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/*
|
||||
print_packet - Print the contents of a packet via Serial.print
|
||||
|
||||
This method is a diagnostic method. It is best used to decipher a
|
||||
packet from the server (or before being sent to the server). If you
|
||||
are looking for additional program memory space, you can safely
|
||||
delete this method.
|
||||
*/
|
||||
void MySQL_Packet::print_packet() {
|
||||
if (!buffer)
|
||||
return;
|
||||
|
||||
Serial.print("Packet: ");
|
||||
Serial.print(buffer[3]);
|
||||
Serial.print(" contains ");
|
||||
Serial.print(packet_len+3);
|
||||
Serial.println(" bytes.");
|
||||
|
||||
Serial.print(" HEX: ");
|
||||
for (int i = 0; i < packet_len+3; i++) {
|
||||
Serial.print(buffer[i], HEX);
|
||||
Serial.print(' ');
|
||||
}
|
||||
Serial.println();
|
||||
Serial.print("ASCII: ");
|
||||
for (int i = 0; i < packet_len+3; i++)
|
||||
Serial.print((char)buffer[i]);
|
||||
Serial.println();
|
||||
}
|
||||
85
libraries/MySQL_Connector_Arduino/src/MySQL_Packet.h
Normal file
85
libraries/MySQL_Connector_Arduino/src/MySQL_Packet.h
Normal file
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
Copyright (c) 2012, 2016 Oracle and/or its affiliates. All rights reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
MySQL_Packet.h - Packet library for communicating with a MySQL Server
|
||||
|
||||
This header file defines the base packet handling code for connecting
|
||||
to a MySQL server and executing queries.
|
||||
|
||||
Change History:
|
||||
|
||||
Version 1.0.0a Created by Dr. Charles A. Bell, April 2012.
|
||||
Version 1.0.0b Updated by Dr. Charles A. Bell, October 2013.
|
||||
Version 1.0.1b Updated by Dr. Charles A. Bell, February 2014.
|
||||
Version 1.0.2b Updated by Dr. Charles A. Bell, April 2014.
|
||||
Version 1.0.3rc Updated by Dr. Charles A. Bell, March 2015.
|
||||
Version 1.0.4ga Updated by Dr. Charles A. Bell, July 2015.
|
||||
Version 1.1.0a Created by Dr. Charles A. Bell, January 2016.
|
||||
Version 1.1.1a Created by Dr. Charles A. Bell, January 2016.
|
||||
Version 1.1.2b Created by Dr. Charles A. Bell, November 2016.
|
||||
Version 1.2.0 Created by Dr. Charles A. Bell, March 2020.
|
||||
*/
|
||||
#ifndef MYSQL_PACKET_H
|
||||
#define MYSQL_PACKET_H
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
#include <Arduino.h>
|
||||
#elif ARDUINO_ARCH_ESP8266
|
||||
#include <ESP8266WiFi.h>
|
||||
#else
|
||||
// #include <WiFi.h>
|
||||
#include <Ethernet.h>
|
||||
#endif
|
||||
|
||||
#define MYSQL_OK_PACKET 0x00
|
||||
#define MYSQL_EOF_PACKET 0xfe
|
||||
#define MYSQL_ERROR_PACKET 0xff
|
||||
#define MYSQL_VERSION_STR "1.2.0"
|
||||
#define DEBUG
|
||||
|
||||
const char MEMORY_ERROR[] PROGMEM = "Memory error.";
|
||||
const char PACKET_ERROR[] PROGMEM = "Packet error.";
|
||||
const char READ_TIMEOUT[] PROGMEM = "ERROR: Timeout waiting for client.";
|
||||
|
||||
class MySQL_Packet {
|
||||
public:
|
||||
byte *buffer; // buffer for reading packets
|
||||
int packet_len; // length of current packet
|
||||
Client *client; // instance of client class (e.g. EthernetClient)
|
||||
char *server_version; // save server version from handshake
|
||||
|
||||
MySQL_Packet(Client *client_instance);
|
||||
boolean complete_handshake(char *user, char *password);
|
||||
void send_authentication_packet(char *user, char *password,
|
||||
char *db=NULL);
|
||||
void parse_handshake_packet();
|
||||
boolean scramble_password(char *password, byte *pwd_hash);
|
||||
void read_packet();
|
||||
int get_packet_type();
|
||||
void parse_error_packet();
|
||||
int get_lcb_len(int offset);
|
||||
int read_int(int offset, int size=0);
|
||||
void store_int(byte *buff, long value, int size);
|
||||
int read_lcb_int(int offset);
|
||||
int wait_for_bytes(int bytes_count);
|
||||
void show_error(const char *msg, bool EOL = false);
|
||||
void print_packet();
|
||||
|
||||
private:
|
||||
byte seed[20];
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user