Merge pull request #276 from bobbycar-graz/ap-qr
This commit is contained in:
@ -1,39 +1 @@
|
||||
#include "qraction.h"
|
||||
|
||||
#include <actioninterface.h>
|
||||
#include <string>
|
||||
#include <screenmanager.h>
|
||||
#include "displays/qrdisplay.h"
|
||||
#include "displays/qrimportdisplay.h"
|
||||
|
||||
using namespace espgui;
|
||||
|
||||
SwitchQrDisplayAction::SwitchQrDisplayAction(const qraction::QrMenu &qrmenu) :
|
||||
m_msg{qrmenu.message}
|
||||
{
|
||||
}
|
||||
|
||||
SwitchQrDisplayAction::SwitchQrDisplayAction(qraction::QrMenu &&qrmenu) :
|
||||
m_msg{std::move(qrmenu.message)}
|
||||
{
|
||||
}
|
||||
|
||||
void SwitchQrDisplayAction::triggered()
|
||||
{
|
||||
switchScreen<QrDisplay>(m_msg);
|
||||
}
|
||||
|
||||
SwitchQrImportDisplayAction::SwitchQrImportDisplayAction(const std::string &nvskey) :
|
||||
m_nvskey{nvskey}
|
||||
{
|
||||
}
|
||||
|
||||
SwitchQrImportDisplayAction::SwitchQrImportDisplayAction(std::string &&nvskey) :
|
||||
m_nvskey{std::move(nvskey)}
|
||||
{
|
||||
}
|
||||
|
||||
void SwitchQrImportDisplayAction::triggered()
|
||||
{
|
||||
switchScreen<QrImportDisplay>(std::move(m_nvskey));
|
||||
}
|
||||
|
@ -1,9 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <actioninterface.h>
|
||||
// system includes
|
||||
#include <string>
|
||||
|
||||
// 3rdparty lib includes
|
||||
#include <actioninterface.h>
|
||||
|
||||
// local includes
|
||||
#include "actions/qraction.h"
|
||||
#include "displays/qrdisplay.h"
|
||||
#include "displays/qrimportdisplay.h"
|
||||
|
||||
namespace qraction {
|
||||
struct QrMenu {
|
||||
@ -12,24 +18,32 @@ struct QrMenu {
|
||||
};
|
||||
} // namespace
|
||||
|
||||
template<typename TMenu>
|
||||
class SwitchQrDisplayAction : public virtual espgui::ActionInterface
|
||||
{
|
||||
public:
|
||||
explicit SwitchQrDisplayAction(const qraction::QrMenu &qrmenu);
|
||||
explicit SwitchQrDisplayAction(qraction::QrMenu &&qrmenu);
|
||||
explicit SwitchQrDisplayAction(const qraction::QrMenu &qrmenu) : m_msg{qrmenu.message} {}
|
||||
explicit SwitchQrDisplayAction(qraction::QrMenu &&qrmenu) : m_msg{std::move(qrmenu.message)} {}
|
||||
|
||||
void triggered() override;
|
||||
void triggered() override
|
||||
{
|
||||
espgui::switchScreen<QrDisplay<TMenu>>(m_msg);
|
||||
}
|
||||
private:
|
||||
std::string m_msg;
|
||||
};
|
||||
|
||||
template<typename TMenu>
|
||||
class SwitchQrImportDisplayAction : public virtual espgui::ActionInterface
|
||||
{
|
||||
public:
|
||||
explicit SwitchQrImportDisplayAction(const std::string &nvskey);
|
||||
explicit SwitchQrImportDisplayAction(std::string &&nvskey);
|
||||
explicit SwitchQrImportDisplayAction(const std::string &nvskey) : m_nvskey{nvskey} {}
|
||||
explicit SwitchQrImportDisplayAction(std::string &&nvskey) : m_nvskey{std::move(nvskey)} {}
|
||||
|
||||
void triggered() override;
|
||||
void triggered() override
|
||||
{
|
||||
espgui::switchScreen<QrImportDisplay<TMenu>>(std::move(m_nvskey));
|
||||
}
|
||||
private:
|
||||
std::string m_nvskey;
|
||||
};
|
||||
|
@ -53,7 +53,7 @@ public:
|
||||
}
|
||||
else
|
||||
{
|
||||
espgui::switchScreen<QrDisplay>(m_qrmenu.message);
|
||||
espgui::switchScreen<QrDisplay<GreenPassMenu>>(m_qrmenu.message);
|
||||
}
|
||||
}
|
||||
private:
|
||||
@ -84,7 +84,7 @@ GreenPassMenu::GreenPassMenu()
|
||||
}
|
||||
else
|
||||
{
|
||||
constructMenuItem<makeComponentArgs<MenuItem, SwitchQrImportDisplayAction, StaticText<TEXT_ADDCERT>>>(std::move(nvs_key));
|
||||
constructMenuItem<makeComponentArgs<MenuItem, SwitchQrImportDisplayAction<GreenPassMenu>, StaticText<TEXT_ADDCERT>>>(std::move(nvs_key));
|
||||
}
|
||||
}
|
||||
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_DELCERT>, BobbyCheckbox, DeleteModeAccessor>>();
|
||||
|
@ -1,24 +1,27 @@
|
||||
#include "networksettingsmenu.h"
|
||||
|
||||
// 3rdparty lib includes
|
||||
#include <menuitem.h>
|
||||
#include <actions/dummyaction.h>
|
||||
#include <actions/switchscreenaction.h>
|
||||
#include <icons/back.h>
|
||||
#include <screenmanager.h>
|
||||
#include <fmt/format.h>
|
||||
#include <icons/back.h>
|
||||
#include <menuitem.h>
|
||||
#include <screenmanager.h>
|
||||
|
||||
// local includes
|
||||
#include "wifistasettingsmenu.h"
|
||||
#include "wifiapsettingsmenu.h"
|
||||
#include "displays/qrdisplay.h"
|
||||
#include "globals.h"
|
||||
#include "settingsmenu.h"
|
||||
#include "texthelpers/networktexthelpers.h"
|
||||
#include "wifiapsettingsmenu.h"
|
||||
#include "wifistasettingsmenu.h"
|
||||
|
||||
using namespace espgui;
|
||||
|
||||
namespace {
|
||||
constexpr char TEXT_STASETTINGS[] = "STA Settings";
|
||||
constexpr char TEXT_APSETTINGS[] = "AP Settings";
|
||||
constexpr char TEXT_APQRCODE[] = "AP QR Code";
|
||||
constexpr char TEXT_BACK[] = "Back";
|
||||
} // namespace
|
||||
|
||||
@ -26,6 +29,8 @@ NetworkSettingsMenu::NetworkSettingsMenu()
|
||||
{
|
||||
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_STASETTINGS>, SwitchScreenAction<WifiStaSettingsMenu>>>();
|
||||
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_APSETTINGS>, SwitchScreenAction<WifiApSettingsMenu>>>();
|
||||
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_APQRCODE>, NetworkAccessPointQRAction>>();
|
||||
|
||||
constructMenuItem<makeComponent<MenuItem, WifiDefaultMacText, DummyAction>>();
|
||||
constructMenuItem<makeComponent<MenuItem, WifiBaseMacText, DummyAction>>();
|
||||
constructMenuItem<makeComponentArgs<MenuItem, DnsText, DummyAction>>(uint8_t{0});
|
||||
@ -44,3 +49,9 @@ void NetworkSettingsMenu::back()
|
||||
{
|
||||
switchScreen<SettingsMenu>();
|
||||
}
|
||||
|
||||
void NetworkAccessPointQRAction::triggered()
|
||||
{
|
||||
std::string qr = fmt::format("WIFI:T:WPA;S:{};P:{};H:;", configs.wifiApName.value, configs.wifiApKey.value);
|
||||
espgui::switchScreen<QrDisplay<NetworkSettingsMenu>>(qr);
|
||||
}
|
||||
|
@ -11,3 +11,9 @@ public:
|
||||
std::string text() const override;
|
||||
void back() override;
|
||||
};
|
||||
|
||||
class NetworkAccessPointQRAction : public virtual espgui::ActionInterface
|
||||
{
|
||||
public:
|
||||
void triggered() override;
|
||||
};
|
||||
|
@ -1,19 +1,5 @@
|
||||
#include "qrdisplay.h"
|
||||
|
||||
// 3rd party libs
|
||||
#include <tftinstance.h>
|
||||
#include <screenmanager.h>
|
||||
|
||||
// local includes
|
||||
#include "displays/menus/greenpassmenu.h"
|
||||
|
||||
using namespace espgui;
|
||||
|
||||
QrDisplay::QrDisplay(std::string_view msg) :
|
||||
m_msg{msg}
|
||||
{
|
||||
}
|
||||
|
||||
uint16_t get_qrver_from_strlen(std::string_view str)
|
||||
{
|
||||
// alpha numeric, ECC Level M
|
||||
@ -100,42 +86,3 @@ uint16_t get_qrver_from_strlen(std::string_view str)
|
||||
else
|
||||
return 40;
|
||||
}
|
||||
|
||||
void QrDisplay::initScreen()
|
||||
{
|
||||
QRCode qrcode;
|
||||
const auto ver = get_qrver_from_strlen(m_msg);
|
||||
uint8_t qrcodeBytes[qrcode_getBufferSize(ver)];
|
||||
qrcode_initText(&qrcode, qrcodeBytes, ver, ECC_MEDIUM, m_msg.data());
|
||||
|
||||
const uint8_t multiplier = (tft.width() - 9) / qrcode.size;
|
||||
const uint8_t x_offset = (tft.width() - qrcode.size * multiplier) / 2;
|
||||
const uint8_t y_offset = (tft.height() - qrcode.size * multiplier) / 2;
|
||||
|
||||
tft.fillScreen(TFT_WHITE);
|
||||
|
||||
for (uint8_t y = 0; y < qrcode.size; y++) {
|
||||
for (uint8_t x = 0; x < qrcode.size; x++) {
|
||||
if (qrcode_getModule(&qrcode, x, y))
|
||||
{
|
||||
tft.fillRect(x*multiplier+x_offset,y*multiplier+y_offset, multiplier, multiplier, TFT_BLACK);
|
||||
} else {
|
||||
tft.fillRect(x*multiplier+x_offset,y*multiplier+y_offset, multiplier, multiplier, TFT_WHITE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QrDisplay::buttonPressed(espgui::Button button)
|
||||
{
|
||||
Base::buttonPressed(button);
|
||||
|
||||
switch (button)
|
||||
{
|
||||
case espgui::Button::Left:
|
||||
case espgui::Button::Right:
|
||||
switchScreen<GreenPassMenu>();
|
||||
break;
|
||||
default:;
|
||||
}
|
||||
}
|
||||
|
@ -1,23 +1,63 @@
|
||||
#pragma once
|
||||
|
||||
// 3rd party includes
|
||||
#include <tftinstance.h>
|
||||
#include <qrcode.h>
|
||||
|
||||
// local includes
|
||||
#include "bobbydisplay.h"
|
||||
#include "screenmanager.h"
|
||||
|
||||
uint16_t get_qrver_from_strlen(std::string_view str);
|
||||
|
||||
template<typename TMenu>
|
||||
class QrDisplay : public BobbyDisplay
|
||||
{
|
||||
using Base = BobbyDisplay;
|
||||
|
||||
public:
|
||||
explicit QrDisplay(std::string_view msg);
|
||||
explicit QrDisplay(std::string_view msg) : m_msg{msg} {}
|
||||
|
||||
void initScreen() override;
|
||||
void initScreen() override
|
||||
{
|
||||
using namespace espgui;
|
||||
QRCode qrcode;
|
||||
const auto ver = get_qrver_from_strlen(m_msg);
|
||||
uint8_t qrcodeBytes[qrcode_getBufferSize(ver)];
|
||||
qrcode_initText(&qrcode, qrcodeBytes, ver, ECC_MEDIUM, m_msg.data());
|
||||
|
||||
void buttonPressed(espgui::Button button) override;
|
||||
const uint8_t multiplier = (tft.width() - 9) / qrcode.size;
|
||||
const uint8_t x_offset = (tft.width() - qrcode.size * multiplier) / 2;
|
||||
const uint8_t y_offset = (tft.height() - qrcode.size * multiplier) / 2;
|
||||
|
||||
tft.fillScreen(TFT_WHITE);
|
||||
|
||||
for (uint8_t y = 0; y < qrcode.size; y++) {
|
||||
for (uint8_t x = 0; x < qrcode.size; x++) {
|
||||
if (qrcode_getModule(&qrcode, x, y))
|
||||
{
|
||||
tft.fillRect(x*multiplier+x_offset,y*multiplier+y_offset, multiplier, multiplier, TFT_BLACK);
|
||||
} else {
|
||||
tft.fillRect(x*multiplier+x_offset,y*multiplier+y_offset, multiplier, multiplier, TFT_WHITE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void buttonPressed(espgui::Button button) override
|
||||
{
|
||||
using namespace espgui;
|
||||
Base::buttonPressed(button);
|
||||
|
||||
switch (button)
|
||||
{
|
||||
case espgui::Button::Left:
|
||||
case espgui::Button::Right:
|
||||
switchScreen<TMenu>();
|
||||
break;
|
||||
default:;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::string_view m_msg;
|
||||
|
@ -1,109 +0,0 @@
|
||||
constexpr const char * const TAG = "qrimport";
|
||||
#include "qrimportdisplay.h"
|
||||
|
||||
// 3rd party includes
|
||||
#include <screenmanager.h>
|
||||
#include <fmt/format.h>
|
||||
#include <esp_log.h>
|
||||
|
||||
// displays/menus includes
|
||||
#include "displays/menus/greenpassmenu.h"
|
||||
#include "bobbyerrorhandler.h"
|
||||
|
||||
// local includes
|
||||
#include "qrimport.h"
|
||||
|
||||
using namespace espgui;
|
||||
|
||||
QrImportDisplay::QrImportDisplay(const std::string &nvs_key) :
|
||||
m_nvs_key{nvs_key}
|
||||
{
|
||||
}
|
||||
|
||||
QrImportDisplay::QrImportDisplay(std::string &&nvs_key) :
|
||||
m_nvs_key{std::move(nvs_key)}
|
||||
{
|
||||
}
|
||||
|
||||
void QrImportDisplay::start()
|
||||
{
|
||||
Base::start();
|
||||
|
||||
m_statuslabel.start();
|
||||
|
||||
qrimport::setup_request();
|
||||
|
||||
if (const auto result = qrimport::start_qr_request(); result)
|
||||
{
|
||||
ESP_LOGI(TAG, "started request, waiting for result");
|
||||
m_waitingForResult = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGE(TAG, "could not start request: %.*s", result.error().size(), result.error().data());
|
||||
m_result = tl::make_unexpected(std::move(result).error());
|
||||
}
|
||||
}
|
||||
|
||||
void QrImportDisplay::update()
|
||||
{
|
||||
Base::update();
|
||||
|
||||
if (!m_waitingForResult)
|
||||
return;
|
||||
|
||||
if (qrimport::get_request_running())
|
||||
return;
|
||||
|
||||
m_waitingForResult = false;
|
||||
|
||||
m_result = qrimport::check_request();
|
||||
if (m_result)
|
||||
{
|
||||
ESP_LOGI(TAG, "%.*s => %.*s", m_nvs_key.size(), m_nvs_key.data(), m_result->size(), m_result->data());
|
||||
if (const auto result = qrimport::set_qr_code(m_nvs_key, *m_result); !result)
|
||||
m_result = tl::make_unexpected(fmt::format("saving qr failed: {}", esp_err_to_name(result.error())));
|
||||
}
|
||||
else
|
||||
ESP_LOGW(TAG, "failed %.*s => %.*s", m_nvs_key.size(), m_nvs_key.data(), m_result.error().size(), m_result.error().data());
|
||||
}
|
||||
|
||||
void QrImportDisplay::redraw()
|
||||
{
|
||||
Base::redraw();
|
||||
|
||||
if (m_waitingForResult)
|
||||
{
|
||||
tft.setTextColor(TFT_YELLOW, TFT_BLACK);
|
||||
m_statuslabel.redraw("In progress");
|
||||
}
|
||||
else if (!m_result && !m_result.error().empty())
|
||||
{
|
||||
tft.setTextColor(TFT_RED, TFT_BLACK);
|
||||
BobbyErrorHandler{}.errorOccured(fmt::format("Error: {}", m_result.error()));
|
||||
m_result.error().clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
||||
m_statuslabel.redraw("OK");
|
||||
switchScreen<GreenPassMenu>();
|
||||
}
|
||||
}
|
||||
|
||||
void QrImportDisplay::buttonPressed(espgui::Button button)
|
||||
{
|
||||
Base::buttonPressed(button);
|
||||
|
||||
switch (button)
|
||||
{
|
||||
using espgui::Button;
|
||||
case Button::Left:
|
||||
if (!m_waitingForResult)
|
||||
switchScreen<GreenPassMenu>();
|
||||
else
|
||||
ESP_LOGW(TAG, "tried to leave while waiting for result");
|
||||
break;
|
||||
default:;
|
||||
}
|
||||
}
|
||||
|
@ -1,26 +1,114 @@
|
||||
#pragma once
|
||||
constexpr const char * const TAG = "qrimport";
|
||||
|
||||
// 3rd party includes
|
||||
#include <esp_log.h>
|
||||
#include <widgets/label.h>
|
||||
#include <tftinstance.h>
|
||||
#include <tl/expected.hpp>
|
||||
#include <fmt/core.h>
|
||||
|
||||
// local includes
|
||||
#include "bobbydisplay.h"
|
||||
#include "bobbyerrorhandler.h"
|
||||
#include "qrimport.h"
|
||||
#include "screenmanager.h"
|
||||
|
||||
template<typename TMenu>
|
||||
class QrImportDisplay : public BobbyDisplay
|
||||
{
|
||||
using Base = BobbyDisplay;
|
||||
|
||||
public:
|
||||
explicit QrImportDisplay(const std::string &nvs_key);
|
||||
explicit QrImportDisplay(std::string &&nvs_key);
|
||||
explicit QrImportDisplay(const std::string &nvs_key) : m_nvs_key{nvs_key} {}
|
||||
explicit QrImportDisplay(std::string &&nvs_key) : m_nvs_key{std::move(nvs_key)} {}
|
||||
|
||||
void start() override;
|
||||
void update() override;
|
||||
void redraw() override;
|
||||
void start() override
|
||||
{
|
||||
using namespace espgui;
|
||||
Base::start();
|
||||
|
||||
void buttonPressed(espgui::Button button) override;
|
||||
m_statuslabel.start();
|
||||
|
||||
qrimport::setup_request();
|
||||
|
||||
if (const auto result = qrimport::start_qr_request(); result)
|
||||
{
|
||||
ESP_LOGI(TAG, "started request, waiting for result");
|
||||
m_waitingForResult = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP_LOGE(TAG, "could not start request: %.*s", result.error().size(), result.error().data());
|
||||
m_result = tl::make_unexpected(std::move(result).error());
|
||||
}
|
||||
}
|
||||
|
||||
void update() override
|
||||
{
|
||||
using namespace espgui;
|
||||
Base::update();
|
||||
|
||||
if (!m_waitingForResult)
|
||||
return;
|
||||
|
||||
if (qrimport::get_request_running())
|
||||
return;
|
||||
|
||||
m_waitingForResult = false;
|
||||
|
||||
m_result = qrimport::check_request();
|
||||
if (m_result)
|
||||
{
|
||||
ESP_LOGI(TAG, "%.*s => %.*s", m_nvs_key.size(), m_nvs_key.data(), m_result->size(), m_result->data());
|
||||
if (const auto result = qrimport::set_qr_code(m_nvs_key, *m_result); !result)
|
||||
m_result = tl::make_unexpected(fmt::format("saving qr failed: {}", esp_err_to_name(result.error())));
|
||||
}
|
||||
else
|
||||
ESP_LOGW(TAG, "failed %.*s => %.*s", m_nvs_key.size(), m_nvs_key.data(), m_result.error().size(), m_result.error().data());
|
||||
}
|
||||
|
||||
void redraw() override
|
||||
{
|
||||
using namespace espgui;
|
||||
Base::redraw();
|
||||
|
||||
if (m_waitingForResult)
|
||||
{
|
||||
tft.setTextColor(TFT_YELLOW, TFT_BLACK);
|
||||
m_statuslabel.redraw("In progress");
|
||||
}
|
||||
else if (!m_result && !m_result.error().empty())
|
||||
{
|
||||
tft.setTextColor(TFT_RED, TFT_BLACK);
|
||||
BobbyErrorHandler{}.errorOccured(fmt::format("Error: {}", m_result.error()));
|
||||
m_result.error().clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
||||
m_statuslabel.redraw("OK");
|
||||
switchScreen<TMenu>();
|
||||
}
|
||||
}
|
||||
|
||||
void buttonPressed(espgui::Button button) override
|
||||
{
|
||||
using namespace espgui;
|
||||
Base::buttonPressed(button);
|
||||
|
||||
switch (button)
|
||||
{
|
||||
using espgui::Button;
|
||||
case Button::Left:
|
||||
if (!m_waitingForResult)
|
||||
switchScreen<TMenu>();
|
||||
else
|
||||
ESP_LOGW(TAG, "tried to leave while waiting for result");
|
||||
break;
|
||||
default:;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_waitingForResult{false};
|
||||
|
Reference in New Issue
Block a user