Merge pull request #148 from bobbycar-graz/cpp-refactor

Refactoring and many new features!
This commit is contained in:
2021-12-18 00:46:51 +01:00
committed by GitHub
74 changed files with 1396 additions and 415 deletions

1
.gitignore vendored
View File

@ -11,3 +11,4 @@ desktop.ini
/.idea
/.ccache
/main/certs/*
/.vscode/*

6
.gitmodules vendored
View File

@ -7,9 +7,6 @@
[submodule "components/cpputils"]
path = components/cpputils
url = ../../0xFEEDC0DE64/cpputils.git
[submodule "components/espcpputils"]
path = components/espcpputils
url = ../../0xFEEDC0DE64/espcpputils.git
[submodule "components/cxx-ring-buffer"]
path = components/cxx-ring-buffer
url = ../../0xFEEDC0DE64/cxx-ring-buffer.git
@ -61,3 +58,6 @@
[submodule "components/espconfiglib"]
path = components/espconfiglib
url = ../../0xFEEDC0DE64/espconfiglib.git
[submodule "components/TFT_eSPI_QRcode"]
path = components/TFT_eSPI_QRcode
url = ../TFT_eSPI_QRcode.git

View File

@ -118,6 +118,8 @@ set(BOBBYCAR_BUILDFLAGS
-DOLD_NVS
-DFEATURE_DNS_NS
-DSWITCH_BLINK
# -DFEATURE_IS_MIR_EGAL_OB_DER_WEBSERVER_FUNKTIONIERT
-DFEATURE_ESPNOW
)
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/ignore/lockscreen_plugin.cmake")

View File

@ -92,10 +92,13 @@ set(BOBBYCAR_BUILDFLAGS
-DFEATURE_LEDSTRIP
-DPINS_LEDSTRIP=26
-DLEDSTRIP_LENGTH=200
# -DHEAP_LRGST_CRASH_TEXT_FIX
# -DLEDSTRIP_WRONG_DIRECTION
-DLEDSTRIP_ANIMATION_DEFAULT=0
-DLEDS_PER_METER=144
-DOLD_NVS
# -DFEATURE_DNS_NS
# -DSWITCH_BLINK
-DFEATURE_IS_MIR_EGAL_OB_DER_WEBSERVER_FUNKTIONIERT
-DFEATURE_ESPNOW
)

BIN
icons/greenpass.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 409 B

View File

@ -77,10 +77,13 @@ set(headers
displays/menus/demosmenu.h
displays/menus/dynamicdebugmenu.h
displays/menus/enablemenu.h
displays/menus/espnowmenu.h
displays/menus/espnowsettingsmenu.h
displays/menus/feedbackdebugmenu.h
displays/menus/gametrakmodesettingsmenu.h
displays/menus/genericwifisettingsmenu.h
displays/menus/graphsmenu.h
displays/menus/greenpassmenu.h
displays/menus/handbremssettingsmenu.h
displays/menus/invertmenu.h
displays/menus/larsmmodesettingsmenu.h
@ -117,6 +120,7 @@ set(headers
displays/popups/alertdisplay.h
displays/poweroffdisplay.h
displays/powersupplydisplay.h
displays/qrcodedebug.h
displays/spirodisplay.h
displays/starfielddisplay.h
displays/statusdisplay.h
@ -129,6 +133,7 @@ set(headers
dpad6wire.h
drivingstatistics.h
esptexthelpers.h
espnowfunctions.h
feedbackparser.h
globals.h
handbremse.h
@ -141,6 +146,7 @@ set(headers
icons/close.h
icons/demos.h
icons/graph.h
icons/greenpass.h
icons/hardware.h
icons/info.h
icons/lock.h
@ -195,6 +201,7 @@ set(headers
webserver_settings.h
webserver_stringsettings.h
widgets/doubleprogressbar.h
widgets/menudisplaywithtime.h
wifi_bobbycar.h
wifitexthelpers.h
)
@ -278,10 +285,13 @@ set(sources
displays/menus/demosmenu.cpp
displays/menus/dynamicdebugmenu.cpp
displays/menus/enablemenu.cpp
displays/menus/espnowmenu.cpp
displays/menus/espnowsettingsmenu.cpp
displays/menus/feedbackdebugmenu.cpp
displays/menus/gametrakmodesettingsmenu.cpp
displays/menus/genericwifisettingsmenu.cpp
displays/menus/graphsmenu.cpp
displays/menus/greenpassmenu.cpp
displays/menus/handbremssettingsmenu.cpp
displays/menus/invertmenu.cpp
displays/menus/larsmmodesettingsmenu.cpp
@ -318,6 +328,7 @@ set(sources
displays/popups/alertdisplay.cpp
displays/poweroffdisplay.cpp
displays/powersupplydisplay.cpp
displays/qrcodedebug.cpp
displays/spirodisplay.cpp
displays/starfielddisplay.cpp
displays/statusdisplay.cpp
@ -330,6 +341,7 @@ set(sources
dpad6wire.cpp
drivingstatistics.cpp
esptexthelpers.cpp
espnowfunctions.cpp
feedbackparser.cpp
globals.cpp
handbremse.cpp
@ -342,6 +354,7 @@ set(sources
icons/close.cpp
icons/demos.cpp
icons/graph.cpp
icons/greenpass.cpp
icons/hardware.cpp
icons/info.cpp
icons/lock.cpp
@ -397,13 +410,14 @@ set(sources
webserver_settings.cpp
webserver_stringsettings.cpp
widgets/doubleprogressbar.cpp
widgets/menudisplaywithtime.cpp
wifi_bobbycar.cpp
wifitexthelpers.cpp
)
set(dependencies
libsodium freertos nvs_flash esp_http_server esp_https_ota mdns app_update esp_system esp_websocket_client driver
arduino-esp32 ArduinoJson esp-nimble-cpp FastLED-idf TFT_eSPI
arduino-esp32 ArduinoJson esp-nimble-cpp FastLED-idf TFT_eSPI TFT_eSPI_QRcode
bobbycar-protocol cpputils cxx-ring-buffer date
espasynchttpreq espasyncota espchrono espcpputils espconfiglib esp-gui-lib esphttpdutils espwifistack expected fmt
)

View File

@ -14,15 +14,19 @@ struct RefAccessorSaveSettings : public virtual espgui::RefAccessor<T>
void setValue(T value) override { espgui::RefAccessor<T>::setValue(value); saveSettings(); };
};
// Bms
#ifdef FEATURE_BMS
struct AutoConnectBmsAccessor : public RefAccessorSaveSettings<bool> { bool &getRef() const override { return settings.autoConnectBms; } };
#endif
// Buzzer
struct ReverseBeepAccessor : public RefAccessorSaveSettings<bool> { bool &getRef() const override { return settings.buzzer.reverseBeep; } };
struct ReverseBeepFreq0Accessor : public RefAccessorSaveSettings<uint8_t> { uint8_t &getRef() const override { return settings.buzzer.reverseBeepFreq0; } };
struct ReverseBeepFreq1Accessor : public RefAccessorSaveSettings<uint8_t> { uint8_t &getRef() const override { return settings.buzzer.reverseBeepFreq1; } };
struct ReverseBeepDuration0Accessor : public RefAccessorSaveSettings<int16_t> { int16_t &getRef() const override { return settings.buzzer.reverseBeepDuration0; } };
struct ReverseBeepDuration1Accessor : public RefAccessorSaveSettings<int16_t> { int16_t &getRef() const override { return settings.buzzer.reverseBeepDuration1; } };
// Limits
struct IMotMaxAccessor : public RefAccessorSaveSettings<int16_t> { int16_t &getRef() const override { return settings.limits.iMotMax; } };
struct IDcMaxAccessor : public RefAccessorSaveSettings<int16_t> { int16_t &getRef() const override { return settings.limits.iDcMax; } };
struct NMotMaxKmhAccessor : public virtual espgui::AccessorInterface<int16_t>
@ -34,22 +38,27 @@ struct NMotMaxRpmAccessor : public RefAccessorSaveSettings<int16_t> { int16_t &g
struct FieldWeakMaxAccessor : public RefAccessorSaveSettings<int16_t> { int16_t &getRef() const override { return settings.limits.fieldWeakMax; } };
struct PhaseAdvMaxAccessor : public RefAccessorSaveSettings<int16_t> { int16_t &getRef() const override { return settings.limits.phaseAdvMax; } };
// WiFi
struct WifiStaEnabledAccessor : public RefAccessorSaveSettings<bool> { bool &getRef() const override { return settings.wifiSettings.wifiStaEnabled; } };
struct WifiApEnabledAccessor : public RefAccessorSaveSettings<bool> { bool &getRef() const override { return settings.wifiSettings.wifiApEnabled; } };
// Bluetooth
#ifdef FEATURE_BLUETOOTH
struct AutoBluetoothModeAccessor : public RefAccessorSaveSettings<BluetoothMode> { BluetoothMode &getRef() const override { return settings.bluetoothSettings.autoBluetoothMode; } };
#endif
// Bluetooth Low Energy
#ifdef FEATURE_BLE
struct BleEnabledAccessor : public RefAccessorSaveSettings<bool> { bool &getRef() const override { return settings.bleSettings.bleEnabled; } };
#endif
// Cloud
#ifdef FEATURE_CLOUD
struct CloudEnabledAccessor : public RefAccessorSaveSettings<bool> { bool &getRef() const override { return settings.cloudSettings.cloudEnabled; } };
struct CloudTransmitTimeoutAccessor : public RefAccessorSaveSettings<int16_t> { int16_t &getRef() const override { return settings.cloudSettings.cloudTransmitTimeout; } };
#endif
// Time
struct TimezoneOffsetAccessor : public virtual espgui::AccessorInterface<int32_t>
{
int32_t getValue() const override { return settings.timeSettings.timezoneOffset.count(); }
@ -66,6 +75,7 @@ struct TimeSyncIntervalAccessor : public virtual espgui::AccessorInterface<int32
};
#endif
// Controller Hardware
struct FrontLeftEnabledAccessor : public RefAccessorSaveSettings<bool> { bool &getRef() const override { return settings.controllerHardware.enableFrontLeft; } };
struct FrontRightEnabledAccessor : public RefAccessorSaveSettings<bool> { bool &getRef() const override { return settings.controllerHardware.enableFrontRight; } };
struct BackLeftEnabledAccessor : public RefAccessorSaveSettings<bool> { bool &getRef() const override { return settings.controllerHardware.enableBackLeft; } };
@ -89,6 +99,8 @@ struct SwapFrontBackAccessor : public RefAccessorSaveSettings<bool> {
void setValue(bool value) override { RefAccessorSaveSettings<bool>::setValue(value); updateSwapFrontBack(); };
#endif
};
// CAN
#ifdef FEATURE_CAN
struct SendFrontCanCmdAccessor : public RefAccessorSaveSettings<bool> { bool &getRef() const override { return settings.controllerHardware.sendFrontCanCmd; } };
struct SendBackCanCmdAccessor : public RefAccessorSaveSettings<bool> { bool &getRef() const override { return settings.controllerHardware.sendBackCanCmd; } };
@ -96,6 +108,7 @@ struct CanTransmitTimeoutAccessor : public RefAccessorSaveSettings<int16_t> { in
struct CanReceiveTimeoutAccessor : public RefAccessorSaveSettings<int16_t> { int16_t &getRef() const override { return settings.controllerHardware.canReceiveTimeout; } };
#endif
// Input devices
struct SampleCountAccessor : public RefAccessorSaveSettings<int16_t> { int16_t &getRef() const override { return settings.boardcomputerHardware.sampleCount; } };
struct GasMinAccessor : public RefAccessorSaveSettings<int16_t> { int16_t &getRef() const override { return settings.boardcomputerHardware.gasMin; } };
struct GasMaxAccessor : public RefAccessorSaveSettings<int16_t> { int16_t &getRef() const override { return settings.boardcomputerHardware.gasMax; } };
@ -117,9 +130,13 @@ struct ModeUpdateRateAccessor : public RefAccessorSaveSettings<int16_t> { int16_
struct StatsUpdateRateAccessor : public RefAccessorSaveSettings<int16_t> { int16_t &getRef() const override { return settings.boardcomputerHardware.timersSettings.statsUpdateRate; } };
struct DisplayUpdateRateAccessor : public RefAccessorSaveSettings<int16_t> { int16_t &getRef() const override { return settings.boardcomputerHardware.timersSettings.displayUpdateRate; } };
struct DisplayRedrawRateAccessor : public RefAccessorSaveSettings<int16_t> { int16_t &getRef() const override { return settings.boardcomputerHardware.timersSettings.displayRedrawRate; } };
// CAN
#ifdef FEATURE_CAN
struct CanReceiveRateAccessor : public RefAccessorSaveSettings<int16_t> { int16_t &getRef() const override { return settings.boardcomputerHardware.timersSettings.canReceiveRate; } };
#endif
// Cloud
#ifdef FEATURE_CLOUD
struct CloudCollectRateAccessor : public RefAccessorSaveSettings<int16_t> { int16_t &getRef() const override { return settings.boardcomputerHardware.timersSettings.cloudCollectRate; } };
struct CloudSendRateAccessor : public RefAccessorSaveSettings<int16_t> { int16_t &getRef() const override { return settings.boardcomputerHardware.timersSettings.cloudSendRate; } };
@ -129,6 +146,7 @@ struct CloudDebugEnableAccessor : public RefAccessorSaveSettings<bool> { bool &g
struct UdpUseStdStringAccessor : public RefAccessorSaveSettings<bool> { bool &getRef() const override { return settings.cloudSettings.udpUseStdString; } };
#endif
// DefaultMode
struct DefaultModeModelModeAccessor : public RefAccessorSaveSettings<UnifiedModelMode> { UnifiedModelMode &getRef() const override { return settings.defaultMode.modelMode; } };
struct DefaultModeHybridModelModeAccessor : public RefAccessorSaveSettings<UnifiedModelMode> { UnifiedModelMode &getRef() const override { return settings.hybrid.hybridMode; } };
struct DefaultModeSquareGasAccessor : public RefAccessorSaveSettings<bool> { bool &getRef() const override { return settings.defaultMode.squareGas; } };
@ -153,15 +171,19 @@ struct DefaultModeEnableHybridAccessor : public RefAccessorSaveSettings<bool> {
struct DefaultModeHybridActivationLimitAccessor : public RefAccessorSaveSettings<int16_t> { int16_t &getRef() const override { return settings.hybrid.activationLimit; } };
struct DefaultModeHybridDeactivationLimitAccessor : public RefAccessorSaveSettings<int16_t> { int16_t &getRef() const override { return settings.hybrid.deactivationLimit; } };
// TempomatMode
struct TempomatModeModelModeAccessor : public RefAccessorSaveSettings<UnifiedModelMode> { UnifiedModelMode &getRef() const override { return settings.tempomatMode.modelMode; } };
// LarsmMode
struct LarsmModeModelModeAccessor : public RefAccessorSaveSettings<UnifiedModelMode> { UnifiedModelMode &getRef() const override { return settings.larsmMode.modelMode; } };
struct LarsmModeModeAccessor : public RefAccessorSaveSettings<LarsmModeMode> { LarsmModeMode &getRef() const override { return settings.larsmMode.mode; } };
struct LarsmModeIterationsAccessor : public RefAccessorSaveSettings<uint8_t> { uint8_t &getRef() const override { return settings.larsmMode.iterations; } };
// MotortestMode
struct MotortestModeMultiplikatorAccessor : public RefAccessorSaveSettings<uint8_t> { uint8_t &getRef() const override { return settings.motortestMode.multiplikator; } };
struct MotortestMaxPwmAccessor : public RefAccessorSaveSettings<uint16_t> { uint16_t &getRef() const override { return settings.motortestMode.maxPwm; } };
// Ledstrip
#ifdef FEATURE_LEDSTRIP
struct EnableLedAnimationAccessor : public RefAccessorSaveSettings<bool> { bool &getRef() const override { return settings.ledstrip.enableLedAnimation; } };
struct EnableBrakeLightsAccessor : public RefAccessorSaveSettings<bool> { bool &getRef() const override { return settings.ledstrip.enableBrakeLights; } };
@ -190,13 +212,22 @@ struct BatteryParallelCellsAccessor : public RefAccessorSaveSettings<uint8_t> {
struct BatteryWHperKMAccessor : public RefAccessorSaveSettings<uint16_t> { uint16_t &getRef() const override { return settings.battery.watthoursPerKilometer; } };
struct BatteryApplyCalibrationAccessor : public RefAccessorSaveSettings<bool> { bool &getRef() const override { return settings.battery.applyCalibration; } };
// Lockscreen
struct LockscreenAllowPresetSwitchAccessor : public RefAccessorSaveSettings<bool> { bool &getRef() const override { return settings.lockscreen.allowPresetSwitch; } };
template<uint8_t index>
struct LockscreenPinDigitAccessor : public RefAccessorSaveSettings<int8_t> { int8_t &getRef() const override { return settings.lockscreen.pin[index]; } };
struct LockscreenKeepLockedAccessor : public RefAccessorSaveSettings<bool> { bool &getRef() const override { return settings.lockscreen.keepLockedAfterReboot; } };
// Handbremse
struct HandbremsEnabledAccessor : public RefAccessorSaveSettings<bool> { bool &getRef() const override { return settings.handbremse.enable; } };
struct HandbremsModeAccessor : public RefAccessorSaveSettings<HandbremseMode> { HandbremseMode &getRef() const override { return settings.handbremse.mode; } };
struct HandbremsTimeoutAccessor : public RefAccessorSaveSettings<uint16_t> { uint16_t &getRef() const override { return settings.handbremse.triggerTimeout; } };
struct HandbremsAutomaticAccessor : public RefAccessorSaveSettings<bool> { bool &getRef() const override { return settings.handbremse.automatic; } };
struct HandbremsVisualizeAccessor : public RefAccessorSaveSettings<bool> { bool &getRef() const override { return settings.handbremse.visualize; } };
// ESP Now
#ifdef FEATURE_ESPNOW
struct ESPNowSyncTimeEnabledAccessor : public RefAccessorSaveSettings<bool> { bool &getRef() const override { return settings.espnow.syncTime; } };
struct ESPNowSyncTimeWithOthersEnabledAccessor : public RefAccessorSaveSettings<bool> { bool &getRef() const override { return settings.espnow.syncTimeWithOthers; } };
struct ESPNowSyncBlinkEnabledAccessor : public RefAccessorSaveSettings<bool> { bool &getRef() const override { return settings.espnow.syncBlink; } };
#endif

View File

@ -1,40 +1,14 @@
#pragma once
#include "actioninterface.h"
#include "utils.h"
#include "globals.h"
#include "ledstrip.h"
// #include "ledstripdefines.h"
using namespace espgui;
namespace {
#ifdef FEATURE_LEDSTRIP
template<uint16_t type>
class LedStripSetAnimationAction : public virtual ActionInterface
class LedStripSetAnimationAction : public virtual espgui::ActionInterface
{
public:
void triggered() override { animation_type = type; }
};
/*
class LedstripAnimationDefaultRainbowAction : public virtual ActionInterface
{
public:
void triggered() override { animation_type = LEDSTRIP_ANIMATION_TYPE_DEFAULTRAINBOW; }
};
class LedstripAnimationBetterRainbowAction : public virtual ActionInterface
{
public:
void triggered() override { animation_type = LEDSTRIP_ANIMATION_TYPE_BETTERRAINBOW; }
};
class LedstripAnimationSyncToSpeedAction : public virtual ActionInterface
{
public:
void triggered() override { animation_type = LEDSTRIP_ANIMATION_TYPE_SPEEDSYNCANIMATION; }
};
*/
#endif
}

