ESP32: сохранить до 8 Wi-Fi сетей и ускорить burn
This commit is contained in:
parent
9ca469a075
commit
f095182673
@ -20,6 +20,9 @@
|
||||
- `SELECT NETWORK` запускает скан;
|
||||
- после скана показывается список доступных SSID;
|
||||
- выбор SSID открывает общий экран редактирования текста для пароля;
|
||||
- если для этого SSID пароль уже сохранялся раньше, он автоматически подставляется в редактор;
|
||||
- если затем ввести пароль для другого SSID, пароль первой сети не теряется;
|
||||
- одновременно хранится до `8` паролей для разных SSID;
|
||||
- на этом экране видно старое значение, курсор стоит в конце;
|
||||
- две верхние служебные строки над полем ввода отсутствуют;
|
||||
- при вводе пароля Wi-Fi текст показывается открыто, без точек;
|
||||
@ -40,6 +43,7 @@
|
||||
- медленный свайп по экрану не должен превращаться в случайное нажатие кнопки;
|
||||
- `ABC/123`, `SHIFT`, `DEL`, `SAVE`, `CANCEL` работают;
|
||||
- при успехе SSID и пароль сохраняются, а `HOME` показывает `Wi-Fi connected`;
|
||||
- если после подключения ко второй сети снова выбрать первую, её старый пароль уже подставлен и достаточно нажать `SAVE`;
|
||||
- при ошибке показывается `Connection failed`;
|
||||
- `CLEAR SAVED WI-FI` очищает сохранённые настройки;
|
||||
- если сеть была ранее успешно сохранена, после потери связи устройство автоматически пытается переподключиться;
|
||||
@ -62,6 +66,7 @@
|
||||
- `EDIT MANUALLY` открывает общий экран редактирования и сохраняет значение в NVS;
|
||||
- `Secret` открывает экран-заглушку, где сказано, что настройка ещё не реализована;
|
||||
- `Secret` теперь открывает меню секрета с показом секрета, ручным вводом и генерацией;
|
||||
- в `SHOW SECRET` сам секрет показывается увеличенным шрифтом и разбит по `10` символов в строке;
|
||||
- при смене `login` сохранённый секрет сбрасывается в `not set`;
|
||||
- во время генерации секрета есть `CANCEL` и подтверждение остановки;
|
||||
- при отмене генерации старый секрет, если он был, не должен теряться;
|
||||
|
||||
@ -90,7 +90,7 @@
|
||||
|
||||
Показывает:
|
||||
- текущий Wi-Fi статус;
|
||||
- сохранённый SSID;
|
||||
- сохранённый SSID и число известных сетей;
|
||||
- статусное сообщение;
|
||||
- кнопку `SELECT NETWORK`;
|
||||
- кнопку `CLEAR SAVED WI-FI`;
|
||||
@ -109,6 +109,13 @@
|
||||
|
||||
Нажатие на SSID открывает `TEXT_EDIT_SCREEN` для ввода пароля.
|
||||
|
||||
Поведение:
|
||||
- если для выбранного SSID пароль уже был сохранён раньше, он сразу подставляется в поле ввода;
|
||||
- если пароль меняют для другого SSID, старые сохранённые пароли других сетей не теряются;
|
||||
- после успешного подключения выбранная сеть становится текущей `wifi_ssid/wifi_pass`;
|
||||
- одновременно хранится до `8` известных сетей `SSID -> password`;
|
||||
- `CLEAR SAVED WI-FI` очищает все сохранённые сети и текущую сеть.
|
||||
|
||||
Переходы:
|
||||
- свайп вправо из любого режима `WIFI_SCREEN` -> `SETTINGS_MENU`
|
||||
- кнопка `BACK` -> `SETTINGS_MENU`
|
||||
@ -162,16 +169,26 @@
|
||||
|
||||
## ACCOUNT_SECRET_SCREEN
|
||||
|
||||
Пока это заглушка.
|
||||
|
||||
Показывает:
|
||||
- текущий статус секрета `set/not set`;
|
||||
- сообщение, что настройка секрета пока не реализована;
|
||||
- кнопку `BACK`.
|
||||
- кнопку `SHOW SECRET` или серую `SECRET NOT SET`, если секрета ещё нет;
|
||||
- кнопку `ENTER SECRET MANUALLY (NOT RECOMMENDED)`;
|
||||
- кнопку `GENERATE SECRET`.
|
||||
|
||||
Переходы:
|
||||
- свайп вправо -> `ACCOUNT_SCREEN`
|
||||
- `BACK` -> `ACCOUNT_SCREEN`
|
||||
- `SHOW SECRET` -> экран просмотра секрета
|
||||
- `ENTER SECRET MANUALLY (NOT RECOMMENDED)` -> `TEXT_EDIT_SCREEN`
|
||||
- `GENERATE SECRET` -> экран подтверждения генерации
|
||||
|
||||
## SECRET_SHOW_SCREEN
|
||||
|
||||
Показывает:
|
||||
- заголовок `SECRET`;
|
||||
- подпись `Current secret in base58:`;
|
||||
- полный секрет открытым текстом;
|
||||
- увеличенный шрифт для значения секрета;
|
||||
- разбиение секрета по строкам по `10` символов;
|
||||
- кнопку `BACK`.
|
||||
|
||||
## TEXT_EDIT_SCREEN
|
||||
|
||||
@ -211,8 +228,13 @@
|
||||
- `wifi_ssid`
|
||||
- `wifi_pass`
|
||||
- `wifi_known_good`
|
||||
- до `8` сохранённых пар `SSID -> password`
|
||||
|
||||
При старте устройства, если сохранён SSID, выполняется попытка подключения к сохранённой сети.
|
||||
При старте устройства, если сохранён SSID, выполняется попытка подключения к текущей сохранённой сети.
|
||||
|
||||
Если пользователь уже вводил пароль для сети раньше:
|
||||
- при повторном выборе этого SSID старый пароль сразу подставляется в editor screen;
|
||||
- сохранение пароля для другой сети не удаляет уже сохранённые пароли остальных сетей.
|
||||
|
||||
Если сеть раньше уже была успешно подключена и помечена как валидная:
|
||||
- после потери связи устройство автоматически пытается переподключиться;
|
||||
|
||||
@ -1,6 +1,10 @@
|
||||
# Test Device
|
||||
|
||||
Скрипт заливает официальные Arduino-примеры для быстрой проверки платы.
|
||||
`burn.sh` теперь:
|
||||
- сам пытается найти USB-порт ESP32;
|
||||
- сначала делает быструю инкрементальную сборку;
|
||||
- если быстрая сборка не удалась, автоматически повторяет полную `clean`-сборку.
|
||||
|
||||
Для режимов `widgets`, `audio` и `hello` рядом должен лежать локальный checkout `official-demo/` из официального репозитория Waveshare. В основной git он не добавляется, потому что это большой внешний набор примеров, библиотек, прошивок и артефактов.
|
||||
|
||||
|
||||
@ -5,11 +5,29 @@ ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
BOARD_DIR="$(cd "${ROOT_DIR}/.." && pwd)"
|
||||
DEMO_BASE="${BOARD_DIR}/official-demo/examples/Arduino-v3.3.5"
|
||||
MODE="${1:-widgets}"
|
||||
PORT="${PORT:-/dev/ttyACM0}"
|
||||
PORT="${PORT:-}"
|
||||
FQBN="${FQBN:-esp32:esp32:esp32s3:USBMode=hwcdc,CDCOnBoot=cdc,UploadSpeed=921600,CPUFreq=240,FlashMode=dio,FlashSize=16M,PartitionScheme=app3M_fat9M_16MB,PSRAM=opi}"
|
||||
BUILD_DIR="${BUILD_DIR:-${ROOT_DIR}/.arduino-build/build-${MODE}}"
|
||||
OUT_DIR="${OUT_DIR:-${ROOT_DIR}/.arduino-build/out-${MODE}}"
|
||||
|
||||
detect_port() {
|
||||
local detected
|
||||
detected="$(arduino-cli board list 2>/dev/null | awk '/\/dev\/tty(ACM|USB)/ {print $1; exit}')"
|
||||
if [[ -n "${detected}" ]]; then
|
||||
echo "${detected}"
|
||||
return 0
|
||||
fi
|
||||
|
||||
for candidate in /dev/ttyACM* /dev/ttyUSB*; do
|
||||
if [[ -e "${candidate}" ]]; then
|
||||
echo "${candidate}"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
case "${MODE}" in
|
||||
hello) SKETCH_DIR="${DEMO_BASE}/examples/01_HelloWorld" ;;
|
||||
widgets) SKETCH_DIR="${DEMO_BASE}/examples/05_LVGL_Widgets" ;;
|
||||
@ -34,6 +52,13 @@ case "${MODE}" in
|
||||
;;
|
||||
esac
|
||||
|
||||
if [[ -z "${PORT}" ]]; then
|
||||
if ! PORT="$(detect_port)"; then
|
||||
echo "Failed to auto-detect ESP32 port. Set PORT=/dev/ttyACM0 ./burn.sh ${MODE}" >&2
|
||||
exit 3
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "== Mode: ${MODE}"
|
||||
echo "== Sketch: ${SKETCH_DIR}"
|
||||
echo "== Port: ${PORT}"
|
||||
@ -41,17 +66,23 @@ echo "== FQBN: ${FQBN}"
|
||||
|
||||
mkdir -p "${BUILD_DIR}" "${OUT_DIR}"
|
||||
|
||||
arduino-cli compile \
|
||||
--clean \
|
||||
--fqbn "${FQBN}" \
|
||||
--build-path "${BUILD_DIR}" \
|
||||
--output-dir "${OUT_DIR}" \
|
||||
--library "${DEMO_BASE}/libraries/GFX_Library_for_Arduino" \
|
||||
--library "${DEMO_BASE}/libraries/SensorLib" \
|
||||
--library "${DEMO_BASE}/libraries/XPowersLib" \
|
||||
--library "${DEMO_BASE}/libraries/lvgl" \
|
||||
--library "${DEMO_BASE}/libraries/Mylibrary" \
|
||||
compile_args=(
|
||||
--fqbn "${FQBN}"
|
||||
--build-path "${BUILD_DIR}"
|
||||
--output-dir "${OUT_DIR}"
|
||||
--library "${DEMO_BASE}/libraries/GFX_Library_for_Arduino"
|
||||
--library "${DEMO_BASE}/libraries/SensorLib"
|
||||
--library "${DEMO_BASE}/libraries/XPowersLib"
|
||||
--library "${DEMO_BASE}/libraries/lvgl"
|
||||
--library "${DEMO_BASE}/libraries/Mylibrary"
|
||||
"${SKETCH_DIR}"
|
||||
)
|
||||
|
||||
echo "== Compile: fast incremental build"
|
||||
if ! arduino-cli compile "${compile_args[@]}"; then
|
||||
echo "== Compile: fast build failed, retrying clean build"
|
||||
arduino-cli compile --clean "${compile_args[@]}"
|
||||
fi
|
||||
|
||||
arduino-cli upload \
|
||||
-p "${PORT}" \
|
||||
|
||||
@ -27,6 +27,7 @@
|
||||
#define SWIPE_THRESHOLD 48
|
||||
#define TAP_CANCEL_THRESHOLD 18
|
||||
#define MAX_SCAN_RESULTS 8
|
||||
#define MAX_SAVED_WIFI_NETWORKS 8
|
||||
#define WIFI_CONNECT_TIMEOUT_MS 12000
|
||||
#define WIFI_RECONNECT_FAST_MS 10000
|
||||
#define WIFI_RECONNECT_SLOW_MS 30000
|
||||
@ -144,6 +145,8 @@ static uint32_t gLastHandledTouchSequence = 0;
|
||||
static String gWifiSavedSsid;
|
||||
static String gWifiSavedPassword;
|
||||
static String gWifiSelectedSsid;
|
||||
static String gKnownWifiSsids[MAX_SAVED_WIFI_NETWORKS];
|
||||
static String gKnownWifiPasswords[MAX_SAVED_WIFI_NETWORKS];
|
||||
static String gWifiStatusMessage = "No Wi-Fi configured";
|
||||
static String gScanResults[MAX_SCAN_RESULTS];
|
||||
static int gScanResultCount = 0;
|
||||
@ -182,6 +185,10 @@ static void handleSwipe(SwipeDirection swipe);
|
||||
static void loadPrefs();
|
||||
static void saveWifiPrefs();
|
||||
static void clearWifiPrefs();
|
||||
static void clearSavedWifiList();
|
||||
static int findKnownWifiIndex(const String &ssid);
|
||||
static String savedPasswordForSsid(const String &ssid);
|
||||
static void upsertKnownWifi(const String &ssid, const String &password);
|
||||
static void saveServerPrefs();
|
||||
static void saveAccountPrefs();
|
||||
static void beginSavedWifi();
|
||||
@ -334,10 +341,86 @@ static void showMessageAt(const String &text, lv_coord_t y) {
|
||||
lv_obj_align(label, LV_ALIGN_TOP_MID, 0, y);
|
||||
}
|
||||
|
||||
static void clearSavedWifiList() {
|
||||
for (int i = 0; i < MAX_SAVED_WIFI_NETWORKS; ++i) {
|
||||
gKnownWifiSsids[i] = "";
|
||||
gKnownWifiPasswords[i] = "";
|
||||
}
|
||||
}
|
||||
|
||||
static int findKnownWifiIndex(const String &ssid) {
|
||||
if (ssid.isEmpty()) {
|
||||
return -1;
|
||||
}
|
||||
for (int i = 0; i < MAX_SAVED_WIFI_NETWORKS; ++i) {
|
||||
if (gKnownWifiSsids[i] == ssid) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static String savedPasswordForSsid(const String &ssid) {
|
||||
int index = findKnownWifiIndex(ssid);
|
||||
return index >= 0 ? gKnownWifiPasswords[index] : "";
|
||||
}
|
||||
|
||||
static String splitFixedWidth(const String &value, size_t chunkSize) {
|
||||
if (chunkSize == 0 || value.isEmpty()) {
|
||||
return value;
|
||||
}
|
||||
|
||||
String out;
|
||||
for (size_t i = 0; i < value.length(); ++i) {
|
||||
if (i > 0 && (i % chunkSize) == 0) {
|
||||
out += '\n';
|
||||
}
|
||||
out += value.charAt(i);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
static void upsertKnownWifi(const String &ssid, const String &password) {
|
||||
if (ssid.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int existing = findKnownWifiIndex(ssid);
|
||||
if (existing >= 0) {
|
||||
gKnownWifiPasswords[existing] = password;
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < MAX_SAVED_WIFI_NETWORKS; ++i) {
|
||||
if (gKnownWifiSsids[i].isEmpty()) {
|
||||
gKnownWifiSsids[i] = ssid;
|
||||
gKnownWifiPasswords[i] = password;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < MAX_SAVED_WIFI_NETWORKS - 1; ++i) {
|
||||
gKnownWifiSsids[i] = gKnownWifiSsids[i + 1];
|
||||
gKnownWifiPasswords[i] = gKnownWifiPasswords[i + 1];
|
||||
}
|
||||
gKnownWifiSsids[MAX_SAVED_WIFI_NETWORKS - 1] = ssid;
|
||||
gKnownWifiPasswords[MAX_SAVED_WIFI_NETWORKS - 1] = password;
|
||||
}
|
||||
|
||||
static void loadPrefs() {
|
||||
clearSavedWifiList();
|
||||
gWifiSavedSsid = gPrefs.getString("wifi_ssid", "");
|
||||
gWifiSavedPassword = gPrefs.getString("wifi_pass", "");
|
||||
gWifiKnownGood = gPrefs.getBool("wifi_known_good", false);
|
||||
for (int i = 0; i < MAX_SAVED_WIFI_NETWORKS; ++i) {
|
||||
String ssidKey = String("wifi_ssid_") + i;
|
||||
String passKey = String("wifi_pass_") + i;
|
||||
gKnownWifiSsids[i] = gPrefs.getString(ssidKey.c_str(), "");
|
||||
gKnownWifiPasswords[i] = gPrefs.getString(passKey.c_str(), "");
|
||||
}
|
||||
if (!gWifiSavedSsid.isEmpty() && findKnownWifiIndex(gWifiSavedSsid) < 0) {
|
||||
upsertKnownWifi(gWifiSavedSsid, gWifiSavedPassword);
|
||||
}
|
||||
gSolanaRpcUrl = gPrefs.getString("solana_rpc", "https://api.devnet.solana.com");
|
||||
gShineServerUrl = gPrefs.getString("shine_server", "https://shineup.me");
|
||||
gLoginValue = gPrefs.getString("login", "");
|
||||
@ -358,6 +441,17 @@ static void saveWifiPrefs() {
|
||||
gPrefs.putString("wifi_ssid", gWifiSavedSsid);
|
||||
gPrefs.putString("wifi_pass", gWifiSavedPassword);
|
||||
gPrefs.putBool("wifi_known_good", gWifiKnownGood);
|
||||
for (int i = 0; i < MAX_SAVED_WIFI_NETWORKS; ++i) {
|
||||
String ssidKey = String("wifi_ssid_") + i;
|
||||
String passKey = String("wifi_pass_") + i;
|
||||
if (gKnownWifiSsids[i].isEmpty()) {
|
||||
gPrefs.remove(ssidKey.c_str());
|
||||
gPrefs.remove(passKey.c_str());
|
||||
} else {
|
||||
gPrefs.putString(ssidKey.c_str(), gKnownWifiSsids[i]);
|
||||
gPrefs.putString(passKey.c_str(), gKnownWifiPasswords[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void saveServerPrefs() {
|
||||
@ -382,6 +476,7 @@ static void clearWifiPrefs() {
|
||||
gWifiSavedSsid = "";
|
||||
gWifiSavedPassword = "";
|
||||
gWifiSelectedSsid = "";
|
||||
clearSavedWifiList();
|
||||
gWifiKnownGood = false;
|
||||
gWifiReconnectEnabled = false;
|
||||
gWifiDisconnectedSinceMs = 0;
|
||||
@ -418,7 +513,13 @@ static String wifiSavedLabel() {
|
||||
if (gWifiSavedSsid.isEmpty()) {
|
||||
return "Saved: none";
|
||||
}
|
||||
return String("Saved: ") + gWifiSavedSsid;
|
||||
int knownCount = 0;
|
||||
for (int i = 0; i < MAX_SAVED_WIFI_NETWORKS; ++i) {
|
||||
if (!gKnownWifiSsids[i].isEmpty()) {
|
||||
knownCount++;
|
||||
}
|
||||
}
|
||||
return String("Saved: ") + gWifiSavedSsid + " (" + knownCount + ")";
|
||||
}
|
||||
|
||||
static String wifiHomeSummary() {
|
||||
@ -652,6 +753,7 @@ static bool connectWifiNow(const String &ssid, const String &password) {
|
||||
if (WiFi.status() == WL_CONNECTED) {
|
||||
gWifiSavedSsid = ssid;
|
||||
gWifiSavedPassword = password;
|
||||
upsertKnownWifi(ssid, password);
|
||||
gWifiKnownGood = true;
|
||||
gWifiReconnectEnabled = true;
|
||||
gWifiDisconnectedSinceMs = 0;
|
||||
@ -830,7 +932,7 @@ static void networkSelectCb(lv_event_t *event) {
|
||||
SCREEN_WIFI,
|
||||
"ENTER PASSWORD",
|
||||
String("SSID: ") + gWifiSelectedSsid,
|
||||
"",
|
||||
savedPasswordForSsid(gWifiSelectedSsid),
|
||||
true);
|
||||
}
|
||||
|
||||
@ -1276,12 +1378,13 @@ static void drawSecretShowScreen() {
|
||||
if (gSecretConfigured) {
|
||||
showMessageAt("Current secret in base58:", 56);
|
||||
lv_obj_t *label = lv_label_create(gRoot);
|
||||
lv_label_set_text(label, gSecretBase58.c_str());
|
||||
String secretLines = splitFixedWidth(gSecretBase58, 10);
|
||||
lv_label_set_text(label, secretLines.c_str());
|
||||
lv_obj_set_width(label, 420);
|
||||
lv_label_set_long_mode(label, LV_LABEL_LONG_WRAP);
|
||||
lv_obj_set_style_text_font(label, &lv_font_montserrat_16, 0);
|
||||
lv_obj_set_style_text_font(label, &lv_font_montserrat_20, 0);
|
||||
lv_obj_set_style_text_color(label, lv_color_hex(0xD9E1EA), 0);
|
||||
lv_obj_align(label, LV_ALIGN_TOP_MID, 0, 112);
|
||||
lv_obj_align(label, LV_ALIGN_TOP_MID, 0, 102);
|
||||
} else {
|
||||
showMessageAt("Secret not set", 96);
|
||||
}
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
client.version=1.2.150
|
||||
server.version=1.2.142
|
||||
client.version=1.2.151
|
||||
server.version=1.2.143
|
||||
|
||||
Loading…
Reference in New Issue
Block a user