Skip to content

Commit 2df4d49

Browse files
committed
Add Webquery example
1 parent c51be75 commit 2df4d49

File tree

6 files changed

+251
-0
lines changed

6 files changed

+251
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.DS_Store
1.52 MB
Binary file not shown.
Lines changed: 250 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,250 @@
1+
/*
2+
This example shows how to retrieve data from Sqlite3 databases from SD Card
3+
through the Web Server and display in the form of HTML page.
4+
It also demonstrates query filtering by parameter passing and chunked encoding.
5+
Before running please copy following files to SD Card:
6+
7+
data/babyname.db
8+
9+
This database contains around 30000 baby names and corresponding data.
10+
11+
For more information, visit https://github.com/siara-cc/esp32_arduino_sqlite3_lib
12+
13+
Copyright (c) 2018, Siara Logics (cc)
14+
*/
15+
16+
/*
17+
Copyright (c) 2015, Majenko Technologies
18+
All rights reserved.
19+
20+
Redistribution and use in source and binary forms, with or without modification,
21+
are permitted provided that the following conditions are met:
22+
23+
* * Redistributions of source code must retain the above copyright notice, this
24+
list of conditions and the following disclaimer.
25+
26+
* * Redistributions in binary form must reproduce the above copyright notice, this
27+
list of conditions and the following disclaimer in the documentation and/or
28+
other materials provided with the distribution.
29+
30+
* * Neither the name of Majenko Technologies nor the names of its
31+
contributors may be used to endorse or promote products derived from
32+
this software without specific prior written permission.
33+
34+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
35+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
36+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
37+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
38+
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
39+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
40+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
41+
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
42+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
43+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
44+
*/
45+
46+
#include <WiFi.h>
47+
#include <WiFiClient.h>
48+
#include <WebServer.h>
49+
#include <ESPmDNS.h>
50+
#include <sqlite3.h>
51+
#include <FS.h>
52+
#include "SD_MMC.h"
53+
54+
const char *ssid = "Nokia1";
55+
const char *password = "nokiafour";
56+
57+
WebServer server(80);
58+
59+
const int led = 13;
60+
61+
void handleRoot() {
62+
digitalWrite ( led, 1 );
63+
String temp;
64+
int sec = millis() / 1000;
65+
int min = sec / 60;
66+
int hr = min / 60;
67+
68+
temp = "<html><head>\
69+
<title>ESP32 Demo</title>\
70+
<style>\
71+
body { background-color: #cccccc; font-family: Arial, Helvetica, Sans-Serif; font-size: large; Color: #000088; }\
72+
</style>\
73+
</head>\
74+
<body>\
75+
<h1>Hello from ESP32!</h1>\
76+
<p>Uptime: ";
77+
temp += hr;
78+
temp += ":";
79+
temp += min % 60;
80+
temp += ":";
81+
temp += sec % 60;
82+
temp += "</p>\
83+
<h2>Query gendered names database</h2>\
84+
<form name='params' method='GET' action='query_db'>\
85+
Enter from: <input type=text style='font-size: large' value='Bob' name='from'/> \
86+
<br>to: <input type=text style='font-size: large' value='Bobby' name='to'/> \
87+
<br><br><input type=submit style='font-size: large' value='Query database'/>\
88+
</form>\
89+
</body>\
90+
</html>";
91+
92+
server.send ( 200, "text/html", temp.c_str() );
93+
digitalWrite ( led, 0 );
94+
}
95+
96+
void handleNotFound() {
97+
digitalWrite ( led, 1 );
98+
String message = "File Not Found\n\n";
99+
message += "URI: ";
100+
message += server.uri();
101+
message += "\nMethod: ";
102+
message += ( server.method() == HTTP_GET ) ? "GET" : "POST";
103+
message += "\nArguments: ";
104+
message += server.args();
105+
message += "\n";
106+
107+
for ( uint8_t i = 0; i < server.args(); i++ ) {
108+
message += " " + server.argName ( i ) + ": " + server.arg ( i ) + "\n";
109+
}
110+
111+
server.send ( 404, "text/plain", message );
112+
digitalWrite ( led, 0 );
113+
}
114+
115+
sqlite3 *db1;
116+
int rc;
117+
sqlite3_stmt *res;
118+
int rec_count = 0;
119+
const char *tail;
120+
121+
int openDb(const char *filename, sqlite3 **db) {
122+
int rc = sqlite3_open(filename, db);
123+
if (rc) {
124+
Serial.printf("Can't open database: %s\n", sqlite3_errmsg(*db));
125+
return rc;
126+
} else {
127+
Serial.printf("Opened database successfully\n");
128+
}
129+
return rc;
130+
}
131+
132+
void setup ( void ) {
133+
pinMode(led, OUTPUT);
134+
digitalWrite(led, 0);
135+
Serial.begin(115200);
136+
WiFi.mode(WIFI_STA);
137+
WiFi.begin(ssid, password);
138+
Serial.println("");
139+
140+
// Wait for connection
141+
while ( WiFi.status() != WL_CONNECTED ) {
142+
delay ( 500 );
143+
Serial.print ( "." );
144+
}
145+
146+
Serial.println ( "" );
147+
Serial.print ( "Connected to " );
148+
Serial.println ( ssid );
149+
Serial.print ( "IP address: " );
150+
Serial.println ( WiFi.localIP() );
151+
152+
if ( MDNS.begin ( "esp32" ) ) {
153+
Serial.println ( "MDNS responder started" );
154+
}
155+
156+
SD_MMC.begin();
157+
sqlite3_initialize();
158+
159+
// Open database
160+
if (openDb("/sdcard/babyname.db", &db1))
161+
return;
162+
163+
server.on ( "/", handleRoot );
164+
server.on ( "/query_db", []() {
165+
String sql = "Select count(*) from gendered_names where name between '";
166+
sql += server.arg("from");
167+
sql += "' and '";
168+
sql += server.arg("to");
169+
sql += "'";
170+
rc = sqlite3_prepare_v2(db1, sql.c_str(), 1000, &res, &tail);
171+
if (rc != SQLITE_OK) {
172+
String resp = "Failed to fetch data: ";
173+
resp += sqlite3_errmsg(db1);
174+
resp += ".<br><br><input type=button onclick='location.href=\"/\"' value='back'/>";
175+
server.send ( 200, "text/html", resp.c_str());
176+
Serial.println(resp.c_str());
177+
return;
178+
}
179+
while (sqlite3_step(res) == SQLITE_ROW) {
180+
rec_count = sqlite3_column_int(res, 0);
181+
if (rec_count > 5000) {
182+
String resp = "Too many records: ";
183+
resp += rec_count;
184+
resp += ". Please select different range";
185+
resp += ".<br><br><input type=button onclick='location.href=\"/\"' value='back'/>";
186+
server.send ( 200, "text/html", resp.c_str());
187+
Serial.println(resp.c_str());
188+
sqlite3_finalize(res);
189+
return;
190+
}
191+
}
192+
sqlite3_finalize(res);
193+
194+
sql = "Select year, state, name, total_babies, primary_sex, primary_sex_ratio, per_100k_in_state from gendered_names where name between '";
195+
sql += server.arg("from");
196+
sql += "' and '";
197+
sql += server.arg("to");
198+
sql += "'";
199+
rc = sqlite3_prepare_v2(db1, sql.c_str(), 1000, &res, &tail);
200+
if (rc != SQLITE_OK) {
201+
String resp = "Failed to fetch data: ";
202+
resp += sqlite3_errmsg(db1);
203+
resp += "<br><br><a href='/'>back</a>";
204+
server.send ( 200, "text/html", resp.c_str());
205+
Serial.println(resp.c_str());
206+
return;
207+
}
208+
209+
rec_count = 0;
210+
server.setContentLength(CONTENT_LENGTH_UNKNOWN);
211+
String resp = "<html><head><title>ESP32 Sqlite local database query through web server</title>\
212+
<style>\
213+
body { background-color: #cccccc; font-family: Arial, Helvetica, Sans-Serif; font-size: large; Color: #000088; }\
214+
</style><head><body><h1>ESP32 Sqlite local database query through web server</h1><h2>";
215+
resp += sql;
216+
resp += "</h2><br><table cellspacing='1' cellpadding='1' border='1'><tr><td>Year</td><td>State</td><td>Name</td><td>Total babies</td><td>Primary Sex</td><td>Ratio</td><td>Per 100k</td></tr>";
217+
server.send ( 200, "text/html", resp.c_str());
218+
while (sqlite3_step(res) == SQLITE_ROW) {
219+
resp = "<tr><td>";
220+
resp += sqlite3_column_int(res, 0);
221+
resp += "</td><td>";
222+
resp += (const char *) sqlite3_column_text(res, 1);
223+
resp += "</td><td>";
224+
resp += (const char *) sqlite3_column_text(res, 2);
225+
resp += "</td><td>";
226+
resp += sqlite3_column_int(res, 3);
227+
resp += "</td><td>";
228+
resp += (const char *) sqlite3_column_text(res, 4);
229+
resp += "</td><td>";
230+
resp += sqlite3_column_double(res, 5);
231+
resp += "</td><td>";
232+
resp += sqlite3_column_double(res, 6);
233+
resp += "</td></tr>";
234+
server.sendContent(resp);
235+
rec_count++;
236+
}
237+
resp = "</table><br><br>Number of records: ";
238+
resp += rec_count;
239+
resp += ".<br><br><input type=button onclick='location.href=\"/\"' value='back'/>";
240+
server.sendContent(resp);
241+
sqlite3_finalize(res);
242+
} );
243+
server.onNotFound ( handleNotFound );
244+
server.begin();
245+
Serial.println ( "HTTP server started" );
246+
}
247+
248+
void loop ( void ) {
249+
server.handleClient();
250+
}

output_web_1.png

41.2 KB
Loading

output_web_2.png

101 KB
Loading

siara_cc_visiting_card.png

4.62 MB
Loading

0 commit comments

Comments
 (0)