mirror of
https://github.com/daveallie/crosspoint-reader.git
synced 2026-02-04 14:47:37 +03:00
auto connect last wifi
This commit is contained in:
parent
e5c0ddc9fa
commit
0531cee32c
@ -22,7 +22,7 @@ void readAndValidate(FsFile& file, uint8_t& member, const uint8_t maxValue) {
|
|||||||
namespace {
|
namespace {
|
||||||
constexpr uint8_t SETTINGS_FILE_VERSION = 1;
|
constexpr uint8_t SETTINGS_FILE_VERSION = 1;
|
||||||
// Increment this when adding new persisted settings fields
|
// Increment this when adding new persisted settings fields
|
||||||
constexpr uint8_t SETTINGS_COUNT = 23;
|
constexpr uint8_t SETTINGS_COUNT = 24;
|
||||||
constexpr char SETTINGS_FILE[] = "/.crosspoint/settings.bin";
|
constexpr char SETTINGS_FILE[] = "/.crosspoint/settings.bin";
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
@ -60,6 +60,7 @@ bool CrossPointSettings::saveToFile() const {
|
|||||||
serialization::writeString(outputFile, std::string(opdsUsername));
|
serialization::writeString(outputFile, std::string(opdsUsername));
|
||||||
serialization::writeString(outputFile, std::string(opdsPassword));
|
serialization::writeString(outputFile, std::string(opdsPassword));
|
||||||
serialization::writePod(outputFile, sleepScreenCoverFilter);
|
serialization::writePod(outputFile, sleepScreenCoverFilter);
|
||||||
|
serialization::writeString(outputFile, std::string(lastConnectedSSID));
|
||||||
// New fields added at end for backward compatibility
|
// New fields added at end for backward compatibility
|
||||||
outputFile.close();
|
outputFile.close();
|
||||||
|
|
||||||
|
|||||||
@ -137,6 +137,7 @@ class CrossPointSettings {
|
|||||||
uint8_t hideBatteryPercentage = HIDE_NEVER;
|
uint8_t hideBatteryPercentage = HIDE_NEVER;
|
||||||
// Long-press chapter skip on side buttons
|
// Long-press chapter skip on side buttons
|
||||||
uint8_t longPressChapterSkip = 1;
|
uint8_t longPressChapterSkip = 1;
|
||||||
|
char lastConnectedSSID[33] = "";
|
||||||
|
|
||||||
~CrossPointSettings() = default;
|
~CrossPointSettings() = default;
|
||||||
|
|
||||||
|
|||||||
91
src/activities/network/AutoConnectingActivity.cpp
Normal file
91
src/activities/network/AutoConnectingActivity.cpp
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
#include "AutoConnectingActivity.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <WiFi.h>
|
||||||
|
#include <GfxRenderer.h>
|
||||||
|
#include "MappedInputManager.h"
|
||||||
|
#include "fontIds.h"
|
||||||
|
#include "CrossPointSettings.h"
|
||||||
|
#include "WifiCredentialStore.h"
|
||||||
|
|
||||||
|
AutoConnectingActivity::AutoConnectingActivity(
|
||||||
|
GfxRenderer& renderer,
|
||||||
|
MappedInputManager& mappedInput,
|
||||||
|
const std::function<void()>& on_success,
|
||||||
|
const std::function<void()>& on_failure
|
||||||
|
) : Activity("AutoConnecting", renderer, mappedInput),
|
||||||
|
on_success(on_success),
|
||||||
|
on_failure(on_failure) {}
|
||||||
|
|
||||||
|
void AutoConnectingActivity::onEnter() {
|
||||||
|
Activity::onEnter();
|
||||||
|
render();
|
||||||
|
attemptConnection();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AutoConnectingActivity::onExit() {
|
||||||
|
Activity::onExit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AutoConnectingActivity::loop() {
|
||||||
|
if (mappedInput.wasPressed(MappedInputManager::Button::Back)) {
|
||||||
|
WiFi.disconnect();
|
||||||
|
on_failure();
|
||||||
|
} else if (mappedInput.wasPressed(MappedInputManager::Button::Confirm)) { // Skip
|
||||||
|
WiFi.disconnect();
|
||||||
|
on_failure();
|
||||||
|
}
|
||||||
|
checkConnectionStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AutoConnectingActivity::attemptConnection() {
|
||||||
|
connectionStartTime = millis();
|
||||||
|
std::string ssid = SETTINGS.lastConnectedSSID;
|
||||||
|
const auto* cred = WIFI_STORE.findCredential(ssid);
|
||||||
|
if (!cred) {
|
||||||
|
on_failure();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
WiFi.mode(WIFI_STA);
|
||||||
|
WiFi.begin(ssid.c_str(), cred->password.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void AutoConnectingActivity::checkConnectionStatus() {
|
||||||
|
const wl_status_t status = WiFi.status();
|
||||||
|
|
||||||
|
if (status == WL_CONNECTED) {
|
||||||
|
on_success();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status == WL_CONNECT_FAILED || status == WL_NO_SSID_AVAIL) {
|
||||||
|
on_failure();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (millis() - connectionStartTime > CONNECTION_TIMEOUT_MS) {
|
||||||
|
WiFi.disconnect();
|
||||||
|
on_failure();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AutoConnectingActivity::render() const {
|
||||||
|
renderer.clearScreen();
|
||||||
|
const auto pageHeight = renderer.getScreenHeight();
|
||||||
|
const auto height = renderer.getLineHeight(UI_10_FONT_ID);
|
||||||
|
const auto top = (pageHeight - height) / 2;
|
||||||
|
|
||||||
|
renderer.drawCenteredText(UI_12_FONT_ID, top - 40, "Connecting...", true, EpdFontFamily::BOLD);
|
||||||
|
|
||||||
|
std::string ssidInfo = "to " + std::string(SETTINGS.lastConnectedSSID);
|
||||||
|
if (ssidInfo.length() > 25) {
|
||||||
|
ssidInfo.replace(22, ssidInfo.length() - 22, "...");
|
||||||
|
}
|
||||||
|
renderer.drawCenteredText(UI_10_FONT_ID, top, ssidInfo.c_str());
|
||||||
|
|
||||||
|
const auto labels = mappedInput.mapLabels("« Back", "Skip", "", "");
|
||||||
|
renderer.drawButtonHints(UI_10_FONT_ID, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
|
||||||
|
renderer.displayBuffer();
|
||||||
|
}
|
||||||
29
src/activities/network/AutoConnectingActivity.h
Normal file
29
src/activities/network/AutoConnectingActivity.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "activities/Activity.h"
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
class AutoConnectingActivity final : public Activity {
|
||||||
|
public:
|
||||||
|
AutoConnectingActivity(
|
||||||
|
GfxRenderer& renderer,
|
||||||
|
MappedInputManager& mappedInput,
|
||||||
|
const std::function<void()>& on_success,
|
||||||
|
const std::function<void()>& on_failure
|
||||||
|
);
|
||||||
|
|
||||||
|
void onEnter() override;
|
||||||
|
void onExit() override;
|
||||||
|
void loop() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void render() const;
|
||||||
|
void attemptConnection();
|
||||||
|
void checkConnectionStatus();
|
||||||
|
|
||||||
|
const std::function<void()> on_success;
|
||||||
|
const std::function<void()> on_failure;
|
||||||
|
|
||||||
|
unsigned long connectionStartTime = 0;
|
||||||
|
static constexpr unsigned long CONNECTION_TIMEOUT_MS = 15000;
|
||||||
|
};
|
||||||
@ -251,6 +251,11 @@ void WifiSelectionActivity::checkConnectionStatus() {
|
|||||||
snprintf(ipStr, sizeof(ipStr), "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
|
snprintf(ipStr, sizeof(ipStr), "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
|
||||||
connectedIP = ipStr;
|
connectedIP = ipStr;
|
||||||
|
|
||||||
|
// Save the last connected SSID
|
||||||
|
strncpy(SETTINGS.lastConnectedSSID, selectedSSID.c_str(), sizeof(SETTINGS.lastConnectedSSID) - 1);
|
||||||
|
SETTINGS.lastConnectedSSID[sizeof(SETTINGS.lastConnectedSSID) - 1] = '\0';
|
||||||
|
SETTINGS.saveToFile();
|
||||||
|
|
||||||
// If we entered a new password, ask if user wants to save it
|
// If we entered a new password, ask if user wants to save it
|
||||||
// Otherwise, immediately complete so parent can start web server
|
// Otherwise, immediately complete so parent can start web server
|
||||||
if (!usedSavedPassword && !enteredPassword.empty()) {
|
if (!usedSavedPassword && !enteredPassword.empty()) {
|
||||||
@ -311,14 +316,12 @@ void WifiSelectionActivity::loop() {
|
|||||||
|
|
||||||
// Handle save prompt state
|
// Handle save prompt state
|
||||||
if (state == WifiSelectionState::SAVE_PROMPT) {
|
if (state == WifiSelectionState::SAVE_PROMPT) {
|
||||||
if (mappedInput.wasPressed(MappedInputManager::Button::Up) ||
|
if (mappedInput.wasPressed(MappedInputManager::Button::Left)) {
|
||||||
mappedInput.wasPressed(MappedInputManager::Button::Left)) {
|
|
||||||
if (savePromptSelection > 0) {
|
if (savePromptSelection > 0) {
|
||||||
savePromptSelection--;
|
savePromptSelection--;
|
||||||
updateRequired = true;
|
updateRequired = true;
|
||||||
}
|
}
|
||||||
} else if (mappedInput.wasPressed(MappedInputManager::Button::Down) ||
|
} else if (mappedInput.wasPressed(MappedInputManager::Button::Right)) {
|
||||||
mappedInput.wasPressed(MappedInputManager::Button::Right)) {
|
|
||||||
if (savePromptSelection < 1) {
|
if (savePromptSelection < 1) {
|
||||||
savePromptSelection++;
|
savePromptSelection++;
|
||||||
updateRequired = true;
|
updateRequired = true;
|
||||||
@ -341,14 +344,12 @@ void WifiSelectionActivity::loop() {
|
|||||||
|
|
||||||
// Handle forget prompt state (connection failed with saved credentials)
|
// Handle forget prompt state (connection failed with saved credentials)
|
||||||
if (state == WifiSelectionState::FORGET_PROMPT) {
|
if (state == WifiSelectionState::FORGET_PROMPT) {
|
||||||
if (mappedInput.wasPressed(MappedInputManager::Button::Up) ||
|
if (mappedInput.wasPressed(MappedInputManager::Button::Left)) {
|
||||||
mappedInput.wasPressed(MappedInputManager::Button::Left)) {
|
|
||||||
if (forgetPromptSelection > 0) {
|
if (forgetPromptSelection > 0) {
|
||||||
forgetPromptSelection--;
|
forgetPromptSelection--;
|
||||||
updateRequired = true;
|
updateRequired = true;
|
||||||
}
|
}
|
||||||
} else if (mappedInput.wasPressed(MappedInputManager::Button::Down) ||
|
} else if (mappedInput.wasPressed(MappedInputManager::Button::Right)) {
|
||||||
mappedInput.wasPressed(MappedInputManager::Button::Right)) {
|
|
||||||
if (forgetPromptSelection < 1) {
|
if (forgetPromptSelection < 1) {
|
||||||
forgetPromptSelection++;
|
forgetPromptSelection++;
|
||||||
updateRequired = true;
|
updateRequired = true;
|
||||||
@ -420,18 +421,23 @@ void WifiSelectionActivity::loop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handle UP/DOWN navigation
|
// Handle UP/DOWN navigation
|
||||||
if (mappedInput.wasPressed(MappedInputManager::Button::Up) ||
|
if (mappedInput.wasPressed(MappedInputManager::Button::Up)) {
|
||||||
mappedInput.wasPressed(MappedInputManager::Button::Left)) {
|
|
||||||
if (selectedNetworkIndex > 0) {
|
if (selectedNetworkIndex > 0) {
|
||||||
selectedNetworkIndex--;
|
selectedNetworkIndex--;
|
||||||
updateRequired = true;
|
updateRequired = true;
|
||||||
}
|
}
|
||||||
} else if (mappedInput.wasPressed(MappedInputManager::Button::Down) ||
|
} else if (mappedInput.wasPressed(MappedInputManager::Button::Down)) {
|
||||||
mappedInput.wasPressed(MappedInputManager::Button::Right)) {
|
|
||||||
if (!networks.empty() && selectedNetworkIndex < static_cast<int>(networks.size()) - 1) {
|
if (!networks.empty() && selectedNetworkIndex < static_cast<int>(networks.size()) - 1) {
|
||||||
selectedNetworkIndex++;
|
selectedNetworkIndex++;
|
||||||
updateRequired = true;
|
updateRequired = true;
|
||||||
}
|
}
|
||||||
|
} else if (mappedInput.wasPressed(MappedInputManager::Button::Left)) {
|
||||||
|
if (!networks.empty() && networks[selectedNetworkIndex].hasSavedPassword) {
|
||||||
|
selectedSSID = networks[selectedNetworkIndex].ssid;
|
||||||
|
state = WifiSelectionState::FORGET_PROMPT;
|
||||||
|
forgetPromptSelection = 0; // Default to "Cancel"
|
||||||
|
updateRequired = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -585,7 +591,7 @@ void WifiSelectionActivity::renderNetworkList() const {
|
|||||||
|
|
||||||
// Draw help text
|
// Draw help text
|
||||||
renderer.drawText(SMALL_FONT_ID, 20, pageHeight - 75, "* = Encrypted | + = Saved");
|
renderer.drawText(SMALL_FONT_ID, 20, pageHeight - 75, "* = Encrypted | + = Saved");
|
||||||
const auto labels = mappedInput.mapLabels("« Back", "Connect", "", "");
|
const auto labels = mappedInput.mapLabels("« Back", "Connect", "Forget", "");
|
||||||
renderer.drawButtonHints(UI_10_FONT_ID, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
|
renderer.drawButtonHints(UI_10_FONT_ID, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -689,7 +695,7 @@ void WifiSelectionActivity::renderForgetPrompt() const {
|
|||||||
const auto height = renderer.getLineHeight(UI_10_FONT_ID);
|
const auto height = renderer.getLineHeight(UI_10_FONT_ID);
|
||||||
const auto top = (pageHeight - height * 3) / 2;
|
const auto top = (pageHeight - height * 3) / 2;
|
||||||
|
|
||||||
renderer.drawCenteredText(UI_12_FONT_ID, top - 40, "Connection Failed", true, EpdFontFamily::BOLD);
|
renderer.drawCenteredText(UI_12_FONT_ID, top - 40, "Forget Network", true, EpdFontFamily::BOLD);
|
||||||
|
|
||||||
std::string ssidInfo = "Network: " + selectedSSID;
|
std::string ssidInfo = "Network: " + selectedSSID;
|
||||||
if (ssidInfo.length() > 28) {
|
if (ssidInfo.length() > 28) {
|
||||||
|
|||||||
@ -11,6 +11,7 @@
|
|||||||
#include "KOReaderSettingsActivity.h"
|
#include "KOReaderSettingsActivity.h"
|
||||||
#include "MappedInputManager.h"
|
#include "MappedInputManager.h"
|
||||||
#include "OtaUpdateActivity.h"
|
#include "OtaUpdateActivity.h"
|
||||||
|
#include "WifiSelectionActivity.h"
|
||||||
#include "fontIds.h"
|
#include "fontIds.h"
|
||||||
|
|
||||||
void CategorySettingsActivity::taskTrampoline(void* param) {
|
void CategorySettingsActivity::taskTrampoline(void* param) {
|
||||||
@ -95,7 +96,15 @@ void CategorySettingsActivity::toggleCurrentSetting() {
|
|||||||
SETTINGS.*(setting.valuePtr) = currentValue + setting.valueRange.step;
|
SETTINGS.*(setting.valuePtr) = currentValue + setting.valueRange.step;
|
||||||
}
|
}
|
||||||
} else if (setting.type == SettingType::ACTION) {
|
} else if (setting.type == SettingType::ACTION) {
|
||||||
if (strcmp(setting.name, "KOReader Sync") == 0) {
|
if (strcmp(setting.name, "Network") == 0) {
|
||||||
|
xSemaphoreTake(renderingMutex, portMAX_DELAY);
|
||||||
|
exitActivity();
|
||||||
|
enterNewActivity(new WifiSelectionActivity(renderer, mappedInput, [this] {
|
||||||
|
exitActivity();
|
||||||
|
updateRequired = true;
|
||||||
|
}));
|
||||||
|
xSemaphoreGive(renderingMutex);
|
||||||
|
} else if (strcmp(setting.name, "KOReader Sync") == 0) {
|
||||||
xSemaphoreTake(renderingMutex, portMAX_DELAY);
|
xSemaphoreTake(renderingMutex, portMAX_DELAY);
|
||||||
exitActivity();
|
exitActivity();
|
||||||
enterNewActivity(new KOReaderSettingsActivity(renderer, mappedInput, [this] {
|
enterNewActivity(new KOReaderSettingsActivity(renderer, mappedInput, [this] {
|
||||||
|
|||||||
@ -48,10 +48,11 @@ const SettingInfo controlsSettings[controlsSettingsCount] = {
|
|||||||
SettingInfo::Toggle("Long-press Chapter Skip", &CrossPointSettings::longPressChapterSkip),
|
SettingInfo::Toggle("Long-press Chapter Skip", &CrossPointSettings::longPressChapterSkip),
|
||||||
SettingInfo::Enum("Short Power Button Click", &CrossPointSettings::shortPwrBtn, {"Ignore", "Sleep", "Page Turn"})};
|
SettingInfo::Enum("Short Power Button Click", &CrossPointSettings::shortPwrBtn, {"Ignore", "Sleep", "Page Turn"})};
|
||||||
|
|
||||||
constexpr int systemSettingsCount = 5;
|
constexpr int systemSettingsCount = 6;
|
||||||
const SettingInfo systemSettings[systemSettingsCount] = {
|
const SettingInfo systemSettings[systemSettingsCount] = {
|
||||||
SettingInfo::Enum("Time to Sleep", &CrossPointSettings::sleepTimeout,
|
SettingInfo::Enum("Time to Sleep", &CrossPointSettings::sleepTimeout,
|
||||||
{"1 min", "5 min", "10 min", "15 min", "30 min"}),
|
{"1 min", "5 min", "10 min", "15 min", "30 min"}),
|
||||||
|
SettingInfo::Action("Network"),
|
||||||
SettingInfo::Action("KOReader Sync"), SettingInfo::Action("OPDS Browser"), SettingInfo::Action("Clear Cache"),
|
SettingInfo::Action("KOReader Sync"), SettingInfo::Action("OPDS Browser"), SettingInfo::Action("Clear Cache"),
|
||||||
SettingInfo::Action("Check for updates")};
|
SettingInfo::Action("Check for updates")};
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|||||||
42
src/main.cpp
42
src/main.cpp
@ -24,7 +24,10 @@
|
|||||||
#include "activities/reader/ReaderActivity.h"
|
#include "activities/reader/ReaderActivity.h"
|
||||||
#include "activities/settings/SettingsActivity.h"
|
#include "activities/settings/SettingsActivity.h"
|
||||||
#include "activities/util/FullScreenMessageActivity.h"
|
#include "activities/util/FullScreenMessageActivity.h"
|
||||||
|
#include "activities/network/AutoConnectingActivity.h"
|
||||||
|
#include "activities/network/WifiSelectionActivity.h"
|
||||||
#include "fontIds.h"
|
#include "fontIds.h"
|
||||||
|
#include <WiFi.h>
|
||||||
|
|
||||||
HalDisplay display;
|
HalDisplay display;
|
||||||
HalGPIO gpio;
|
HalGPIO gpio;
|
||||||
@ -211,9 +214,38 @@ void onGoToReader(const std::string& initialEpubPath, MyLibraryActivity::Tab fro
|
|||||||
}
|
}
|
||||||
void onContinueReading() { onGoToReader(APP_STATE.openEpubPath, MyLibraryActivity::Tab::Recent); }
|
void onContinueReading() { onGoToReader(APP_STATE.openEpubPath, MyLibraryActivity::Tab::Recent); }
|
||||||
|
|
||||||
|
void onGoHome(); // forward declaration
|
||||||
|
|
||||||
|
void withWifi(std::function<void()> on_success) {
|
||||||
|
if (WiFi.isConnected()) {
|
||||||
|
on_success();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto on_failure = [on_success]() {
|
||||||
|
exitActivity();
|
||||||
|
enterNewActivity(new WifiSelectionActivity(renderer, mappedInputManager, [on_success](bool connected) {
|
||||||
|
if (connected) {
|
||||||
|
on_success();
|
||||||
|
} else {
|
||||||
|
onGoHome();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
if (strlen(SETTINGS.lastConnectedSSID) > 0) {
|
||||||
|
exitActivity();
|
||||||
|
enterNewActivity(new AutoConnectingActivity(renderer, mappedInputManager, on_success, on_failure));
|
||||||
|
} else {
|
||||||
|
on_failure();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void onGoToFileTransfer() {
|
void onGoToFileTransfer() {
|
||||||
exitActivity();
|
withWifi([]() {
|
||||||
enterNewActivity(new CrossPointWebServerActivity(renderer, mappedInputManager, onGoHome));
|
exitActivity();
|
||||||
|
enterNewActivity(new CrossPointWebServerActivity(renderer, mappedInputManager, onGoHome));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void onGoToSettings() {
|
void onGoToSettings() {
|
||||||
@ -232,8 +264,10 @@ void onGoToMyLibraryWithTab(const std::string& path, MyLibraryActivity::Tab tab)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void onGoToBrowser() {
|
void onGoToBrowser() {
|
||||||
exitActivity();
|
withWifi([]() {
|
||||||
enterNewActivity(new OpdsBookBrowserActivity(renderer, mappedInputManager, onGoHome));
|
exitActivity();
|
||||||
|
enterNewActivity(new OpdsBookBrowserActivity(renderer, mappedInputManager, onGoHome));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void onGoHome() {
|
void onGoHome() {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user