View File

@ -0,0 +1,42 @@
#include "ledstripblinkactions.h"
#ifdef FEATURE_LEDSTRIP
#include "ledstrip.h"
#include "ledstripdefines.h"
using namespace espgui;
void LedstripAnimationBlinkNoneAction::triggered()
{
blinkAnimation = LEDSTRIP_OVERWRITE_NONE;
}
#ifndef LEDSTRIP_WRONG_DIRECTION
void LedstripAnimationBlinkLeftAction::triggered()
{
blinkAnimation = LEDSTRIP_OVERWRITE_BLINKLEFT;
}
#else
void LedstripAnimationBlinkLeftAction::triggered()
{
blinkAnimation = LEDSTRIP_OVERWRITE_BLINKRIGHT;
}
#endif
#ifndef LEDSTRIP_WRONG_DIRECTION
void LedstripAnimationBlinkRightAction::triggered()
{
blinkAnimation = LEDSTRIP_OVERWRITE_BLINKRIGHT;
}
#else
void LedstripAnimationBlinkRightAction::triggered()
{
blinkAnimation = LEDSTRIP_OVERWRITE_BLINKLEFT;
}
#endif
void LedstripAnimationBlinkBothAction::triggered()
{
blinkAnimation = LEDSTRIP_OVERWRITE_BLINKBOTH;
}
#endif

View File

@ -1,53 +1,37 @@
#pragma once
#include "actioninterface.h"
#include "utils.h"
#include "globals.h"
#include "ledstrip.h"
#include "ledstripdefines.h"
using namespace espgui;
#ifdef FEATURE_LEDSTRIP
namespace {
class LedstripAnimationBlinkNoneAction : public virtual ActionInterface
#include "actioninterface.h"
class LedstripAnimationBlinkNoneAction : public virtual espgui::ActionInterface
{
public:
void triggered() override { blinkAnimation = LEDSTRIP_OVERWRITE_NONE; }
void triggered() override;
};
class LedstripAnimationBlinkLeftAction : public virtual ActionInterface
class LedstripAnimationBlinkLeftAction : public virtual espgui::ActionInterface
{
public:
#ifndef LEDSTRIP_WRONG_DIRECTION
void triggered() override {
blinkAnimation = LEDSTRIP_OVERWRITE_BLINKLEFT;
}
void triggered() override;
#else
void triggered() override {
blinkAnimation = LEDSTRIP_OVERWRITE_BLINKRIGHT;
}
void triggered() override;
#endif
};
class LedstripAnimationBlinkRightAction : public virtual ActionInterface
class LedstripAnimationBlinkRightAction : public virtual espgui::ActionInterface
{
public:
#ifndef LEDSTRIP_WRONG_DIRECTION
void triggered() override {
blinkAnimation = LEDSTRIP_OVERWRITE_BLINKRIGHT;
}
void triggered() override;
#else
void triggered() override {
blinkAnimation = LEDSTRIP_OVERWRITE_BLINKLEFT;
}
void triggered() override;
#endif
};
class LedstripAnimationBlinkBothAction : public virtual ActionInterface
class LedstripAnimationBlinkBothAction : public virtual espgui::ActionInterface
{
public:
void triggered() override { blinkAnimation = LEDSTRIP_OVERWRITE_BLINKBOTH; }
void triggered() override;
};
}
#endif

View File

@ -12,7 +12,7 @@ class SwitchProfileAction : public virtual ActionInterface
public:
void triggered() override
{
switchProfile(index);
settingsutils::switchProfile(index);
}
};
}

View File

@ -1,6 +1,8 @@
#include "buttons.h"
#include "modes/defaultmode.h"
using namespace std::chrono_literals;
int rotated{};
bool requestFullRedraw{};
@ -123,7 +125,7 @@ void InputDispatcher::profileButton(uint8_t index, bool pressed)
if (profileButtonDisabled)
return;
switchProfile(index);
settingsutils::switchProfile(index);
}
#ifdef SWITCH_BLINK

View File

