Network details QR code (#113)
Using QRCode library from pio to generate the QR code. Done: - Display QR code for URL in network mode - minor fixes of layout - Display QR for URL in AP mode - Display QR for AP in AP mode --------- Co-authored-by: Dave Allie <dave@daveallie.com>
This commit is contained in:
parent
b77af16caa
commit
e8c0fb42d4
6
.github/workflows/ci.yml
vendored
6
.github/workflows/ci.yml
vendored
@ -12,12 +12,6 @@ jobs:
|
|||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
- uses: actions/cache@v5
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
~/.cache/pip
|
|
||||||
~/.platformio/.cache
|
|
||||||
key: ${{ runner.os }}-pio
|
|
||||||
- uses: actions/setup-python@v6
|
- uses: actions/setup-python@v6
|
||||||
with:
|
with:
|
||||||
python-version: '3.14'
|
python-version: '3.14'
|
||||||
|
|||||||
@ -40,6 +40,7 @@ lib_deps =
|
|||||||
InputManager=symlink://open-x4-sdk/libs/hardware/InputManager
|
InputManager=symlink://open-x4-sdk/libs/hardware/InputManager
|
||||||
EInkDisplay=symlink://open-x4-sdk/libs/display/EInkDisplay
|
EInkDisplay=symlink://open-x4-sdk/libs/display/EInkDisplay
|
||||||
ArduinoJson @ 7.4.2
|
ArduinoJson @ 7.4.2
|
||||||
|
QRCode @ 0.0.1
|
||||||
|
|
||||||
[env:default]
|
[env:default]
|
||||||
extends = base
|
extends = base
|
||||||
|
|||||||
@ -4,8 +4,12 @@
|
|||||||
#include <ESPmDNS.h>
|
#include <ESPmDNS.h>
|
||||||
#include <GfxRenderer.h>
|
#include <GfxRenderer.h>
|
||||||
#include <InputManager.h>
|
#include <InputManager.h>
|
||||||
|
#include <QrCode.h>
|
||||||
#include <WiFi.h>
|
#include <WiFi.h>
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
#include "NetworkModeSelectionActivity.h"
|
#include "NetworkModeSelectionActivity.h"
|
||||||
#include "WifiSelectionActivity.h"
|
#include "WifiSelectionActivity.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
@ -336,6 +340,28 @@ void CrossPointWebServerActivity::render() const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void drawQRCode(const GfxRenderer& renderer, const int x, const int y, const std::string& data) {
|
||||||
|
// Implementation of QR code calculation
|
||||||
|
// The structure to manage the QR code
|
||||||
|
QRCode qrcode;
|
||||||
|
uint8_t qrcodeBytes[qrcode_getBufferSize(4)];
|
||||||
|
Serial.printf("[%lu] [WEBACT] QR Code (%lu): %s\n", millis(), data.length(), data.c_str());
|
||||||
|
|
||||||
|
qrcode_initText(&qrcode, qrcodeBytes, 4, ECC_LOW, data.c_str());
|
||||||
|
const uint8_t px = 6; // pixels per module
|
||||||
|
for (uint8_t cy = 0; cy < qrcode.size; cy++) {
|
||||||
|
for (uint8_t cx = 0; cx < qrcode.size; cx++) {
|
||||||
|
if (qrcode_getModule(&qrcode, cx, cy)) {
|
||||||
|
// Serial.print("**");
|
||||||
|
renderer.fillRect(x + px * cx, y + px * cy, px, px, true);
|
||||||
|
} else {
|
||||||
|
// Serial.print(" ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Serial.print("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CrossPointWebServerActivity::renderServerRunning() const {
|
void CrossPointWebServerActivity::renderServerRunning() const {
|
||||||
// Use consistent line spacing
|
// Use consistent line spacing
|
||||||
constexpr int LINE_SPACING = 28; // Space between lines
|
constexpr int LINE_SPACING = 28; // Space between lines
|
||||||
@ -344,7 +370,7 @@ void CrossPointWebServerActivity::renderServerRunning() const {
|
|||||||
|
|
||||||
if (isApMode) {
|
if (isApMode) {
|
||||||
// AP mode display - center the content block
|
// AP mode display - center the content block
|
||||||
const int startY = 55;
|
int startY = 55;
|
||||||
|
|
||||||
renderer.drawCenteredText(UI_FONT_ID, startY, "Hotspot Mode", true, BOLD);
|
renderer.drawCenteredText(UI_FONT_ID, startY, "Hotspot Mode", true, BOLD);
|
||||||
|
|
||||||
@ -354,6 +380,13 @@ void CrossPointWebServerActivity::renderServerRunning() const {
|
|||||||
renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING * 2, "Connect your device to this WiFi network",
|
renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING * 2, "Connect your device to this WiFi network",
|
||||||
true, REGULAR);
|
true, REGULAR);
|
||||||
|
|
||||||
|
renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING * 3,
|
||||||
|
"or scan QR code with your phone to connect to Wifi.", true, REGULAR);
|
||||||
|
// Show QR code for URL
|
||||||
|
std::string wifiConfig = std::string("WIFI:T:WPA;S:") + connectedSSID + ";P:" + "" + ";;";
|
||||||
|
drawQRCode(renderer, (480 - 6 * 33) / 2, startY + LINE_SPACING * 4, wifiConfig);
|
||||||
|
|
||||||
|
startY += 6 * 29 + 3 * LINE_SPACING;
|
||||||
// Show primary URL (hostname)
|
// Show primary URL (hostname)
|
||||||
std::string hostnameUrl = std::string("http://") + AP_HOSTNAME + ".local/";
|
std::string hostnameUrl = std::string("http://") + AP_HOSTNAME + ".local/";
|
||||||
renderer.drawCenteredText(UI_FONT_ID, startY + LINE_SPACING * 3, hostnameUrl.c_str(), true, BOLD);
|
renderer.drawCenteredText(UI_FONT_ID, startY + LINE_SPACING * 3, hostnameUrl.c_str(), true, BOLD);
|
||||||
@ -361,8 +394,12 @@ void CrossPointWebServerActivity::renderServerRunning() const {
|
|||||||
// Show IP address as fallback
|
// Show IP address as fallback
|
||||||
std::string ipUrl = "or http://" + connectedIP + "/";
|
std::string ipUrl = "or http://" + connectedIP + "/";
|
||||||
renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING * 4, ipUrl.c_str(), true, REGULAR);
|
renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING * 4, ipUrl.c_str(), true, REGULAR);
|
||||||
|
|
||||||
renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING * 5, "Open this URL in your browser", true, REGULAR);
|
renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING * 5, "Open this URL in your browser", true, REGULAR);
|
||||||
|
|
||||||
|
// Show QR code for URL
|
||||||
|
renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING * 6, "or scan QR code with your phone:", true,
|
||||||
|
REGULAR);
|
||||||
|
drawQRCode(renderer, (480 - 6 * 33) / 2, startY + LINE_SPACING * 7, hostnameUrl);
|
||||||
} else {
|
} else {
|
||||||
// STA mode display (original behavior)
|
// STA mode display (original behavior)
|
||||||
const int startY = 65;
|
const int startY = 65;
|
||||||
@ -385,6 +422,11 @@ void CrossPointWebServerActivity::renderServerRunning() const {
|
|||||||
renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING * 3, hostnameUrl.c_str(), true, REGULAR);
|
renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING * 3, hostnameUrl.c_str(), true, REGULAR);
|
||||||
|
|
||||||
renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING * 4, "Open this URL in your browser", true, REGULAR);
|
renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING * 4, "Open this URL in your browser", true, REGULAR);
|
||||||
|
|
||||||
|
// Show QR code for URL
|
||||||
|
drawQRCode(renderer, (480 - 6 * 33) / 2, startY + LINE_SPACING * 6, webInfo);
|
||||||
|
renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING * 5, "or scan QR code with your phone:", true,
|
||||||
|
REGULAR);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderer.drawButtonHints(UI_FONT_ID, "« Exit", "", "", "");
|
renderer.drawButtonHints(UI_FONT_ID, "« Exit", "", "", "");
|
||||||
|
|||||||
@ -150,6 +150,11 @@ void WifiSelectionActivity::processWifiScanResults() {
|
|||||||
std::sort(networks.begin(), networks.end(),
|
std::sort(networks.begin(), networks.end(),
|
||||||
[](const WifiNetworkInfo& a, const WifiNetworkInfo& b) { return a.rssi > b.rssi; });
|
[](const WifiNetworkInfo& a, const WifiNetworkInfo& b) { return a.rssi > b.rssi; });
|
||||||
|
|
||||||
|
// Show networks with PW first
|
||||||
|
std::sort(networks.begin(), networks.end(), [](const WifiNetworkInfo& a, const WifiNetworkInfo& b) {
|
||||||
|
return a.hasSavedPassword && !b.hasSavedPassword;
|
||||||
|
});
|
||||||
|
|
||||||
WiFi.scanDelete();
|
WiFi.scanDelete();
|
||||||
state = WifiSelectionState::NETWORK_LIST;
|
state = WifiSelectionState::NETWORK_LIST;
|
||||||
selectedNetworkIndex = 0;
|
selectedNetworkIndex = 0;
|
||||||
@ -581,7 +586,7 @@ void WifiSelectionActivity::renderConnecting() const {
|
|||||||
if (state == WifiSelectionState::SCANNING) {
|
if (state == WifiSelectionState::SCANNING) {
|
||||||
renderer.drawCenteredText(UI_FONT_ID, top, "Scanning...", true, REGULAR);
|
renderer.drawCenteredText(UI_FONT_ID, top, "Scanning...", true, REGULAR);
|
||||||
} else {
|
} else {
|
||||||
renderer.drawCenteredText(READER_FONT_ID, top - 30, "Connecting...", true, BOLD);
|
renderer.drawCenteredText(READER_FONT_ID, top - 40, "Connecting...", true, BOLD);
|
||||||
|
|
||||||
std::string ssidInfo = "to " + selectedSSID;
|
std::string ssidInfo = "to " + selectedSSID;
|
||||||
if (ssidInfo.length() > 25) {
|
if (ssidInfo.length() > 25) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user