Arduino - 将高分写入 SD 卡上的 SQLite 数据库
Posted
技术标签:
【中文标题】Arduino - 将高分写入 SD 卡上的 SQLite 数据库【英文标题】:Arduino - write highscores to SQLite database on SD card 【发布时间】:2021-12-30 03:10:04 【问题描述】:编辑 因为我找到的解决方案采用了不同的路径,所以我更新了标题以反映最终解决方案。最终解决方案允许通过简单的查询轻松添加和删除条目或检索您想要的条目数。最初的问题(下)是关于用 txt 文件解决问题的。
我有一个 ESP32,目前将高分写入 EEPROM。
每个条目都包含一个名称和分数。
我想用 SD 卡替换此工作解决方案。 我会在 SD 卡上有一个包含前 100 名分数的 txt 文件。一个文件会是这样的:
Player1 97.3 ROWCHECKSUM
Some player name 92.3 ROWCHECKSUM
Player1 91.2 ROWCHECKSUM
Player1 90.3 ROWCHECKSUM
Player2 87.1 ROWCHECKSUM
Player4 guy 77.3 ROWCHECKSUM
Player2 64.3 ROWCHECKSUM
Player1 61.1 ROWCHECKSUM
Player7 51.1 ROWCHECKSUM
.
.
.
Player9 21.1 ROWCHECKSUM
rowchecksum 将确保没有人手动更改文件。 每次有新的高分时,我都必须更新 txt 文件。什么是一个好的方法呢?每次都删除文件并重新生成?似乎要写入很多数据只是为了删除最后一行并将新行插入到适当的位置。
【问题讨论】:
【参考方案1】:我通过将数据写入 SD 卡上的 sqlite 数据库解决了这个问题。这样我可以简单地添加行,然后使用查询返回前 10 名玩家。
根据评论中的要求进行更新。
我的表叫做 highscores,它的结构是:
名称:字符串 分数:字符串 哈希:字符串has 是sha256(name + score + salt)
并确保没有人修改名称或分数。
#include <WiFi.h>
#include <WebServer.h>
#include <ArduinoJson.h>
#include <sqlite3.h>
#include <SPI.h>
#include <FS.h>
#include "SD.h"
#include "mbedtls/md.h"
#include "highscores.h"
[...]
WebServer server(80);
int rc;
sqlite3_stmt *res;
int rec_count = 0;
const char *tail;
sqlite3 *db1;
char *zErrMsg = 0;
File myFile;
[...]
void setup(void)
[...]
server.on("/highscores", handleHighscores);
server.on("/gethighscores", handleGetHighscores);
sqlite3_initialize();
if (openDb("/sd/mydb.db3", &db1))
return;
[...]
void loop(void)
server.handleClient();
if (progStep == SAVEHIGHSCORE)
String tmp = shooter + rankingAvgScore + "fajlo5a5%9k";
const char *payload = tmp.c_str();
byte shaResult[32];
mbedtls_md_context_t ctx;
mbedtls_md_type_t md_type = MBEDTLS_MD_SHA256;
const size_t payloadLength = strlen(payload);
mbedtls_md_init(&ctx);
mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(md_type), 0);
mbedtls_md_starts(&ctx);
mbedtls_md_update(&ctx, (const unsigned char *) payload, payloadLength);
mbedtls_md_finish(&ctx, shaResult);
mbedtls_md_free(&ctx);
String shastr;
for (int i = 0; i < sizeof(shaResult); i++)
char str[3];
sprintf(str, "%02x", (int)shaResult[i]);
shastr = shastr + str;
String sql = "insert into highscores ('name','score','hash') values ('";
sql += shooter;
sql += "','";
sql += rankingAvgScore;
sql += "','";
sql += shastr;
sql += "')";
rc = db_exec(db1, sql.c_str());
sql = "Select * from highscores order by score desc limit 10";
rc = sqlite3_prepare_v2(db1, sql.c_str(), 1000, &res, &tail);
if (rc != SQLITE_OK)
String resp = "Failed to fetch data: ";
resp += sqlite3_errmsg(db1);
Serial.println(resp.c_str());
return;
rec_count = 0;
while (sqlite3_step(res) == SQLITE_ROW)
highscoreNames[rec_count] = (const char *) sqlite3_column_text(res, 1);
highscoreScores[rec_count] = sqlite3_column_double(res, 2);
highscoreHash[rec_count] = (const char *) sqlite3_column_text(res, 3);
rec_count++;
sqlite3_finalize(res);
progStep = END;
这会根据请求发送网页。
void handleHighscores()
Serial.println("GET /");
server.send(200, "text/html", htmlhighscores);
这会在网页请求时从数据库中读取值..
void handleGetHighscores()
/* read highscores from sqlite db*/
String sql = "Select * from highscores order by score desc limit 10";
rc = sqlite3_prepare_v2(db1, sql.c_str(), 1000, &res, &tail);
if (rc != SQLITE_OK)
String resp = "Failed to fetch data: ";
resp += sqlite3_errmsg(db1);
Serial.println(resp.c_str());
return;
rec_count = 0;
while (sqlite3_step(res) == SQLITE_ROW)
highscoreNames[rec_count] = (const char *) sqlite3_column_text(res, 1);
highscoreScores[rec_count] = sqlite3_column_double(res, 2);
highscoreHash[rec_count] = (const char *) sqlite3_column_text(res, 3);
rec_count++;
sqlite3_finalize(res);
/* end read highschores from sqlite db*/
StaticJsonDocument<2000> doc;
JsonObject root = doc.to<JsonObject>();
JsonObject values = root["highscores"].to<JsonObject>();
//String highscoreNames[10];
//double highscoreScores[10];
for (int i = 0; i <= 9; i++)
String tmp = highscoreNames[i] + highscoreScores[i] + "fajlo5a5%9k";
const char *payload = tmp.c_str();
Serial.println(tmp);
byte shaResult[32];
mbedtls_md_context_t ctx;
mbedtls_md_type_t md_type = MBEDTLS_MD_SHA256;
const size_t payloadLength = strlen(payload);
mbedtls_md_init(&ctx);
mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(md_type), 0);
mbedtls_md_starts(&ctx);
mbedtls_md_update(&ctx, (const unsigned char *) payload, payloadLength);
mbedtls_md_finish(&ctx, shaResult);
mbedtls_md_free(&ctx);
String shastr;
for (int i = 0; i < sizeof(shaResult); i++)
char str[3];
sprintf(str, "%02x", (int)shaResult[i]);
shastr = shastr + str;
String tmp2 = "name" + (String)(i+1);
values[tmp2] = highscoreNames[i];
tmp2 = "score" + (String)(i+1);
values[tmp2] = highscoreScores[i];
Serial.println(highscoreHash[i]);
Serial.println(shastr);
if ((highscoreHash[i] != shastr) && (highscoreScores[i] > 0))
values[tmp2] = (String)highscoreScores[i] + (String)" Hacked.. :D";
Serial.println("Json SENT");
Serial.println(highscoreScores[0]);
String json;
serializeJsonPretty(doc, json);
//Serial.println(json);
server.send(200, "text/plane", json);
highschores.h 文件
const char htmlhighscores[] PROGMEM = R"=====(
<html>
<style>
div.divshooter
text-align: center;
font-size: 18px;
font-weight: bold;
div.minimalistBlack
border: 0px solid #000000;
width: 100%;
text-align: left;
border-collapse: collapse;
.divTable.minimalistBlack .divTableCell, .divTable.minimalistBlack .divTableHead
border: 1px solid #000000;
padding: 5px 4px;
.divTable.minimalistBlack .divTableBody .divTableCell
font-size: 13px;
.divTable.minimalistBlack .divTableHeading
background: #CFCFCF;
background: -moz-linear-gradient(top, #dbdbdb 0%, #d3d3d3 66%, #CFCFCF 100%);
background: -webkit-linear-gradient(top, #dbdbdb 0%, #d3d3d3 66%, #CFCFCF 100%);
background: linear-gradient(to bottom, #dbdbdb 0%, #d3d3d3 66%, #CFCFCF 100%);
border-bottom: 3px solid #000000;
.divTable.minimalistBlack .divTableHeading .divTableHead
font-size: 15px;
font-weight: bold;
color: #000000;
text-align: left;
.minimalistBlack .tableFootStyle
font-size: 14px;
font-weight: bold;
color: #000000;
border-top: 3px solid #000000;
.minimalistBlack .tableFootStyle
font-size: 14px;
/* DivTable.com */
.divTable display: table;
.divTableRow display: table-row;
.divTableHeading display: table-header-group;
.divTableCell, .divTableHead display: table-cell;
.divTableHeading display: table-header-group;
.divTableFoot display: table-footer-group;
.divTableBody display: table-row-group;
</style>
<script>
function getData()
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function()
if (this.readyState == 4 && this.status == 200)
var jsonval = JSON.parse( this.responseText );
document.getElementById("name1").innerHTML = jsonval.highscores["name1"];
document.getElementById("score1").innerHTML = jsonval.highscores["score1"];
document.getElementById("name2").innerHTML = jsonval.highscores["name2"];
document.getElementById("score2").innerHTML = jsonval.highscores["score2"];
document.getElementById("name3").innerHTML = jsonval.highscores["name3"];
document.getElementById("score3").innerHTML = jsonval.highscores["score3"];
document.getElementById("name4").innerHTML = jsonval.highscores["name4"];
document.getElementById("score4").innerHTML = jsonval.highscores["score4"];
document.getElementById("name5").innerHTML = jsonval.highscores["name5"];
document.getElementById("score5").innerHTML = jsonval.highscores["score5"];
document.getElementById("name6").innerHTML = jsonval.highscores["name6"];
document.getElementById("score6").innerHTML = jsonval.highscores["score6"];
document.getElementById("name7").innerHTML = jsonval.highscores["name7"];
document.getElementById("score7").innerHTML = jsonval.highscores["score7"];
document.getElementById("name8").innerHTML = jsonval.highscores["name8"];
document.getElementById("score8").innerHTML = jsonval.highscores["score8"];
document.getElementById("name9").innerHTML = jsonval.highscores["name9"];
document.getElementById("score9").innerHTML = jsonval.highscores["score9"];
document.getElementById("name10").innerHTML = jsonval.highscores["name10"];
document.getElementById("score10").innerHTML = jsonval.highscores["score10"];
console.log(this.responseText);
;
xhttp.open("GET", "gethighscores", true);
xhttp.send();
</script>
<body onload="getData();">
<h2>Highscores</h2>
<div class="divTable minimalistBlack">
<div class="divTableHeading">
<div class="divTableRow">
<div class="divTableHead">Rank</div>
<div class="divTableHead">Name</div>
<div class="divTableHead">Score</div>
</div>
</div>
<div class="divTableBody">
<div class = "divTableRow">
<div class = "divTableCell"><b><u>1</u></b></div>
<div class = "divTableCell" id="name1"></div>
<div class = "divTableCell" id="score1"></div>
</div>
<div class = "divTableRow">
<div class = "divTableCell"><b>2</b></div>
<div class = "divTableCell" id="name2"></div>
<div class = "divTableCell" id="score2"></div>
</div>
<div class = "divTableRow">
<div class = "divTableCell"><b>3</b></div>
<div class = "divTableCell" id="name3"></div>
<div class = "divTableCell" id="score3"></div>
</div>
<div class = "divTableRow">
<div class = "divTableCell">4</div>
<div class = "divTableCell" id="name4"></div>
<div class = "divTableCell" id="score4"></div>
</div>
<div class = "divTableRow">
<div class = "divTableCell">5</div>
<div class = "divTableCell" id="name5"></div>
<div class = "divTableCell" id="score5"></div>
</div>
<div class = "divTableRow">
<div class = "divTableCell">6</div>
<div class = "divTableCell" id="name6"></div>
<div class = "divTableCell" id="score6"></div>
</div>
<div class = "divTableRow">
<div class = "divTableCell">7</div>
<div class = "divTableCell" id="name7"></div>
<div class = "divTableCell" id="score7"></div>
</div>
<div class = "divTableRow">
<div class = "divTableCell">8</div>
<div class = "divTableCell" id="name8"></div>
<div class = "divTableCell" id="score8"></div>
</div>
<div class = "divTableRow">
<div class = "divTableCell">9</div>
<div class = "divTableCell" id="name9"></div>
<div class = "divTableCell" id="score9"></div>
</div>
<div class = "divTableRow">
<div class = "divTableCell">10</div>
<div class = "divTableCell" id="name10"></div>
<div class = "divTableCell" id="score10"></div>
</div>
</div>
</div>
</div>
</br></br>
<form action="/">
<center> <input type="submit" value="Back to start" /></center>
</form>
</body>
</html>)=====";
【讨论】:
你能分享一下选择和打印前 10 名球员的代码吗?我正在做类似的事情 @VAAA 当然可以,但是因为我现在不在家,所以只能在大约 10 小时内完成。你已经完成了对数据库的写入?你到底需要什么零件? 非常感谢。我开始添加sqlite。所以真的什么都没有。 @VAAA 完成。希望它有所帮助,我不得不删除代码,因为它包含大量不相关的代码,我无法发布。以上是关于Arduino - 将高分写入 SD 卡上的 SQLite 数据库的主要内容,如果未能解决你的问题,请参考以下文章
如何从 Android API 24+ 在 SD 卡上写入文件