@ -19,6 +19,8 @@
#include "globals.h"
#include "buttons.h"
using namespace std::chrono_literals;
namespace can {
namespace {
constexpr const char * const TAG = "BOBBYCAN";

View File

@ -0,0 +1,105 @@
#include "bmsdisplay.h"
#if defined(FEATURE_BLUETOOTH) && defined(FEATURE_BMS)
#include "displays/menus/mainmenu.h"
#include "displays/metersdisplay.h"
#include "displays/statusdisplay.h"
#include "screenmanager.h"
#include "tftinstance.h"
using namespace espgui;
void BmsDisplay::initScreen()
{
tft.fillScreen(TFT_BLACK);
tft.setTextColor(TFT_WHITE, TFT_BLACK);
tft.setTextFont(2);
m_statusLabel.start();
m_statusLabel.redraw("init");
tft.setTextFont(4);
tft.drawString("Voltage:", 0, m_voltageLabel.y());
m_voltageLabel.start();
tft.drawString("Capacity:", 0, m_capacityLabel.y());
m_capacityLabel.start();
tft.drawString("SOC:", 0, m_socLabel.y());
m_socLabel.start();
tft.drawString("Power:", 0, m_powerLabel.y());
m_powerLabel.start();
tft.drawString("Current:", 0, m_currentLabel.y());
m_currentLabel.start();
tft.drawString("Speed:", 0, m_speedLabel.y());
m_speedLabel.start();
tft.drawString("PpS:", 0, m_powerPerSpeedLabel.y());
m_powerPerSpeedLabel.start();
for (auto &label : m_battLabels)
label.start();
tft.drawString("Cycle:", 0, m_cycleLabel.y());
m_cycleLabel.start();
}
void BmsDisplay::redraw()
{
if (bluetoothSerial.hasClient())
tft.setTextColor(TFT_GREEN, TFT_BLACK);
else
{
tft.setTextColor(TFT_RED, TFT_BLACK);
tft.setTextFont(2);
}
m_statusLabel.redraw(bluetoothSerial.hasClient() ? "OK" : "FAIL");
tft.setTextColor(TFT_WHITE, TFT_BLACK);
if (!bluetoothSerial.hasClient())
tft.setTextFont(4);
if (bluetoothSerial.hasClient())
{
m_voltageLabel.redraw(fmt::format("{:.02f}V", bms::voltage));
m_capacityLabel.redraw(fmt::format("{:.02f} mAh", bms::capacity));
m_socLabel.redraw(fmt::format("{:.02f}%", bms::soc));
m_powerLabel.redraw(fmt::format("{:.02f}W", bms::power));
m_currentLabel.redraw(fmt::format("{:.02f}A", bms::current));
}
else
{
m_voltageLabel.clear();
m_capacityLabel.clear();
m_socLabel.clear();
m_powerLabel.clear();
m_currentLabel.clear();
}
m_speedLabel.redraw(fmt::format("{:.02f}kmh", avgSpeedKmh));
if (bluetoothSerial.hasClient())
m_powerPerSpeedLabel.redraw(fmt::format("{:.02f}W/kmh", avgSpeedKmh < 1 ? 0 : bms::power / avgSpeedKmh));
else
m_powerPerSpeedLabel.clear();
for (int i = 0; i < 12; i++)
m_battLabels[i].redraw(fmt::format("{:.02f}", bms::batt[i]));
if (bluetoothSerial.hasClient())
m_cycleLabel.redraw(fmt::format("{:.02f}AH", bms::cycle));
else
m_cycleLabel.clear();
}
void BmsDisplay::rotate(int offset)
{
if (offset < 0)
switchScreen<MetersDisplay>();
else if (offset > 0)
switchScreen<StatusDisplay>();
}
void BmsDisplay::confirm()
{
switchScreen<MainMenu>();
}
#endif

View File

@ -1,5 +1,6 @@
#pragma once
#if defined(FEATURE_BLUETOOTH) && defined(FEATURE_BMS)
// 3rdparty lib includes
#include <fmt/core.h>
@ -11,122 +12,32 @@
#include "widgets/label.h"
#include "screenmanager.h"
namespace {
#if defined(FEATURE_BLUETOOTH) && defined(FEATURE_BMS)
class BmsDisplay : public Display, public ConfirmActionInterface<SwitchScreenAction<MainMenu>>, public DummyBack
class BmsDisplay :
public espgui::Display,
public espgui::DummyBack
{
public:
void initScreen() override;
void redraw() override;
void confirm() override;
void rotate(int offset) override;
Label m_statusLabel{200, 0};
espgui::Label m_statusLabel{200, 0};
Label m_voltageLabel{107, 0};
Label m_capacityLabel{107, 25};
Label m_socLabel{107, 50};
Label m_powerLabel{107, 75};
Label m_currentLabel{107, 100};
Label m_speedLabel{107, 125};
Label m_powerPerSpeedLabel{107, 150};
espgui::Label m_voltageLabel{107, 0};
espgui::Label m_capacityLabel{107, 25};
espgui::Label m_socLabel{107, 50};
espgui::Label m_powerLabel{107, 75};
espgui::Label m_currentLabel{107, 100};
espgui::Label m_speedLabel{107, 125};
espgui::Label m_powerPerSpeedLabel{107, 150};
std::array<Label, 12> m_battLabels{{
Label{0, 225}, Label{60, 225}, Label{120, 225}, Label{180, 225},
Label{0, 250}, Label{60, 250}, Label{120, 250}, Label{180, 250},
Label{0, 275}, Label{60, 275}, Label{120, 275}, Label{180, 275}
std::array<espgui::Label, 12> m_battLabels{{
espgui::Label{0, 225}, espgui::Label{60, 225}, espgui::Label{120, 225}, espgui::Label{180, 225},
espgui::Label{0, 250}, espgui::Label{60, 250}, espgui::Label{120, 250}, espgui::Label{180, 250},
espgui::Label{0, 275}, espgui::Label{60, 275}, espgui::Label{120, 275}, espgui::Label{180, 275}
}};
Label m_cycleLabel{105, 300};
espgui::Label m_cycleLabel{105, 300};
};
void BmsDisplay::initScreen()
{
tft.fillScreen(TFT_BLACK);
tft.setTextColor(TFT_WHITE, TFT_BLACK);
tft.setTextFont(2);
m_statusLabel.start();
m_statusLabel.redraw("init");
tft.setTextFont(4);
tft.drawString("Voltage:", 0, m_voltageLabel.y());
m_voltageLabel.start();
tft.drawString("Capacity:", 0, m_capacityLabel.y());
m_capacityLabel.start();
tft.drawString("SOC:", 0, m_socLabel.y());
m_socLabel.start();
tft.drawString("Power:", 0, m_powerLabel.y());
m_powerLabel.start();
tft.drawString("Current:", 0, m_currentLabel.y());
m_currentLabel.start();
tft.drawString("Speed:", 0, m_speedLabel.y());
m_speedLabel.start();
tft.drawString("PpS:", 0, m_powerPerSpeedLabel.y());
m_powerPerSpeedLabel.start();
for (auto &label : m_battLabels)
label.start();
tft.drawString("Cycle:", 0, m_cycleLabel.y());
m_cycleLabel.start();
}
void BmsDisplay::redraw()
{
if (bluetoothSerial.hasClient())
tft.setTextColor(TFT_GREEN, TFT_BLACK);
else
{
tft.setTextColor(TFT_RED, TFT_BLACK);
tft.setTextFont(2);
}
m_statusLabel.redraw(bluetoothSerial.hasClient() ? "OK" : "FAIL");
tft.setTextColor(TFT_WHITE, TFT_BLACK);
if (!bluetoothSerial.hasClient())
tft.setTextFont(4);
if (bluetoothSerial.hasClient())
{
m_voltageLabel.redraw(fmt::format("{:.02f}V", bms::voltage));
m_capacityLabel.redraw(fmt::format("{:.02f} mAh", bms::capacity));
m_socLabel.redraw(fmt::format("{:.02f}%", bms::soc));
m_powerLabel.redraw(fmt::format("{:.02f}W", bms::power));
m_currentLabel.redraw(fmt::format("{:.02f}A", bms::current));
}
else
{
m_voltageLabel.clear();
m_capacityLabel.clear();
m_socLabel.clear();
m_powerLabel.clear();
m_currentLabel.clear();
}
m_speedLabel.redraw(fmt::format("{:.02f}kmh", avgSpeedKmh));
if (bluetoothSerial.hasClient())
m_powerPerSpeedLabel.redraw(fmt::format("{:.02f}W/kmh", avgSpeedKmh < 1 ? 0 : bms::power / avgSpeedKmh));
else
m_powerPerSpeedLabel.clear();
for (int i = 0; i < 12; i++)
m_battLabels[i].redraw(fmt::format("{:.02f}", bms::batt[i]));
if (bluetoothSerial.hasClient())
m_cycleLabel.redraw(fmt::format("{:.02f}AH", bms::cycle));
else
m_cycleLabel.clear();
}
void BmsDisplay::rotate(int offset)
{
if (offset < 0)
switchScreen<MetersDisplay>();
else if (offset > 0)
switchScreen<StatusDisplay>();
}
#endif
}

View File

@ -5,6 +5,7 @@
#include <screenmanager.h>
// local includes
#include "displays/menus/mainmenu.h"
#include "displays/statusdisplay.h"
#include "displays/menus/boardcomputerhardwaresettingsmenu.h"
@ -241,6 +242,12 @@ void CalibrateDisplay::back()
case Status::Begin:
if (m_bootup)
espgui::switchScreen<StatusDisplay>();
else if (settings.lockscreen.keepLockedAfterReboot && settings.lockscreen.locked)
{
espgui::switchScreen<MainMenu>();
settings.lockscreen.locked = false;
saveSettings();
}
else
espgui::switchScreen<BoardcomputerHardwareSettingsMenu>();
break;

View File

@ -14,6 +14,7 @@
#include "displays/menus/mainmenu.h"
#include "globals.h"
#include "texts.h"
#include "espnowfunctions.h"
#ifdef FEATURE_GARAGE
void GarageDisplay::start()
@ -41,6 +42,14 @@ void GarageDisplay::redraw()
void GarageDisplay::confirm()
{
#ifdef FEATURE_ESPNOW
if (const auto error = espnow::send_espnow_message(fmt::format("BOBBYOPEN:garage:{}", "TOKEN")); error != ESP_OK)
{
ESP_LOGE("BOBBY", "send_espnow_message() failed with: %s", esp_err_to_name(error));
return;
}
espgui::switchScreen<MainMenu>();
#endif
}
void GarageDisplay::back()

View File

@ -10,6 +10,7 @@
#include "texts.h"
#include "buttons.h"
#include "displays/menus/mainmenu.h"
#include "displays/calibratedisplay.h"
void Lockscreen::start()
{
@ -23,6 +24,11 @@ void Lockscreen::start()
profileButtonDisabled = !settings.lockscreen.allowPresetSwitch;
isLocked = true;
if (settings.lockscreen.keepLockedAfterReboot && !settings.lockscreen.locked)
{
settings.lockscreen.locked = true;
saveSettings();
}
}
void Lockscreen::initScreen()
@ -64,16 +70,19 @@ void Lockscreen::update()
void Lockscreen::redraw()
{
if (m_pressed)
if (m_pressed || m_back_pressed)
{
drawRect(m_currentIndex, 1, TFT_BLACK);
drawRect(m_currentIndex, 2, TFT_BLACK);
if (++m_currentIndex>=4)
if (!m_back_pressed && ++m_currentIndex>=4)
{
if (m_numbers == settings.lockscreen.pin)
{
espgui::switchScreen<MainMenu>();
if (!gas || !brems || *gas > 200.f || *brems > 200.f)
espgui::switchScreen<CalibrateDisplay>(true);
else
espgui::switchScreen<MainMenu>();
#ifdef LOCKSCREEN_PLUGIN
#pragma message "Activating Lockscreen Plugin"
#include LOCKSCREEN_PLUGIN
@ -83,7 +92,12 @@ void Lockscreen::redraw()
m_numbers = {0,0,0,0};
m_currentIndex = 0;
std::for_each(std::begin(m_labels) + 1, std::end(m_labels), [](auto &label){ label.redraw({}); });
std::for_each(std::begin(m_labels) + 1, std::end(m_labels), [](auto &label){ label.redraw("0"); });
}
else if (m_back_pressed && m_currentIndex < 3)
{
drawRect(m_currentIndex+1, 1, TFT_BLACK);
drawRect(m_currentIndex+1, 2, TFT_BLACK);
}
m_labels[m_currentIndex].redraw(std::to_string(m_numbers[m_currentIndex]));
@ -92,6 +106,7 @@ void Lockscreen::redraw()
drawRect(m_currentIndex, 2, TFT_YELLOW);
m_pressed = false;
m_back_pressed = false;
}
if (m_rotated)
@ -124,6 +139,14 @@ void Lockscreen::stop()
profileButtonDisabled = false;
isLocked = false;
if (!(!gas || !brems || *gas > 200.f || *brems > 200.f))
{
if (settings.lockscreen.keepLockedAfterReboot && settings.lockscreen.locked)
{
settings.lockscreen.locked = false;
saveSettings();
}
}
}
void Lockscreen::confirm()
@ -133,6 +156,9 @@ void Lockscreen::confirm()
void Lockscreen::back()
{
if (m_currentIndex > 0)
m_currentIndex--;
m_back_pressed = true;
}
void Lockscreen::rotate(int offset)

View File

@ -46,6 +46,7 @@ private:
uint8_t m_currentIndex{};
bool m_pressed;
bool m_back_pressed;
int m_rotated;
ModeInterface *m_oldMode;

View File

@ -0,0 +1,33 @@
#include "accesspointwifisettingsmenu.h"
// local includes
#include "accessors/settingsaccessors.h"
#include "actions/dummyaction.h"
#include "actions/switchscreenaction.h"
#include "actions/toggleboolaction.h"
#include "checkboxicon.h"
#include "displays/menus/wifisettingsmenu.h"
#include "icons/back.h"
#include "menuitem.h"
#include "wifitexthelpers.h"
using namespace espgui;
AccessPointWifiSettingsMenu::AccessPointWifiSettingsMenu()
{
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_WIFIAPENABLED>, ToggleBoolAction, CheckboxIcon, WifiApEnabledAccessor>>();
constructMenuItem<makeComponent<MenuItem, WifiSoftApGetStationNumText, StaticFont<2>, DisabledColor, DummyAction>>();
constructMenuItem<makeComponent<MenuItem, WifiSoftApIpText, StaticFont<2>, DisabledColor, DummyAction>>();
constructMenuItem<makeComponent<MenuItem, WifiSoftApBroadcastIpText, StaticFont<2>, DisabledColor, DummyAction>>();
constructMenuItem<makeComponent<MenuItem, WifiSoftApNetworkIdText, StaticFont<2>, DisabledColor, DummyAction>>();
constructMenuItem<makeComponent<MenuItem, WifiSoftApSubnetCidrText, StaticFont<2>, DisabledColor, DummyAction>>();
constructMenuItem<makeComponent<MenuItem, WifiSoftApIpV6Text, StaticFont<2>, DisabledColor, DummyAction>>();
constructMenuItem<makeComponent<MenuItem, WifiSoftApHostnameText, StaticFont<2>, DisabledColor, DummyAction>>();
constructMenuItem<makeComponent<MenuItem, WifiSoftApMacAddressText, StaticFont<2>, DisabledColor, DummyAction>>();
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_BACK>, SwitchScreenAction<WifiSettingsMenu>, StaticMenuItemIcon<&espgui::icons::back>>>();
}
void AccessPointWifiSettingsMenu::back()
{
switchScreen<WifiSettingsMenu>();
}

View File

@ -2,37 +2,13 @@
// local includes
#include "menudisplay.h"
#include "menuitem.h"
#include "actions/dummyaction.h"
#include "actions/switchscreenaction.h"
#include "actions/toggleboolaction.h"
#include "checkboxicon.h"
#include "icons/back.h"
#include "wifitexthelpers.h"
#include "accessors/settingsaccessors.h"
#include "texts.h"
using namespace espgui;
namespace {
class AccessPointWifiSettingsMenu :
public MenuDisplay,
public StaticText<TEXT_ACCESSPOINTWIFISETTINGS>,
public BackActionInterface<SwitchScreenAction<WifiSettingsMenu>>
public espgui::MenuDisplay,
public espgui::StaticText<TEXT_ACCESSPOINTWIFISETTINGS>
{
public:
AccessPointWifiSettingsMenu()
{
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_WIFIAPENABLED>, ToggleBoolAction, CheckboxIcon, WifiApEnabledAccessor>>();
constructMenuItem<makeComponent<MenuItem, WifiSoftApGetStationNumText, StaticFont<2>, DisabledColor, DummyAction>>();
constructMenuItem<makeComponent<MenuItem, WifiSoftApIpText, StaticFont<2>, DisabledColor, DummyAction>>();
constructMenuItem<makeComponent<MenuItem, WifiSoftApBroadcastIpText, StaticFont<2>, DisabledColor, DummyAction>>();
constructMenuItem<makeComponent<MenuItem, WifiSoftApNetworkIdText, StaticFont<2>, DisabledColor, DummyAction>>();
constructMenuItem<makeComponent<MenuItem, WifiSoftApSubnetCidrText, StaticFont<2>, DisabledColor, DummyAction>>();
constructMenuItem<makeComponent<MenuItem, WifiSoftApIpV6Text, StaticFont<2>, DisabledColor, DummyAction>>();
constructMenuItem<makeComponent<MenuItem, WifiSoftApHostnameText, StaticFont<2>, DisabledColor, DummyAction>>();
constructMenuItem<makeComponent<MenuItem, WifiSoftApMacAddressText, StaticFont<2>, DisabledColor, DummyAction>>();
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_BACK>, SwitchScreenAction<WifiSettingsMenu>, StaticMenuItemIcon<&espgui::icons::back>>>();
}
AccessPointWifiSettingsMenu();
void back() override;
};
} // namespace

View File

@ -19,6 +19,7 @@
#include "icons/battery.h"
#include "debugcolorhelpers.h"
#include "esptexthelpers.h"
#include "displays/qrcodedebug.h"
#include "displays/menus/commanddebugmenu.h"
#include "displays/menus/motorstatedebugmenu.h"
#include "displays/menus/feedbackdebugmenu.h"
@ -47,6 +48,7 @@ using namespace espgui;
DebugMenu::DebugMenu()
{
constructMenuItem<AlertAction>();
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_QRCODE_DEBUG>, SwitchScreenAction<QrCodeDebugDisplay>>>();
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_LOADSETTINGS>, LoadSettingsAction>>();
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_SAVESETTINGS>, SaveSettingsAction>>();
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_ERASENVS>, EraseNvsAction>>();

View File

@ -0,0 +1,31 @@
#include "espnowmenu.h"
#ifdef FEATURE_ESPNOW
#include "actions/dummyaction.h"
#include "actions/switchscreenaction.h"
#include "actions/toggleboolaction.h"
#include "checkboxicon.h"
#include "icons/back.h"
#include "icons/settings.h"
#include "icons/time.h"
#include "displays/menus/espnowsettingsmenu.h"
#include "displays/menus/settingsmenu.h"
using namespace espgui;
namespace espnowmenu {
} // namespace
EspNowMenu::EspNowMenu() {
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_ESPNOW_SENDTSMSG>, espnowmenu::SendBobbycarTimesyncMessageAction, StaticMenuItemIcon<&bobbyicons::time>>>();
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_ESPNOW_RECEIVETS>, ToggleBoolAction, CheckboxIcon, espnowmenu::ReceiveTimeStampAccessor>>();
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_ESPNOW_RECEIVETSFROMBOBBY>, ToggleBoolAction, CheckboxIcon, espnowmenu::ReceiveTsFromOtherBobbycarsAccessor>>();
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_ESPNOW_SETTINGS>, SwitchScreenAction<EspNowSettingsMenu>, StaticMenuItemIcon<&bobbyicons::settings>>>();
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_BACK>, SwitchScreenAction<SettingsMenu>, StaticMenuItemIcon<&espgui::icons::back>>>();
}
void EspNowMenu::back()
{
switchScreen<SettingsMenu>();
}
#endif

View File

@ -0,0 +1,42 @@
#pragma once
#ifdef FEATURE_ESPNOW
#include <accessorinterface.h>
#include <actioninterface.h>
#include <espchrono.h>
#include <fmt/core.h>
#include <menudisplay.h>
#include <textinterface.h>
#include <texts.h>
#include "espnowfunctions.h"
using namespace espgui;
namespace espnowmenu {
struct ReceiveTimeStampAccessor : public RefAccessor<bool> { bool &getRef() const override { return espnow::receiveTimeStamp; } };
struct ReceiveTsFromOtherBobbycarsAccessor : public RefAccessor<bool> { bool &getRef() const override { return espnow::receiveTsFromOtherBobbycars; } };
class SendBobbycarTimesyncMessageAction : public virtual ActionInterface {
public:
void triggered() override
{
const auto message = fmt::format("BOBBYT:{}", espchrono::utc_clock::now().time_since_epoch().count());
espnow::send_espnow_message(message);
}
};
} // namespace
class EspNowMenu :
public espgui::MenuDisplay,
public espgui::StaticText<TEXT_ESPNOW_MENU>
{
public:
EspNowMenu();
void back() override;
};
#endif

View File

@ -0,0 +1,29 @@
#include "espnowsettingsmenu.h"
#ifdef FEATURE_ESPNOW
#include "accessors/settingsaccessors.h"
#include "actions/dummyaction.h"
#include "actions/switchscreenaction.h"
#include "actions/toggleboolaction.h"
#include "checkboxicon.h"
#include "icons/back.h"
#include "icons/time.h"
#include "espnowmenu.h"
using namespace espgui;
namespace espnowsettingsmenu {
} // namespace
EspNowSettingsMenu::EspNowSettingsMenu() {
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_ESPNOW_SYNCTIME>, ToggleBoolAction, CheckboxIcon, ESPNowSyncTimeEnabledAccessor>>();
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_ESPNOW_SYNCWITHOTHERS>, ToggleBoolAction, CheckboxIcon, ESPNowSyncTimeWithOthersEnabledAccessor>>();
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_ESPNOW_SYNCBLINK>, ToggleBoolAction, CheckboxIcon, ESPNowSyncBlinkEnabledAccessor>>();
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_BACK>, SwitchScreenAction<EspNowMenu>, StaticMenuItemIcon<&espgui::icons::back>>>();
}
void EspNowSettingsMenu::back()
{
switchScreen<EspNowMenu>();
}
#endif

View File

@ -0,0 +1,29 @@
#pragma once
#ifdef FEATURE_ESPNOW
#include <accessorinterface.h>
#include <actioninterface.h>
#include <espchrono.h>
#include <fmt/core.h>
#include <menudisplay.h>
#include <textinterface.h>
#include <texts.h>
#include "espnowfunctions.h"
using namespace espgui;
namespace espnowsettingsmenu {
} // namespace
class EspNowSettingsMenu :
public espgui::MenuDisplay,
public espgui::StaticText<TEXT_ESPNOW_SETTINGS>
{
public:
EspNowSettingsMenu();
void back() override;
};
#endif

View File

@ -10,6 +10,7 @@
#include "texts.h"
#include "debugtexthelpers.h"
#include "debugcolorhelpers.h"
#include "displays/menus/debugmenu.h"
using namespace espgui;

View File

@ -0,0 +1,49 @@
#include "greenpassmenu.h"
#include <actioninterface.h>
// local includes
#include "actions/switchscreenaction.h"
#include "displays/menus/mainmenu.h"
#include "icons/back.h"
using namespace espgui;
namespace greenpassmenu {
bool showingQRCode{false};
} // namespace
void GreenPassMenu::ShowCertAction::triggered() {
greenpassmenu::showingQRCode = true;
m_qrcode.init();
m_qrcode.createScaleToFit("");
}
GreenPassMenu::GreenPassMenu()
{
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_SHOWCERT>, ShowCertAction>>();
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_BACK>, SwitchScreenAction<MainMenu>, StaticMenuItemIcon<&espgui::icons::back>>>();
}
void GreenPassMenu::initScreen()
{
Base::initScreen();
greenpassmenu::showingQRCode = false;
}
void GreenPassMenu::rotate(int offset)
{
if (greenpassmenu::showingQRCode)
GreenPassMenu::initScreen();
Base::rotate(offset);
}
void GreenPassMenu::back()
{
if (greenpassmenu::showingQRCode)
{
GreenPassMenu::initScreen();
}
else
switchScreen<MainMenu>();
}

View File

@ -0,0 +1,30 @@
#pragma once
#include <qrcode.h>
// local includes
#include "menudisplay.h"
#include "texts.h"
namespace greenpassmenu {
extern bool showingQRCode;
} // namespace
class GreenPassMenu :
public espgui::MenuDisplay,
public espgui::StaticText<TEXT_GREENPASS>
{
using Base = espgui::MenuDisplay;
public:
GreenPassMenu();
void back() override;
void rotate(int offset) override;
void initScreen() override;
class ShowCertAction : public virtual espgui::ActionInterface {
public:
void triggered() override;
private:
qrcode::QRcode m_qrcode{};
};
};

View File

@ -1,28 +1,30 @@
#include "ledstripmenu.h"
#ifdef FEATURE_LEDSTRIP
// 3rdparty lib includes
#include <FastLED.h>
#include "menuitem.h"
#include "actions/toggleboolaction.h"
#include "actions/switchscreenaction.h"
#include "icons/back.h"
#include "checkboxicon.h"
#include "changevaluedisplay.h"
#include "actioninterface.h"
#include <actioninterface.h>
#include <actions/switchscreenaction.h>
#include <actions/toggleboolaction.h>
#include <changevaluedisplay.h>
#include <checkboxicon.h>
#include <icons/back.h>
#include <menuitem.h>
// local includes
#include "accessors/settingsaccessors.h"
#include "displays/ledstripcolorsdisplay.h"
#include "displays/menus/ledstripselectotamode.h"
#include "displays/menus/mainmenu.h"
#include "globals.h"
#include "ledstrip.h"
#include "ledstripselectanimationmenu.h"
#include "ledstripselectblinkmenu.h"
#include "globals.h"
#include "accessors/settingsaccessors.h"
#ifdef FEATURE_LEDSTRIP
#include "ledstrip.h"
#include "displays/menus/ledstripselectotamode.h"
#endif
#include "displays/ledstripcolorsdisplay.h"
#include "displays/menus/mainmenu.h"
#ifdef FEATURE_LEDSTRIP
// clang-format off
using namespace espgui;
namespace {
using LedsCountChangeScreen = makeComponent<
ChangeValueDisplay<int16_t>,
@ -109,8 +111,6 @@ public:
};
} // namespace
using namespace espgui;
LedstripMenu::LedstripMenu()
{
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_LEDSTRIPCOLORMENU>, SwitchScreenAction<LedstripColorsDisplay>>>();

View File

@ -1,14 +1,14 @@
#pragma once
// 3rdparty lib includes
#include "menudisplay.h"
#include "widgets/menudisplaywithtime.h"
// local includes
#include "texts.h"
#ifdef FEATURE_LEDSTRIP
class LedstripMenu :
public espgui::MenuDisplay,
public bobbygui::MenuDisplayWithTime,
public espgui::StaticText<TEXT_LEDSTRIP>
{
public:

View File

@ -0,0 +1,53 @@
#include "ledstripselectblinkmenu.h"
#ifdef FEATURE_LEDSTRIP
// Local includes
#include "accessors/settingsaccessors.h"
#include "actions/dummyaction.h"
#include "actions/ledstripblinkactions.h"
#include "actions/switchscreenaction.h"
#include "actions/toggleboolaction.h"
#include "checkboxicon.h"
#include "displays/menus/ledstripmenu.h"
#include "icons/back.h"
using namespace espgui;
std::string currentSelectedBlinkAnimationText::text() const {
switch (blinkAnimation) {
case LEDSTRIP_OVERWRITE_BLINKLEFT:
#ifndef LEDSTRIP_WRONG_DIRECTION
return TEXT_ANIMATION_BLINKLEFT;
#else
return TEXT_ANIMATION_BLINKRIGHT;
#endif
case LEDSTRIP_OVERWRITE_BLINKRIGHT:
#ifndef LEDSTRIP_WRONG_DIRECTION
return TEXT_ANIMATION_BLINKRIGHT;
#else
return TEXT_ANIMATION_BLINKLEFT;
#endif
case LEDSTRIP_OVERWRITE_BLINKBOTH:
return TEXT_ANIMATION_BLINKBOTH;
default:
return TEXT_ANIMATION_BLINKNONE;
}
}
LedstripSelectBlinkMenu::LedstripSelectBlinkMenu()
{
constructMenuItem<makeComponent<MenuItem, currentSelectedBlinkAnimationText, DisabledColor, DummyAction>>();
constructMenuItem<makeComponent<MenuItem, EmptyText, DummyAction>>();
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_ANIMATION_BLINKNONE>, LedstripAnimationBlinkNoneAction>>();
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_ANIMATION_BLINKLEFT>, LedstripAnimationBlinkLeftAction>>();
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_ANIMATION_BLINKRIGHT>, LedstripAnimationBlinkRightAction>>();
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_ANIMATION_BLINKBOTH>, LedstripAnimationBlinkBothAction>>();
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_LEDSTRIP_EN_BLINK_ANIM>, ToggleBoolAction, CheckboxIcon, LedstripEnableBlinkAnimationAccessor>>();
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_BACK>, SwitchScreenAction<LedstripMenu>, StaticMenuItemIcon<&espgui::icons::back>>>();
}
void LedstripSelectBlinkMenu::back()
{
switchScreen<LedstripMenu>();
}
#endif

View File

@ -2,64 +2,22 @@
// Local includes
#include "menudisplay.h"
#include "utils.h"
#include "menuitem.h"
#include "ledstrip.h"
#include "ledstripselectanimationmenu.h"
#include "icons/back.h"
#include "texts.h"
#include "actions/dummyaction.h"
#include "actions/ledstripblinkactions.h"
#include "actions/switchscreenaction.h"
#include "actions/toggleboolaction.h"
#include "checkboxicon.h"
#include "ledstrip.h"
#include "ledstripdefines.h"
#include "accessors/settingsaccessors.h"
#include "ledstripmenu.h"
#ifdef FEATURE_LEDSTRIP
class currentSelectedBlinkAnimationText : public virtual TextInterface { public: std::string text() const override {
switch (blinkAnimation) {
case LEDSTRIP_OVERWRITE_BLINKLEFT:
#ifndef LEDSTRIP_WRONG_DIRECTION
return TEXT_ANIMATION_BLINKLEFT;
#else
return TEXT_ANIMATION_BLINKRIGHT;
#endif
case LEDSTRIP_OVERWRITE_BLINKRIGHT:
#ifndef LEDSTRIP_WRONG_DIRECTION
return TEXT_ANIMATION_BLINKRIGHT;
#else
return TEXT_ANIMATION_BLINKLEFT;
#endif
case LEDSTRIP_OVERWRITE_BLINKBOTH:
return TEXT_ANIMATION_BLINKBOTH;
default:
return TEXT_ANIMATION_BLINKNONE;
}
};
class currentSelectedBlinkAnimationText : public virtual espgui::TextInterface
{
public: std::string text() const override;
};
using namespace espgui;
namespace {
class LedstripSelectBlinkMenu :
public MenuDisplay,
public StaticText<TEXT_BLINKANIMATION>,
public BackActionInterface<SwitchScreenAction<LedstripMenu>>
{
public:
LedstripSelectBlinkMenu()
{
constructMenuItem<makeComponent<MenuItem, currentSelectedBlinkAnimationText, DisabledColor, DummyAction>>();
constructMenuItem<makeComponent<MenuItem, EmptyText, DummyAction>>();
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_ANIMATION_BLINKNONE>, LedstripAnimationBlinkNoneAction>>();
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_ANIMATION_BLINKLEFT>, LedstripAnimationBlinkLeftAction>>();
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_ANIMATION_BLINKRIGHT>, LedstripAnimationBlinkRightAction>>();
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_ANIMATION_BLINKBOTH>, LedstripAnimationBlinkBothAction>>();
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_LEDSTRIP_EN_BLINK_ANIM>, ToggleBoolAction, CheckboxIcon, LedstripEnableBlinkAnimationAccessor>>();
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_BACK>, SwitchScreenAction<LedstripMenu>, StaticMenuItemIcon<&espgui::icons::back>>>();
}
};
} // Namespace
class LedstripSelectBlinkMenu :
public espgui::MenuDisplay,
public espgui::StaticText<TEXT_BLINKANIMATION>
{
public:
LedstripSelectBlinkMenu();
void back() override;
};
#endif

View File

@ -0,0 +1,24 @@
#include "ledstripselectotamode.h"
#include "actions/switchscreenaction.h"
#include "icons/back.h"
#include "ledstripmenu.h"
// Local includes
#if defined(FEATURE_LEDSTRIP) && defined(FEATURE_OTA)
using namespace espgui;
ledstripOtaAnimationChangeMenu::ledstripOtaAnimationChangeMenu()
{
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_OTAANIM_NONE>, LedstripChangeOtaAnimModeAction<OtaAnimationModes::None>>>();
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_OTAANIM_PROGRESS>, LedstripChangeOtaAnimModeAction<OtaAnimationModes::GreenProgressBar>>>();
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_OTAANIM_COLOR>, LedstripChangeOtaAnimModeAction<OtaAnimationModes::ColorChangeAll>>>();
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_BACK>, SwitchScreenAction<LedstripMenu>, StaticMenuItemIcon<&espgui::icons::back>>>();
}
void ledstripOtaAnimationChangeMenu::back()
{
switchScreen<LedstripMenu>();
}
#endif

View File

@ -2,20 +2,15 @@
// Local includes
#include "menudisplay.h"
#include "utils.h"
#include "menuitem.h"
#include "ledstrip.h"
#include "icons/back.h"
#include "texts.h"
#include "actions/switchscreenaction.h"
#include "accessors/settingsaccessors.h"
#include "ledstripmenu.h"
#include "ledstrip.h"
#include "globals.h"
#include "utils.h"
#if defined(FEATURE_LEDSTRIP) && defined(FEATURE_OTA)
using namespace espgui;
template <OtaAnimationModes mode>
class LedstripChangeOtaAnimModeAction : public virtual ActionInterface
class LedstripChangeOtaAnimModeAction : public virtual espgui::ActionInterface
{
public:
void triggered() override
@ -25,20 +20,12 @@ public:
}
};
namespace {
class ledstripOtaAnimationChangeMenu :
public MenuDisplay,
public StaticText<TEXT_BLINKANIMATION>,
public BackActionInterface<SwitchScreenAction<LedstripMenu>>
{
public:
ledstripOtaAnimationChangeMenu()
{
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_OTAANIM_NONE>, LedstripChangeOtaAnimModeAction<OtaAnimationModes::None>>>();
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_OTAANIM_PROGRESS>, LedstripChangeOtaAnimModeAction<OtaAnimationModes::GreenProgressBar>>>();
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_OTAANIM_COLOR>, LedstripChangeOtaAnimModeAction<OtaAnimationModes::ColorChangeAll>>>();
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_BACK>, SwitchScreenAction<LedstripMenu>, StaticMenuItemIcon<&espgui::icons::back>>>();
}
};
} // Namespace
class ledstripOtaAnimationChangeMenu :
public espgui::MenuDisplay,
public espgui::StaticText<TEXT_BLINKANIMATION>
{
public:
ledstripOtaAnimationChangeMenu();
void back() override;
};
#endif

View File

@ -52,6 +52,7 @@ using namespace espgui;
LockscreenSettingsMenu::LockscreenSettingsMenu()
{
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_ALLOWPRESETSWITCH>, ToggleBoolAction, CheckboxIcon, LockscreenAllowPresetSwitchAccessor>>();
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_KEEPLOCKED>, ToggleBoolAction, CheckboxIcon, LockscreenKeepLockedAccessor>>();
constructMenuItem<makeComponent<MenuItem, TextWithValueHelper<TEXT_PINDIGIT0, LockscreenPinDigitAccessor<0>>, SwitchScreenAction<LockscreenPinDigit0ChangeScreen>>>();
constructMenuItem<makeComponent<MenuItem, TextWithValueHelper<TEXT_PINDIGIT1, LockscreenPinDigitAccessor<1>>, SwitchScreenAction<LockscreenPinDigit1ChangeScreen>>>();
constructMenuItem<makeComponent<MenuItem, TextWithValueHelper<TEXT_PINDIGIT2, LockscreenPinDigitAccessor<2>>, SwitchScreenAction<LockscreenPinDigit2ChangeScreen>>>();

View File

@ -19,6 +19,7 @@
#include "displays/menus/settingsmenu.h"
#include "displays/menus/mosfetsmenu.h"
#include "displays/menus/demosmenu.h"
#include "displays/menus/greenpassmenu.h"
#include "displays/lockscreen.h"
#include "displays/garagedisplay.h"
#include "displays/menus/otamenu.h"
@ -45,11 +46,28 @@
#include "icons/poweroff.h"
#include "icons/reboot.h"
#include "icons/statistics.h"
#include "icons/greenpass.h"
#include "icons/time.h"
#include "tftinstance.h"
using namespace espgui;
namespace mainmenu {
/*
class CurrentTimeText : public virtual TextInterface
{
public:
std::string text() const override
{
return fmt::format("&7Time: {}", local_clock_string());
}
};
*/
} // namespace
MainMenu::MainMenu()
{
// constructMenuItem<makeComponent<MenuItem, mainmenu::CurrentTimeText, DummyAction, StaticMenuItemIcon<&bobbyicons::time>>>();
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_STATUS>, SwitchScreenAction<StatusDisplay>, StaticMenuItemIcon<&espgui::icons::back>>>();
#ifdef FEATURE_LEDSTRIP
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_LEDSTRIP>, SwitchScreenAction<LedstripMenu>, StaticMenuItemIcon<&bobbyicons::neopixel>>>();
@ -72,6 +90,7 @@ MainMenu::MainMenu()
if (SHOWITEM) { constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_MOSFETS>, SwitchScreenAction<MosfetsMenu>>>(); }
#endif
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_DEMOS>, SwitchScreenAction<DemosMenu>, StaticMenuItemIcon<&bobbyicons::demos>>>();
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_GREENPASS>, SwitchScreenAction<GreenPassMenu>, StaticMenuItemIcon<&bobbyicons::greenpass>>>();
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_LOCKVEHICLE>, SwitchScreenAction<Lockscreen>, StaticMenuItemIcon<&bobbyicons::lock>>>();
#ifdef FEATURE_GARAGE
if (SHOWITEM) { constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_GARAGE>, SwitchScreenAction<GarageDisplay>>>(); }

View File

@ -1,11 +1,11 @@
#pragma once
// 3rdparty lib includes
#include "menudisplay.h"
#include "menuitem.h"
// local includes
#include "texts.h"
#include "widgets/menudisplaywithtime.h"
#ifdef MAINMENU_PLUGIN
#include MAINMENU_PLUGIN
#endif
@ -22,11 +22,11 @@ namespace {
} // namespace
class MainMenu :
public espgui::MenuDisplay,
public bobbygui::MenuDisplayWithTime,
public espgui::StaticText<TEXT_MAINMENU>
{
using Base = espgui::MenuDisplay;
public:
MainMenu();
void back() override;
};

View File

@ -0,0 +1,26 @@
#include "mosfetsmenu.h"
#ifdef FEATURE_MOSFETS
#include "actions/switchscreenaction.h"
#include "actions/toggleboolaction.h"
#include "checkboxicon.h"
#include "displays/menus/mainmenu.h"
#include "icons/back.h"
using namespace espgui;
MosfetsMenu::MosfetsMenu()
{
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_MOSFET0>, ToggleBoolAction, CheckboxIcon, Mosfet0Accessor>>();
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_MOSFET1>, ToggleBoolAction, CheckboxIcon, Mosfet1Accessor>>();
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_MOSFET2>, ToggleBoolAction, CheckboxIcon, Mosfet2Accessor>>();
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_BACK>, SwitchScreenAction<MainMenu>, StaticMenuItemIcon<&espgui::icons::back>>>();
}
void MosfetsMenu::back()
{
switchScreen<MainMenu>();
}
#endif

View File

@ -1,22 +1,13 @@
#pragma once
// local includes
#ifdef FEATURE_MOSFETS
#include "menudisplay.h"
#include "utils.h"
#include "menuitem.h"
#include "actions/toggleboolaction.h"
#include "actions/switchscreenaction.h"
#include "checkboxicon.h"
#include "icons/back.h"
#include "accessorinterface.h"
#include "texts.h"
#include "types.h"
using namespace espgui;
namespace {
#ifdef FEATURE_MOSFETS
template<pin_t PIN>
class GPIOAccessor : public virtual AccessorInterface<bool>
class GPIOAccessor : public virtual espgui::AccessorInterface<bool>
{
public:
bool getValue() const override { return digitalRead(PIN); }
@ -28,18 +19,11 @@ using Mosfet1Accessor = GPIOAccessor<PINS_MOSFET1>;
using Mosfet2Accessor = GPIOAccessor<PINS_MOSFET2>;
class MosfetsMenu :
public MenuDisplay,
public StaticText<TEXT_MOSFETS>,
public BackActionInterface<SwitchScreenAction<MainMenu>>
public espgui::MenuDisplay,
public espgui::StaticText<TEXT_MOSFETS>
{
public:
MosfetsMenu()
{
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_MOSFET0>, ToggleBoolAction, CheckboxIcon, Mosfet0Accessor>>();
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_MOSFET1>, ToggleBoolAction, CheckboxIcon, Mosfet1Accessor>>();
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_MOSFET2>, ToggleBoolAction, CheckboxIcon, Mosfet2Accessor>>();
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_BACK>, SwitchScreenAction<MainMenu>, StaticMenuItemIcon<&espgui::icons::back>>>();
}
MosfetsMenu();
void back() override;
};
#endif
} // namespace

View File

@ -10,7 +10,7 @@
// local includes
#include "actions/dummyaction.h"
#include "buildserver.h"
#include "displays/menus/settingsmenu.h"
#include "displays/menus/otamenu.h"
#include "utils.h"
#ifdef FEATURE_OTA
@ -67,11 +67,11 @@ SelectBuildServerMenu::SelectBuildServerMenu()
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_NOBUILDSERVERCONFIGURED>, DefaultFont, StaticColor<TFT_RED>, DummyAction>>();
}
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_BACK>, SwitchScreenAction<SettingsMenu>, StaticMenuItemIcon<&espgui::icons::back>>>();
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_BACK>, SwitchScreenAction<OtaMenu>, StaticMenuItemIcon<&espgui::icons::back>>>();
}
void SelectBuildServerMenu::back()
{
espgui::switchScreen<SettingsMenu>();
espgui::switchScreen<OtaMenu>();
}
#endif

View File

@ -28,6 +28,7 @@
#include "displays/menus/bluetoothsettingsmenu.h"
#include "displays/menus/blesettingsmenu.h"
#include "displays/menus/cloudsettingsmenu.h"
#include "displays/menus/espnowmenu.h"
#include "displays/menus/selectbuildservermenu.h"
#include "displays/menus/timesettingsmenu.h"
#include "displays/menus/modessettingsmenu.h"
@ -61,6 +62,9 @@ SettingsMenu::SettingsMenu()
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_LIMITSSETTINGS>, SwitchScreenAction<LimitsSettingsMenu>>>();
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_WIFISETTINGS>, SwitchScreenAction<WifiSettingsMenu>, StaticMenuItemIcon<&bobbyicons::wifi>>>();
#ifdef FEATURE_ESPNOW
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_ESPNOW>, SwitchScreenAction<EspNowMenu>, StaticMenuItemIcon<&bobbyicons::wifi>>>();
#endif
#ifdef FEATURE_BLUETOOTH
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_BLUETOOTHSETTINGS>, SwitchScreenAction<BluetoothSettingsMenu>, StaticMenuItemIcon<&bobbyicons::bluetooth>>>();
#endif

View File

@ -1,13 +1,13 @@
#pragma once
// 3rdparty lib includes
#include "menudisplay.h"
#include "widgets/menudisplaywithtime.h"
// local includes
#include "texts.h"
class SettingsMenu :
public espgui::MenuDisplay,
public bobbygui::MenuDisplayWithTime,
public espgui::StaticText<TEXT_SETTINGS>
{
public:

View File

@ -3,9 +3,11 @@
// local includes
#include "mainmenu.h"
#include "actions/dummyaction.h"
#include "actions/switchscreenaction.h"
#include "actioninterface.h"
#include "fmt/core.h"
#include "utils.h"
#include "icons/back.h"
#include "icons/time.h"
#include "icons/reboot.h"
#include "icons/update.h"

View File

@ -1,18 +1,14 @@
#pragma once
// 3rdparty lib includes
#include <menudisplay.h>
#include "widgets/menudisplaywithtime.h"
#include <menuitem.h>
#include <icons/back.h>
#include <actions/dummyaction.h>
#include <actions/switchscreenaction.h>
// Local includes
#include "utils.h"
#include "texts.h"
class StatisticsMenu :
public espgui::MenuDisplay,
public bobbygui::MenuDisplayWithTime,
public espgui::StaticText<TEXT_STATISTICSMENU>
{
public:

View File

@ -37,7 +37,8 @@ public:
#ifdef CONFIG_ESPCHRONO_SUPPORT_DEFAULT_TIMEZONE
return fmt::format("local: {}", espchrono::toString(espchrono::toDateTime(espchrono::local_clock::now())));
#else
return "TODO";
// Crude local time implementation
return fmt::format("local: {}", espchrono::toString(espchrono::toDateTime(espchrono::utc_clock::now() + settings.timeSettings.timezoneOffset)));
#endif
}
};

View File

@ -1,13 +1,13 @@
#pragma once
// 3rdparty lib includes
#include "menudisplay.h"
#include "widgets/menudisplaywithtime.h"
// local includes
#include "texts.h"
class TimeSettingsMenu :
public espgui::MenuDisplay,
public bobbygui::MenuDisplayWithTime,
public espgui::StaticText<TEXT_TIME>
{
public:

View File

@ -0,0 +1,36 @@
#include "qrcodedebug.h"
#include <fmt/core.h>
#include "displays/menus/debugmenu.h"
#include "globals.h"
#include "screenmanager.h"
using namespace espgui;
QrCodeDebugDisplay::QrCodeDebugDisplay()
{
}
void QrCodeDebugDisplay::back()
{
switchScreen<DebugMenu>();
}
void QrCodeDebugDisplay::initScreen()
{
Base::initScreen();
m_qrcode.init();
}
void QrCodeDebugDisplay::confirm()
{
m_qrcode.createScaleToFit(fmt::format("WIFI:T:WPA;S:{};P:{};", deviceName, stringSettings.ap_password));
}
void QrCodeDebugDisplay::rotate(int offset)
{
m_mult += offset;
m_qrcode.setMultiply(m_mult);
m_qrcode.create("Hello World!");
}

View File

@ -0,0 +1,21 @@
#pragma once
// 3rdparty lib includes
#include <display.h>
#include <qrcode.h>
class QrCodeDebugDisplay :
public espgui::Display
{
using Base = espgui::Display;
public:
QrCodeDebugDisplay();
// std::string text() const override;
void initScreen() override;
void confirm() override;
void back() override;
void rotate(int offset) override;
private:
qrcode::QRcode m_qrcode{};
uint8_t m_mult{2};
};

View File

@ -11,6 +11,7 @@
#include "dpad.h"
#include "buttons.h"
#include "types.h"
#include "globals.h"
namespace {
namespace dpad3wire

View File

@ -13,6 +13,7 @@
// local includes
#include "buttons.h"
#include "types.h"
#include "globals.h"
namespace {
namespace dpad5wire {

View File

@ -13,6 +13,7 @@
// local includes
#include "buttons.h"
#include "types.h"
#include "globals.h"
namespace {
namespace dpad5wire_2out {

View File

@ -12,6 +12,7 @@
// local includes
#include "buttons.h"
#include "types.h"
#include "globals.h"
namespace {
namespace dpad6wire {

290
main/espnowfunctions.cpp Normal file
View File

@ -0,0 +1,290 @@
#ifdef FEATURE_ESPNOW
#include "espnowfunctions.h"
#include <string>
#include <espchrono.h>
#include <esp_log.h>
#include <numberparsing.h>
#include <espwifistack.h>
#include "globals.h"
#include "utils.h"
#include "time_bobbycar.h"
namespace espnow {
namespace {
constexpr const char * const TAG = "BOBBY_ESP_NOW";
} // namespace
uint16_t lastYear; // Used for esp-now timesync
std::deque<esp_now_message_t> message_queue{};
std::vector<esp_now_peer_info_t> peers{};
uint8_t initialized{0};
bool receiveTimeStamp{true};
bool receiveTsFromOtherBobbycars{true};
namespace {
extern "C" void onReceive(const uint8_t *mac_addr, const uint8_t *data, int data_len)
{
ESP_LOGD(TAG, "Received data");
const std::string_view data_str{(const char *)data, size_t(data_len)};
size_t sep_pos = data_str.find(":");
if (std::string_view::npos != sep_pos)
{
std::string_view msg_type = data_str.substr(0, sep_pos);
std::string_view msg = data_str.substr(sep_pos+1, data_str.length()-3); // - 3 may needs to be converted to sep_pos+1
ESP_LOGD(TAG, "Type: %.*s - Message: %.*s", msg_type.size(), msg_type.data(), msg.size(), msg.data());
message_queue.push_back(esp_now_message_t {
.content = std::string{msg},
.type = std::string{msg_type}
});
}
else
{
ESP_LOGW(TAG, "Invalid message: Could not find ':' (%.*s)", data_str.size(), data_str.data());
}
}
} // namespace
void initESPNow()
{
ESP_LOGI(TAG, "Initializing esp-now...");
if (initialized < 1)
{
if (!settings.wifiSettings.wifiApEnabled && (!settings.wifiSettings.wifiStaEnabled && wifi_stack::get_sta_status() == wifi_stack::WiFiStaStatus::NO_SHIELD) || (wifi_stack::get_wifi_mode() != wifi_mode_t::WIFI_MODE_STA && wifi_stack::get_wifi_mode() != wifi_mode_t::WIFI_MODE_AP && wifi_stack::get_wifi_mode() != wifi_mode_t::WIFI_MODE_APSTA))
{
ESP_LOGW(TAG, "cannot execute esp_now_init(): tcp stack is down.");
return;
}
else
initialized = 1;
}
if (initialized < 2)
{
if (const auto error = esp_now_init(); error != ESP_OK)
{
ESP_LOGE(TAG, "esp_now_init() failed with %s", esp_err_to_name(error));
return;
}
else
initialized = 2;
}
if (initialized < 3)
{
if (const auto error = esp_now_register_recv_cb(onReceive); error != ESP_OK)
{
ESP_LOGE(TAG, "esp_now_register_recv_cb() failed with %s", esp_err_to_name(error));
return;
}
else
initialized = 3;
}
if (initialized < 4)
{
peers.push_back(esp_now_peer_info_t{});
esp_now_peer_info_t &peer = peers.back();
std::memcpy(peer.peer_addr, broadcast_address, sizeof(peer.peer_addr));
peer.channel = 0;
if (settings.wifiSettings.wifiApEnabled)
peer.ifidx = WIFI_IF_AP;
else if (settings.wifiSettings.wifiStaEnabled)
peer.ifidx = WIFI_IF_STA;
else
{
ESP_LOGE(TAG, "Interfaces not ready.");
return;
}
if (const auto error = esp_now_add_peer(&peers.back()); error != ESP_OK)
{
ESP_LOGE(TAG, "esp_now_add_peer() failed with %s", esp_err_to_name(error));
return;
}
else
initialized = 4;
}
initialized = 255;
ESP_LOGI(TAG, "Init done.");
}
void handle()
{
if (initialized < 255 && !(!settings.wifiSettings.wifiApEnabled && (!settings.wifiSettings.wifiStaEnabled && wifi_stack::get_sta_status() == wifi_stack::WiFiStaStatus::NO_SHIELD) || (wifi_stack::get_wifi_mode() != wifi_mode_t::WIFI_MODE_STA && wifi_stack::get_wifi_mode() != wifi_mode_t::WIFI_MODE_AP && wifi_stack::get_wifi_mode() != wifi_mode_t::WIFI_MODE_APSTA)))
{
initESPNow();
return;
}
else if (!settings.wifiSettings.wifiApEnabled && (!settings.wifiSettings.wifiStaEnabled && wifi_stack::get_sta_status() == wifi_stack::WiFiStaStatus::NO_SHIELD) || (wifi_stack::get_wifi_mode() != wifi_mode_t::WIFI_MODE_STA && wifi_stack::get_wifi_mode() != wifi_mode_t::WIFI_MODE_AP && wifi_stack::get_wifi_mode() != wifi_mode_t::WIFI_MODE_APSTA))
{
if (initialized > 0)
{
if (initialized >= 4) // peer
{
for (const auto &peer : peers)
{
if (const auto error = esp_now_del_peer(peer.peer_addr); error != ESP_OK)
{
if (error == ESP_ERR_ESPNOW_NOT_FOUND)
{
initialized = 0;
return;
}
ESP_LOGE(TAG, "esp_now_del_peer() failed with %s", esp_err_to_name(error));
return;
}
}
initialized--;
}
if (initialized >= 3) // callback
{
if (const auto error = esp_now_unregister_recv_cb(); error != ESP_OK)
{
ESP_LOGE(TAG, "esp_now_unregister_recv_cb() failed with %s", esp_err_to_name(error));
return;
}
else if (error == ESP_ERR_ESPNOW_NOT_FOUND)
{
initialized = 0;
}
else
initialized--;
}
if (initialized >= 2) // esp deinit
{
if (const auto error = esp_now_deinit(); error != ESP_OK)
{
ESP_LOGE(TAG, "esp_now_deinit() failed with %s", esp_err_to_name(error));
return;
}
else if (error == ESP_ERR_ESPNOW_NOT_FOUND)
{
initialized = 0;
}
else
initialized--;
}
initialized = 0;
ESP_LOGI(TAG, "Deinit done.");
}
return;
}
if(message_queue.size())
{
for (const esp_now_message_t &msg : message_queue)
{
ESP_LOGD(TAG, "queue has processed message of type '%s' with content '%s'", msg.type.c_str(), msg.content.c_str());
message_queue.pop_front();
if (msg.type == "T")
{
if (!receiveTimeStamp || !settings.espnow.syncTime)
return;
if (const auto result = cpputils::fromString<uint64_t>(msg.content); result)
{
onRecvTs(*result);
}
else
{
ESP_LOGW(TAG, "could not parse number: %.*s", result.error().size(), result.error().data());
}
}
else if (msg.type == "BOBBYT")
{
if (!receiveTsFromOtherBobbycars || !settings.espnow.syncTimeWithOthers)
return;
if (const auto result = cpputils::fromString<uint64_t>(msg.content); result)
{
ESP_LOGI(TAG, "setting current time to %" PRIu64, *result);
onRecvTs(*result, true);
}
else
{
ESP_LOGW(TAG, "could not parse number: %.*s", result.error().size(), result.error().data());
}
}
else
{
ESP_LOGI(TAG, "Unkown Type: %s - Message: %s", msg.type.c_str(), msg.content.c_str());
}
}
}
}
void onRecvTs(uint64_t millis, bool isFromBobbycar)
{
const auto milliseconds = std::chrono::milliseconds(millis);
const auto timepoint = espchrono::utc_clock::time_point(milliseconds);
// ESP_LOGW(TAG, "setting current time to %s", espchrono::toString(timepoint.time_since_epoch()).c_str());
time_set_now(timepoint);
if (receiveTimeStamp)
{
if (const auto thisYear = int(espchrono::toDateTime(espchrono::utc_clock::now()).date.year()); abs(thisYear - espnow::lastYear) > 1)
{
espnow::lastYear = thisYear;
receiveTimeStamp = false;
}
}
receiveTsFromOtherBobbycars = false;
}
esp_err_t send_espnow_message(std::string_view message)
{
if (initialized < 255)
return ESP_ERR_ESPNOW_NOT_INIT;
if (!settings.wifiSettings.wifiApEnabled && !settings.wifiSettings.wifiStaEnabled)
{
return ESP_ERR_ESPNOW_IF;
}
if (peers.size() < 1)
{
return ESP_FAIL;
}
for (auto &peer : peers)
{
if (settings.wifiSettings.wifiApEnabled)
peer.ifidx = WIFI_IF_AP;
else if (settings.wifiSettings.wifiStaEnabled)
peer.ifidx = WIFI_IF_STA;
else
return ESP_ERR_ESPNOW_IF;
const auto timeBefore = espchrono::millis_clock::now();
if(const auto error = esp_now_send(broadcast_address, (const uint8_t*)message.data(), message.size()); error != ESP_OK)
{
return error;
}
else
{
const auto timeAfter = espchrono::millis_clock::now();
ESP_LOGI(TAG, "Successfully executed esp_now_send(): Took %lldms", std::chrono::milliseconds{timeAfter-timeBefore}.count());
}
}
return ESP_OK;
}
} // namespace espnow
#endif

30
main/espnowfunctions.h Normal file
View File

@ -0,0 +1,30 @@
#pragma once
#ifdef FEATURE_ESPNOW
#include <cstdint>
#include <deque>
#include <string>
#include <string_view>
#include <vector>
#include <esp_now.h>
namespace espnow {
extern uint16_t lastYear;
constexpr const uint8_t broadcast_address[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
struct esp_now_message_t
{
std::string content;
std::string type;
};
extern bool receiveTimeStamp;
extern bool receiveTsFromOtherBobbycars;
extern std::deque<esp_now_message_t> message_queue;
extern std::vector<esp_now_peer_info_t> peers;
void initESPNow();
void handle();
void onRecvTs(uint64_t millis, bool isFromBobbycar = false);
esp_err_t send_espnow_message(std::string_view message);
} // namespace espnow
#endif

42
main/icons/greenpass.cpp Normal file
View File

@ -0,0 +1,42 @@
#include "greenpass.h"
namespace bobbyicons {
const espgui::Icon<24, 24> greenpass{{
0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0xF7BE, 0xF7BE, 0x4CAA, 0x4CAA, 0x4CAA, // 0x0010 (16) pixels
0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x6D2E, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, // 0x0020 (32) pixels
0xF7BE, 0x650C, 0x4CAA, 0xF7BE, 0xF7BE, 0x4CAA, 0x6D2E, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0x650D, 0x4CAA, // 0x0030 (48) pixels
0x4CAA, 0x6D2E, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0x650C, 0x4CAA, 0xF7BE, 0xF7BE, 0x4CAA, 0x6D2E, 0xF7BE, // 0x0040 (64) pixels
0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0x650D, 0x4CAA, 0x4CAA, 0x6D2E, 0xF7BE, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, // 0x0050 (80) pixels
0xF7BE, 0x650C, 0x4CAA, 0xF7BE, 0xF7BE, 0x4CAA, 0x6D2E, 0xF7BE, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0xF7BE, 0x650D, 0x4CAA, // 0x0060 (96) pixels
0x4CAA, 0x6D2E, 0xF7BE, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0xF7BE, 0x650C, 0x4CAA, 0xF7BE, 0xF7BE, 0x4CAA, 0x6D2E, 0xF7BE, // 0x0070 (112) pixels
0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0xF7BE, 0x650D, 0x4CAA, 0x4CAA, 0x6D2E, 0xF7BE, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, // 0x0080 (128) pixels
0xF7BE, 0x650C, 0x4CAA, 0xF7BE, 0xF7BE, 0x4CAA, 0x6D2E, 0xF7BE, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0xF7BE, 0x650D, 0x4CAA, // 0x0090 (144) pixels
0x4CAA, 0x6D2E, 0xF7BE, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0xF7BE, 0x650C, 0x4CAA, 0xF7BE, 0xF7BE, 0x4CAA, 0x6D2E, 0xF7BE, // 0x00A0 (160) pixels
0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0xF7BE, 0x650D, 0x4CAA, 0x4CAA, 0x6D2E, 0xF7BE, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, // 0x00B0 (176) pixels
0xF7BE, 0x650C, 0x4CAA, 0xF7BE, 0xF7BE, 0x4CAA, 0x6D2E, 0xF7BE, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0xF7BE, 0x650D, 0x4CAA, // 0x00C0 (192) pixels
0x4CAA, 0x6D2E, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0x650C, 0x4CAA, 0xF7BE, 0xF7BE, 0x4CAA, 0x6D2E, 0xF7BE, // 0x00D0 (208) pixels
0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0x650D, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, // 0x00E0 (224) pixels
0x4CAA, 0x4CAA, 0x4CAA, 0xF7BE, 0xF7BE, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, // 0x00F0 (240) pixels
0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0xF7BE, 0xF7BE, 0x4CAA, 0x4CAA, 0x4CAA, // 0x0100 (256) pixels
0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, // 0x0110 (272) pixels
0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, // 0x0120 (288) pixels
0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, // 0x0130 (304) pixels
0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, // 0x0140 (320) pixels
0x4CAA, 0x4CAA, 0x4CAA, 0xF7BE, 0xF7BE, 0x4CAA, 0xB676, 0xF7BE, 0xF7BE, 0xF7BE, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, // 0x0150 (336) pixels
0x4CAA, 0x4CAA, 0x54CB, 0x54CB, 0x54CB, 0x54CB, 0x54CB, 0x54CB, 0x54CB, 0x4CAA, 0x4CAA, 0xF7BE, 0xF7BE, 0x4CAA, 0x6D2E, 0xF7BE, // 0x0160 (352) pixels
0xF7BE, 0xF7BE, 0x4CAA, 0x54CB, 0x54CB, 0x54CB, 0x4CAA, 0x4CAA, 0x4CAA, 0x6D2E, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, // 0x0170 (368) pixels
0xF7BE, 0x650C, 0x4CAA, 0xF7BE, 0xF7BE, 0x4CAA, 0x6D2E, 0xF7BE, 0xF7BE, 0xF7BE, 0x4CAA, 0xF7BE, 0xF7BE, 0xF7BE, 0x650C, 0x4CAA, // 0x0180 (384) pixels
0x4CAA, 0x6D2E, 0xF7BE, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0xF7BE, 0x650C, 0x4CAA, 0xF7BE, 0xF7BE, 0x4CAA, 0x6D2E, 0xF7BE, // 0x0190 (400) pixels
0xF7BE, 0xF7BE, 0x4CAA, 0xF7BE, 0xF7BE, 0xF7BE, 0x650C, 0x4CAA, 0x4CAA, 0x6D2E, 0xF7BE, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, // 0x01A0 (416) pixels
0xF7BE, 0x650C, 0x4CAA, 0xF7BE, 0xF7BE, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0xF7BE, 0xF7BE, 0xF7BE, 0x8590, 0x4CAA, // 0x01B0 (432) pixels
0x4CAA, 0x6D2E, 0xF7BE, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0xF7BE, 0x650C, 0x4CAA, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, // 0x01C0 (448) pixels
0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0x4CAA, 0x6D2E, 0xF7BE, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, // 0x01D0 (464) pixels
0xF7BE, 0x650C, 0x4CAA, 0xF7BE, 0xF7BE, 0x6D2E, 0x4CAA, 0x4CAA, 0x4CAA, 0xF7BE, 0xF7BE, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x8590, // 0x01E0 (480) pixels
0x4CAA, 0x6D2E, 0xF7BE, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0xF7BE, 0x650C, 0x4CAA, 0xF7BE, 0xF7BE, 0x4CAA, 0x4CAA, 0x4CAA, // 0x01F0 (496) pixels
0x4CAA, 0xF7BE, 0xF7BE, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x6D2E, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, // 0x0200 (512) pixels
0xF7BE, 0x650C, 0x4CAA, 0xF7BE, 0xF7BE, 0x4CAA, 0x6D2E, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, 0xF7BE, // 0x0210 (528) pixels
0x4CAA, 0x54CB, 0x7D6F, 0x7D6F, 0x7D6F, 0x7D6F, 0x7D6F, 0x7D6F, 0x7D6F, 0x54CB, 0x4CAA, 0xF7BE, 0xF7BE, 0x4CAA, 0x54CB, 0x7D6F, // 0x0220 (544) pixels
0x7D6F, 0x7D6F, 0x7D6F, 0x7D6F, 0x7D6F, 0x7D6F, 0x7D6F, 0xF79D, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, // 0x0230 (560) pixels
0x4CAA, 0x4CAA, 0x4CAA, 0xF7BE, 0xF7BE, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, 0x4CAA, // 0x0240 (576) pixels
}, "greenpass"};
} // namespace bobbyicons

7
main/icons/greenpass.h Normal file
View File

@ -0,0 +1,7 @@
#pragma once
#include "icon.h"
namespace bobbyicons {
extern const espgui::Icon<24, 24> greenpass;
} // namespace bobbyicons

View File

@ -59,12 +59,16 @@ using namespace std::chrono_literals;
#endif
#include "modes/defaultmode.h"
#include "displays/statusdisplay.h"
#include "displays/lockscreen.h"
#include "displays/calibratedisplay.h"
#ifdef FEATURE_DNS_NS
#include "dnsannounce.h"
#endif
#include "drivingstatistics.h"
#include "newsettings.h"
#ifdef FEATURE_ESPNOW
#include "espnowfunctions.h"
#endif
#include "taskmanager.h"
namespace {
@ -230,10 +234,22 @@ extern "C" void app_main()
switchScreen<DPad6WireDebugDisplay>();
#else
if (!gas || !brems || *gas > 200.f || *brems > 200.f)
espgui::switchScreen<CalibrateDisplay>(true);
if (settings.lockscreen.keepLockedAfterReboot && settings.lockscreen.locked)
{
espgui::switchScreen<Lockscreen>();
}
else
espgui::switchScreen<StatusDisplay>();
{
if (!gas || !brems || *gas > 200.f || *brems > 200.f)
espgui::switchScreen<CalibrateDisplay>(true);
else
{
espgui::switchScreen<StatusDisplay>();
}
}
#endif
#ifdef FEATURE_ESPNOW
espnow::initESPNow();
#endif
while (true)
@ -330,6 +346,10 @@ extern "C" void app_main()
}
#endif
#ifdef FEATURE_ESPNOW
espnow::handle();
#endif
#ifdef FEATURE_CLOUD
if (!lastCloudCollect || now - *lastCloudCollect >= std::chrono::milliseconds{settings.boardcomputerHardware.timersSettings.cloudCollectRate})
{

View File

@ -274,6 +274,8 @@ constexpr Settings::Ledstrip defaultLedstrip {
constexpr Settings::LockscreenSettings defaultLockscreen {
.allowPresetSwitch = true,
.keepLockedAfterReboot = false,
.locked = false,
.pin = { 1, 2, 3, 4 }
};
@ -300,6 +302,19 @@ constexpr Settings::SavedStatistics defaultSavedStatistics {
.totalCentimeters = 0,
};
#ifdef FEATURE_ESPNOW
constexpr Settings::ESPNOW defaultEspNowSettings {
#ifndef FEATURE_NTP
.syncTime = true,
.syncTimeWithOthers = true,
#else
.syncTime = false,
.syncTimeWithOthers = false,
#endif
.syncBlink = false
};
#endif
constexpr Settings defaultSettings {
#ifdef FEATURE_BMS
.autoConnectBms = false,
@ -330,7 +345,10 @@ constexpr Settings defaultSettings {
.hybrid = defaultHybrid,
.lockscreen = defaultLockscreen,
.savedStatistics = defaultSavedStatistics,
.handbremse = defaultHandbremse
.handbremse = defaultHandbremse,
#ifdef FEATURE_ESPNOW
.espnow = defaultEspNowSettings,
#endif
};
StringSettings makeDefaultStringSettings();

View File

@ -210,6 +210,8 @@ struct Settings
struct LockscreenSettings {
bool allowPresetSwitch;
bool keepLockedAfterReboot;
bool locked;
std::array<int8_t, 4> pin;
} lockscreen;
@ -224,6 +226,13 @@ struct Settings
bool enable;
bool visualize;
} handbremse;
#ifdef FEATURE_ESPNOW
struct ESPNOW {
bool syncTime;
bool syncTimeWithOthers;
bool syncBlink;
} espnow;
#endif
template<typename T>
void executeForEveryCommonSetting(T &&callable);
@ -353,6 +362,8 @@ void Settings::executeForEveryCommonSetting(T &&callable)
callable("hybridDeacL", hybrid.deactivationLimit);
callable("lockAlwPresetSw", lockscreen.allowPresetSwitch);
callable("keepLocked", lockscreen.keepLockedAfterReboot);
callable("currentlyLocked", lockscreen.locked);
callable("lockscreenPin", lockscreen.pin);
callable("totalCentimeter", savedStatistics.totalCentimeters);
@ -362,6 +373,14 @@ void Settings::executeForEveryCommonSetting(T &&callable)
callable("handBremsM", handbremse.mode);
callable("handBremsT", handbremse.triggerTimeout);
callable("handBremsV", handbremse.visualize);
#ifdef FEATURE_ESPNOW
callable("espnowSyncT", espnow.syncTime);
callable("espnowSyncTWO", espnow.syncTimeWithOthers);
#ifdef FEATURE_LEDSTRIP
callable("espnowSyncBl", espnow.syncBlink);
#endif
#endif
}
template<typename T>

View File

@ -0,0 +1,45 @@
#include "settingsutils.h"
// esp-idf includes
#include <esp_log.h>
// local includes
#include "globals.h"
#include "presets.h"
namespace settingsutils {
void switchProfile(uint8_t index)
{
#ifdef SIMPLIFIED_TRIGGER_TRIGGERONPRESET
if (index == SIMPLIFIED_TRIGGER_TRIGGERONPRESET)
{
simplified = true;
#ifdef SETTINGSUTILS_PLUGIN
#include SETTINGSUTILS_PLUGIN
#endif
return;
}
#endif
settings = presets::defaultSettings;
stringSettings = presets::makeDefaultStringSettings();
if (!settingsPersister.openProfile(index))
{
ESP_LOGE("BOBBY", "openProfile() failed");
return;
}
if (!settingsPersister.load(settings))
{
ESP_LOGE("BOBBY", "load() for settings failed");
return;
}
if (!settingsPersister.load(stringSettings))
{
ESP_LOGE("BOBBY", "load() for stringSettings failed");
return;
}
}
} // namespace

View File

@ -1,45 +1,7 @@
#pragma once
// esp-idf includes
#include <esp_log.h>
#include <cstdint>
// local includes
#include "globals.h"
#include "presets.h"
namespace {
void switchProfile(uint8_t index)
{
#ifdef SIMPLIFIED_TRIGGER_TRIGGERONPRESET
if (index == SIMPLIFIED_TRIGGER_TRIGGERONPRESET)
{
simplified = true;
#ifdef SETTINGSUTILS_PLUGIN
#include SETTINGSUTILS_PLUGIN
#endif
return;
}
#endif
settings = presets::defaultSettings;
stringSettings = presets::makeDefaultStringSettings();
if (!settingsPersister.openProfile(index))
{
ESP_LOGE("BOBBY", "openProfile() failed");
return;
}
if (!settingsPersister.load(settings))
{
ESP_LOGE("BOBBY", "load() for settings failed");
return;
}
if (!settingsPersister.load(stringSettings))
{
ESP_LOGE("BOBBY", "load() for stringSettings failed");
return;
}
}
namespace settingsutils {
void switchProfile(uint8_t index);
}

View File

@ -332,6 +332,7 @@ char TEXT_ANIMATION_BLINKBOTH[] = "Blink Both";
//LockscreenSettingsMenu
char TEXT_LOCKSCREENSETTINGS[] = "Lockscreen Settings";
char TEXT_ALLOWPRESETSWITCH[] = "Allow preset switch";
char TEXT_KEEPLOCKED[] = "Keep locked";
char TEXT_PINDIGIT0[] = "PIN digit0";
char TEXT_PINDIGIT1[] = "PIN digit1";
char TEXT_PINDIGIT2[] = "PIN digit2";
@ -537,4 +538,23 @@ char TEXT_REENABLE_MENUITEMS[] = "Show advanced";
//SelectBuildserverBranchMenu
char TEXT_SELECT_BRANCH[] = "Select Branch";
char TEXT_SELECT_BRANCH_CLEAR[] = "Clear Branch";
char TEXT_QRCODE_DEBUG[] = "QR Debug";
//GreenPassMenu
char TEXT_GREENPASS[] = "Green Pass";
char TEXT_SHOWCERT[] = "Show cert";
//EspNowMenu
char TEXT_ESPNOW[] = "ESP-Now";
char TEXT_ESPNOW_MENU[] = "ESP-Now Menu";
char TEXT_ESPNOW_RECEIVETS[] = "Recv Ts State";
char TEXT_ESPNOW_RECEIVETSFROMBOBBY[] = "Recv BobbyTs State";
char TEXT_ESPNOW_SENDTSMSG[] = "Broadcast Time";
//EspNowSettingsMenu
char TEXT_ESPNOW_SETTINGS[] = "ESP-Now settings";
char TEXT_ESPNOW_SYNCTIME[] = "Sync time (no NTP)";
char TEXT_ESPNOW_SYNCWITHOTHERS[] = "Sync time with others";
char TEXT_ESPNOW_SYNCBLINK[] = "Sync blink";
} // namespace

View File

@ -332,6 +332,7 @@ extern char TEXT_ANIMATION_BLINKBOTH[];
//LockscreenSettingsMenu
extern char TEXT_LOCKSCREENSETTINGS[];
extern char TEXT_ALLOWPRESETSWITCH[];
extern char TEXT_KEEPLOCKED[];
extern char TEXT_PINDIGIT0[];
extern char TEXT_PINDIGIT1[];
extern char TEXT_PINDIGIT2[];
@ -536,6 +537,26 @@ extern char TEXT_REENABLE_MENUITEMS[];
//SelectBuildserverBranchMenu
extern char TEXT_SELECT_BRANCH[];
extern char TEXT_SELECT_BRANCH_CLEAR[];
//QrCodeDebug
extern char TEXT_QRCODE_DEBUG[];
//GreenPassMenu
extern char TEXT_GREENPASS[];
extern char TEXT_SHOWCERT[];
//EspNowMenu
extern char TEXT_ESPNOW[];
extern char TEXT_ESPNOW_MENU[];
extern char TEXT_ESPNOW_RECEIVETS[];
extern char TEXT_ESPNOW_RECEIVETSFROMBOBBY[];
extern char TEXT_ESPNOW_SENDTSMSG[];
//EspNowSettingsMenu
extern char TEXT_ESPNOW_SETTINGS[];
extern char TEXT_ESPNOW_SYNCTIME[];
extern char TEXT_ESPNOW_SYNCWITHOTHERS[];
extern char TEXT_ESPNOW_SYNCBLINK[];
} // namespace
using namespace bobbytexts;

View File

@ -25,7 +25,6 @@ constexpr const char * const TAG = "bobbycloud";
using namespace std::chrono_literals;
// Little "flash" on statusdisplay when udp stuff is happening
bool visualSendUdpPacket;
espchrono::millis_clock::time_point timestampLastFailed;
void spamUdpBroadcast()
@ -294,7 +293,7 @@ std::string buildUdpCloudString()
void sendUdpCloudPacket()
{
EVERY_N_MILLIS(settings.boardcomputerHardware.timersSettings.udpSendRateMs) {
if (espchrono::ago(timestampLastFailed) < 3s)
if (espchrono::ago(timestampLastFailed) < 2s)
{
visualSendUdpPacket = false;
return;
@ -332,6 +331,7 @@ void sendUdpCloudPacket()
if (udpCloudIp.type != IPADDR_TYPE_V4)
{
ESP_LOGE(TAG, "unsupported ip type: %hhu", udpCloudIp.type);
timestampLastFailed = espchrono::millis_clock::now();
visualSendUdpPacket = false;
return;
}
@ -348,6 +348,7 @@ void sendUdpCloudPacket()
if (const auto result = udpCloudSender.send(receipient, buf); !result)
{
timestampLastFailed = espchrono::millis_clock::now();
ESP_LOGE(TAG, "send to cloud failed: %.*s (ip=%s)", result.error().size(), result.error().data(), wifi_stack::toString(udpCloudIp.u_addr.ip4).c_str());
}

View File

@ -337,3 +337,26 @@ uint8_t time_to_percent(espchrono::milliseconds32 repeat, espchrono::millisecond
else
return invert ? numLeds : 0;
}
void time_set_now(espchrono::utc_clock::time_point now)
{
using namespace espchrono;
// ESP_LOGI("BOBBY", "%s (%lld)%s", toString(toDateTime(now)).c_str(), std::chrono::floor<std::chrono::seconds>(now.time_since_epoch()).count(), time_valid(now) ? "":" (probably invalid)");
const auto seconds = std::chrono::floor<std::chrono::seconds>(now.time_since_epoch());
timeval ts {
.tv_sec = (long int)seconds.count(),
.tv_usec = (long int)std::chrono::floor<std::chrono::microseconds>(now.time_since_epoch() - seconds).count()
};
timezone tz {
.tz_minuteswest = 0,
.tz_dsttime = 0
};
settimeofday(&ts, &tz);
}
std::string local_clock_string()
{
const auto dt = espchrono::toDateTime(espchrono::utc_clock::now() + settings.timeSettings.timezoneOffset);
return fmt::format("{:02d}:{:02d}:{:02d}", dt.hour, dt.minute, dt.second);
}

View File

@ -59,3 +59,5 @@ void readPotis();
float wattToAmpere(float watt);
float wattToMotorCurrent(float watt);
uint8_t time_to_percent(espchrono::milliseconds32 repeat, espchrono::milliseconds32 riseTime, espchrono::milliseconds32 fullTime, size_t numLeds, bool invert);
void time_set_now(espchrono::utc_clock::time_point now);
std::string local_clock_string();

View File

@ -1,6 +1,8 @@
#include "webserver.h"
#include "sdkconfig.h"
using namespace std::chrono_literals;
#ifdef FEATURE_WEBSERVER
namespace {
constexpr const char * const TAG = "BOBBYWEB";

View File

@ -2,6 +2,7 @@
#ifdef FEATURE_WEBSERVER
using esphttpdutils::HtmlTag;
using namespace std::chrono_literals;
namespace {
constexpr const char * const TAG = "BOBBYWEB";

View File

@ -2,6 +2,7 @@
using esphttpdutils::HtmlTag;
using namespace espchrono;
using namespace std::chrono_literals;
namespace {
constexpr const char * const TAG = "BOBBYWEB";
@ -148,7 +149,7 @@ esp_err_t webserver_dump_nvs_handler(httpd_req_t *req)
continue;
}
#endif
switchProfile(profile_num);
settingsutils::switchProfile(profile_num);
const auto cur_profile = settingsPersister.currentlyOpenProfileIndex();
const auto profile_str = cur_profile ? std::to_string(*cur_profile) : "-";
@ -166,7 +167,7 @@ esp_err_t webserver_dump_nvs_handler(httpd_req_t *req)
});
}
switchProfile(switchBackProfile);
settingsutils::switchProfile(switchBackProfile);
std::string body;
serializeJson(doc, body);

View File

@ -0,0 +1,21 @@
#include "menudisplaywithtime.h"
#include "tftinstance.h"
#include "utils.h"
using namespace espgui;
namespace bobbygui {
void MenuDisplayWithTime::start()
{
Base::start();
m_label_currentTime.start();
}
void MenuDisplayWithTime::redraw()
{
Base::redraw();
tft.setTextFont(m_use_big_font() ? 4 : 2);
m_label_currentTime.redraw(fmt::format("&7Time: {}", local_clock_string()));
}
} // namespace

View File

@ -0,0 +1,25 @@
#pragma once
#include <menudisplay.h>
#include <cstdint>
namespace bobbygui {
class MenuDisplayWithTime :
public espgui::MenuDisplay
{
using Base = espgui::MenuDisplay;
public:
void start() override;
void redraw() override;
espgui::Label m_label_currentTime{145, 6};
private:
virtual bool m_use_big_font() const
{
#ifdef MENU_DISPLAY_USE_BIG_TIME
return true;
#else
return false;
#endif
}
};
} // namespace

View File

@ -701,19 +701,8 @@ CONFIG_ESP32_PHY_MAX_TX_POWER=20
# Core dump
#
# CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH is not set
CONFIG_ESP_COREDUMP_ENABLE_TO_UART=y
# CONFIG_ESP_COREDUMP_ENABLE_TO_NONE is not set
# CONFIG_ESP_COREDUMP_DATA_FORMAT_BIN is not set
CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF=y
# CONFIG_ESP_COREDUMP_CHECKSUM_CRC32 is not set
CONFIG_ESP_COREDUMP_CHECKSUM_SHA256=y
CONFIG_ESP_COREDUMP_ENABLE=y
CONFIG_ESP_COREDUMP_MAX_TASKS_NUM=64
CONFIG_ESP_COREDUMP_UART_DELAY=0
CONFIG_ESP_COREDUMP_STACK_SIZE=0
CONFIG_ESP_COREDUMP_DECODE_INFO=y
# CONFIG_ESP_COREDUMP_DECODE_DISABLE is not set
CONFIG_ESP_COREDUMP_DECODE="info"
# CONFIG_ESP_COREDUMP_ENABLE_TO_UART is not set
CONFIG_ESP_COREDUMP_ENABLE_TO_NONE=y
# end of Core dump
#
@ -1473,19 +1462,8 @@ CONFIG_ESP32S2_PANIC_PRINT_REBOOT=y
CONFIG_TIMER_TASK_STACK_SIZE=3584
CONFIG_SW_COEXIST_ENABLE=y
# CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH is not set
CONFIG_ESP32_ENABLE_COREDUMP_TO_UART=y
# CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE is not set
# CONFIG_ESP32_COREDUMP_DATA_FORMAT_BIN is not set
CONFIG_ESP32_COREDUMP_DATA_FORMAT_ELF=y
# CONFIG_ESP32_COREDUMP_CHECKSUM_CRC32 is not set
CONFIG_ESP32_COREDUMP_CHECKSUM_SHA256=y
CONFIG_ESP32_ENABLE_COREDUMP=y
CONFIG_ESP32_CORE_DUMP_MAX_TASKS_NUM=64
CONFIG_ESP32_CORE_DUMP_UART_DELAY=0
CONFIG_ESP32_CORE_DUMP_STACK_SIZE=0
CONFIG_ESP32_CORE_DUMP_DECODE_INFO=y
# CONFIG_ESP32_CORE_DUMP_DECODE_DISABLE is not set
CONFIG_ESP32_CORE_DUMP_DECODE="info"
# CONFIG_ESP32_ENABLE_COREDUMP_TO_UART is not set
CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE=y
CONFIG_MB_MASTER_TIMEOUT_MS_RESPOND=150
CONFIG_MB_MASTER_DELAY_MS_CONVERT=200
CONFIG_MB_QUEUE_LENGTH=20