Merge pull request #250 from bobbycar-graz/profile-copy
This commit is contained in:
@ -111,6 +111,7 @@ set(headers
|
||||
displays/menus/limitssettingsmenu.h
|
||||
displays/menus/lockscreensettingsmenu.h
|
||||
displays/menus/mainmenu.h
|
||||
displays/menus/manageprofilesmenu.h
|
||||
displays/menus/modessettingsmenu.h
|
||||
displays/menus/mosfetsmenu.h
|
||||
displays/menus/motorfeedbackdebugmenu.h
|
||||
@ -341,6 +342,7 @@ set(sources
|
||||
displays/menus/limitssettingsmenu.cpp
|
||||
displays/menus/lockscreensettingsmenu.cpp
|
||||
displays/menus/mainmenu.cpp
|
||||
displays/menus/manageprofilesmenu.cpp
|
||||
displays/menus/modessettingsmenu.cpp
|
||||
displays/menus/mosfetsmenu.cpp
|
||||
displays/menus/motorfeedbackdebugmenu.cpp
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "displays/powersupplydisplay.h"
|
||||
#include "displays/menus/bmsmenu.h"
|
||||
#include "displays/menus/settingsmenu.h"
|
||||
#include "displays/menus/manageprofilesmenu.h"
|
||||
#include "displays/menus/mosfetsmenu.h"
|
||||
#include "displays/menus/demosmenu.h"
|
||||
#include "displays/menus/greenpassmenu.h"
|
||||
@ -78,6 +79,7 @@ constexpr char TEXT_DEBUG[] = "Debug";
|
||||
constexpr char TEXT_BATTERY[] = "Battery";
|
||||
constexpr char TEXT_BATTERYDEBUG[] = "Bat Debug Menu";
|
||||
constexpr char TEXT_TOGGLECLOUDDEBUG[] = "Cloud Debug";
|
||||
constexpr char TEXT_MANAGEPROFILESMENU[] = "Manage Profiles";
|
||||
|
||||
} // namespace
|
||||
|
||||
@ -114,7 +116,8 @@ MainMenu::MainMenu()
|
||||
if (SHOWITEM) { constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_BMS>, SwitchScreenAction<BmsMenu>, StaticMenuItemIcon<&bobbyicons::bms>>>(); }
|
||||
#endif
|
||||
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_DEMOS>, SwitchScreenAction<DemosMenu>, StaticMenuItemIcon<&bobbyicons::demos>>>();
|
||||
if (SHOWITEM) { constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_PROFILES>, SwitchScreenAction<ProfilesMenu>>>(); }
|
||||
if (SHOWITEM) { constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_PROFILES>, SwitchScreenAction<ProfilesMenu>, StaticMenuItemIcon<&bobbyicons::presets>>>(); }
|
||||
if (SHOWITEM) { constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_MANAGEPROFILESMENU>,SwitchScreenAction<ManageProfilesMenu>, StaticMenuItemIcon<&bobbyicons::presets>>>(); }
|
||||
if (SHOWITEM) { constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_DEBUG>, SwitchScreenAction<DebugMenu>>>(); }
|
||||
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_POWEROFF>, SwitchScreenAction<PoweroffDisplay>, StaticMenuItemIcon<&bobbyicons::poweroff>>>();
|
||||
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_REBOOT>, RebootAction, StaticMenuItemIcon<&bobbyicons::reboot>>>();
|
||||
|
279
main/displays/menus/manageprofilesmenu.cpp
Normal file
279
main/displays/menus/manageprofilesmenu.cpp
Normal file
@ -0,0 +1,279 @@
|
||||
#include "manageprofilesmenu.h"
|
||||
|
||||
// 3rdparty lib includes
|
||||
#include <icons/back.h>
|
||||
#include <TFT_eSPI.h>
|
||||
|
||||
// local includes
|
||||
#include "actions/switchscreenaction.h"
|
||||
#include "bobbyerrorhandler.h"
|
||||
#include "globals.h"
|
||||
#include "mainmenu.h"
|
||||
#include "presets.h"
|
||||
#include "settingsutils.h"
|
||||
#include "utils.h"
|
||||
|
||||
constexpr const char * const TAG = "ProfileManager";
|
||||
|
||||
using namespace espgui;
|
||||
|
||||
namespace {
|
||||
constexpr char TEXT_MANAGEPROFILESMENU[] = "Manage Profiles Menu";
|
||||
constexpr char TEXT_BACK[] = "Back";
|
||||
} // namespace
|
||||
|
||||
class ManageProfileMenuItem : public MenuItem
|
||||
{
|
||||
using Base = MenuItem;
|
||||
public:
|
||||
ManageProfileMenuItem(ManageProfilesMenu &menu, const uint8_t profileIndex) : m_menu{menu}, m_profileIndex{profileIndex} {}
|
||||
void copy()
|
||||
{
|
||||
if (m_mode == CONFIRM_COPY)
|
||||
{
|
||||
const auto currProfile = settingsPersister.currentlyOpenProfileIndex();
|
||||
if (!currProfile)
|
||||
return;
|
||||
|
||||
settingsutils::switchProfile(m_menu.m_firstIndex);
|
||||
|
||||
if (!settingsPersister.openProfile(m_profileIndex)) // just switch nvs namespace
|
||||
{
|
||||
BobbyErrorHandler{}.errorOccured(fmt::format("openProfile({}) failed", m_profileIndex));
|
||||
return;
|
||||
}
|
||||
saveProfileSettings();
|
||||
settingsutils::switchProfile(*currProfile);
|
||||
m_mode = _DEFAULT;
|
||||
m_menu.m_firstIndex = -1;
|
||||
}
|
||||
else if (m_menu.m_firstIndex == m_profileIndex && m_mode == SELECT_OTHER)
|
||||
{
|
||||
m_mode = _DEFAULT;
|
||||
m_menu.m_firstIndex = -1;
|
||||
}
|
||||
else if (m_menu.m_firstIndex == -1 && m_mode == _DEFAULT)
|
||||
{
|
||||
m_mode = SELECT_OTHER;
|
||||
m_menu.m_firstIndex = m_profileIndex;
|
||||
}
|
||||
else if (m_menu.m_firstIndex != -1 && m_menu.m_firstIndex != m_profileIndex)
|
||||
{
|
||||
BobbyErrorHandler{}.errorOccured(fmt::format("Press CONFIRM to COPY from Profile {} to Profile {}", m_menu.m_firstIndex, m_profileIndex));
|
||||
m_mode = CONFIRM_COPY;
|
||||
}
|
||||
}
|
||||
|
||||
void swap()
|
||||
{
|
||||
if (m_mode == CONFIRM_SWAP)
|
||||
{
|
||||
const auto currProfile = settingsPersister.currentlyOpenProfileIndex();
|
||||
if (!currProfile)
|
||||
return;
|
||||
|
||||
settingsutils::switchProfile(m_menu.m_firstIndex);
|
||||
const ProfileSettings tmp = profileSettings;
|
||||
settingsutils::switchProfile(m_profileIndex);
|
||||
const ProfileSettings tmp2 = profileSettings;
|
||||
|
||||
profileSettings = tmp;
|
||||
saveProfileSettings();
|
||||
settingsutils::switchProfile(m_menu.m_firstIndex);
|
||||
profileSettings = tmp2;
|
||||
saveProfileSettings();
|
||||
|
||||
m_mode = _DEFAULT;
|
||||
m_menu.m_firstIndex = -1;
|
||||
settingsutils::switchProfile(*currProfile);
|
||||
}
|
||||
else if (m_menu.m_firstIndex == m_profileIndex && m_mode == SELECT_OTHER)
|
||||
{
|
||||
m_mode = _DEFAULT;
|
||||
m_menu.m_firstIndex = -1;
|
||||
}
|
||||
else if (m_menu.m_firstIndex == -1 && m_mode == _DEFAULT)
|
||||
{
|
||||
m_mode = SELECT_OTHER;
|
||||
m_menu.m_firstIndex = m_profileIndex;
|
||||
}
|
||||
else if (m_menu.m_firstIndex != -1 && m_menu.m_firstIndex != m_profileIndex)
|
||||
{
|
||||
BobbyErrorHandler{}.errorOccured(fmt::format("Press CONFIRM to SWAP Profile {} with Profile {}", m_menu.m_firstIndex, m_profileIndex));
|
||||
m_mode = CONFIRM_SWAP;
|
||||
}
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
if (m_mode == CONFIRM_CLEAR)
|
||||
{
|
||||
const auto currProfile = settingsPersister.currentlyOpenProfileIndex();
|
||||
if (!currProfile)
|
||||
return;
|
||||
|
||||
m_menu.unlock();
|
||||
ESP_LOGI(TAG, "Reseting profile %i...", m_profileIndex);
|
||||
settingsutils::switchProfile(m_profileIndex);
|
||||
profileSettings = presets::defaultProfileSettings;
|
||||
saveProfileSettings();
|
||||
m_mode = _DEFAULT;
|
||||
settingsutils::switchProfile(*currProfile);
|
||||
}
|
||||
else if(m_mode == _DEFAULT)
|
||||
{
|
||||
m_menu.lock();
|
||||
m_mode = CONFIRM_CLEAR;
|
||||
BobbyErrorHandler{}.errorOccured("Press CONFIRM to reset Profile or BACK to cancel.");
|
||||
}
|
||||
}
|
||||
|
||||
std::string text() const override
|
||||
{
|
||||
switch (m_mode)
|
||||
{
|
||||
case _DEFAULT:
|
||||
return fmt::format("Profile {}", m_profileIndex);
|
||||
case CONFIRM_CLEAR:
|
||||
return fmt::format("&1Profile {}", m_profileIndex);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return fmt::format("Profile {}", m_profileIndex);
|
||||
}
|
||||
|
||||
int color() const override
|
||||
{
|
||||
if (m_mode == CONFIRM_CLEAR || m_mode == CONFIRM_COPY || m_mode == CONFIRM_SWAP)
|
||||
return TFT_RED;
|
||||
else if (m_menu.m_firstIndex == m_profileIndex)
|
||||
return TFT_GREEN;
|
||||
else if (m_menu.m_firstIndex != -1)
|
||||
return TFT_GREY;
|
||||
else if (m_menu.m_locked)
|
||||
return TFT_DARKGREY;
|
||||
return TFT_WHITE;
|
||||
};
|
||||
|
||||
void triggered() override
|
||||
{
|
||||
switch (m_menu.m_action)
|
||||
{
|
||||
case Actions::Clear:
|
||||
clear();
|
||||
break;
|
||||
case Actions::Copy:
|
||||
copy();
|
||||
break;
|
||||
case Actions::Swap:
|
||||
swap();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void update() override
|
||||
{
|
||||
Base::update();
|
||||
if (m_mode != _DEFAULT && !m_menu.m_locked && m_menu.m_firstIndex == -1)
|
||||
m_mode = _DEFAULT;
|
||||
}
|
||||
private:
|
||||
enum Mode : uint8_t {
|
||||
_DEFAULT,
|
||||
CONFIRM_CLEAR,
|
||||
SELECT_OTHER,
|
||||
CONFIRM_COPY,
|
||||
CONFIRM_SWAP
|
||||
} m_mode;
|
||||
ManageProfilesMenu &m_menu;
|
||||
const uint8_t m_profileIndex;
|
||||
};
|
||||
|
||||
class ManageProfileModeMenuItem : public MenuItem
|
||||
{
|
||||
public:
|
||||
ManageProfileModeMenuItem(ManageProfilesMenu &menu) : m_menu{menu} {}
|
||||
std::string text() const override {
|
||||
return fmt::format("&7{}", m_menu.action_text());
|
||||
}
|
||||
|
||||
void triggered() override {
|
||||
m_menu.m_action = Actions((uint8_t)m_menu.m_action+1);
|
||||
|
||||
if(m_menu.m_action == Actions::__END__)
|
||||
{
|
||||
m_menu.m_action = Actions(0);
|
||||
}
|
||||
m_menu.m_firstIndex = -1;
|
||||
m_menu.unlock();
|
||||
}
|
||||
private:
|
||||
ManageProfilesMenu &m_menu;
|
||||
};
|
||||
|
||||
ManageProfilesMenu::ManageProfilesMenu()
|
||||
{
|
||||
for (uint8_t i = 0; i < 4; i++)
|
||||
{
|
||||
constructMenuItem<ManageProfileMenuItem>(*this, i);
|
||||
}
|
||||
constructMenuItem<ManageProfileModeMenuItem>(*this);
|
||||
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_BACK>, SwitchScreenAction<MainMenu>, StaticMenuItemIcon<&espgui::icons::back>>>();
|
||||
}
|
||||
|
||||
void ManageProfilesMenu::start()
|
||||
{
|
||||
Base::start();
|
||||
m_oldMode = currentMode;
|
||||
currentMode = &m_mode;
|
||||
}
|
||||
|
||||
void ManageProfilesMenu::stop()
|
||||
{
|
||||
Base::stop();
|
||||
|
||||
if (currentMode == &m_mode)
|
||||
{
|
||||
m_mode.stop();
|
||||
lastMode = nullptr;
|
||||
currentMode = m_oldMode;
|
||||
}
|
||||
}
|
||||
|
||||
void ManageProfilesMenu::back()
|
||||
{
|
||||
if (!m_locked && m_firstIndex == -1)
|
||||
{
|
||||
switchScreen<MainMenu>();
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_locked)
|
||||
m_locked = false;
|
||||
|
||||
if (m_firstIndex != -1)
|
||||
m_firstIndex = -1;
|
||||
|
||||
}
|
||||
|
||||
std::string ManageProfilesMenu::text() const
|
||||
{
|
||||
return TEXT_MANAGEPROFILESMENU;
|
||||
}
|
||||
|
||||
std::string ManageProfilesMenu::action_text() const {
|
||||
return toString(m_action);
|
||||
}
|
||||
|
||||
void ManageProfilesMenu::lock() {
|
||||
m_locked = true;
|
||||
}
|
||||
|
||||
void ManageProfilesMenu::unlock() {
|
||||
m_locked = false;
|
||||
}
|
||||
// functions: clear profile, copy profile, move profile
|
||||
// TODO: If m_locked == true, only confirm and back (espgui::Button::Right and espgui::Button::Left) should be allowed to pass to the menuitems.
|
||||
//
|
39
main/displays/menus/manageprofilesmenu.h
Normal file
39
main/displays/menus/manageprofilesmenu.h
Normal file
@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
|
||||
// 3rdparty lib includes
|
||||
#include <cpptypesafeenum.h>
|
||||
|
||||
// local includes
|
||||
#include "displays/bobbymenudisplay.h"
|
||||
#include "modes/ignoreinputmode.h"
|
||||
|
||||
#define ActionValues(x) \
|
||||
x(Clear) \
|
||||
x(Copy) \
|
||||
x(Swap) \
|
||||
x(__END__)
|
||||
DECLARE_TYPESAFE_ENUM(Actions, : uint8_t, ActionValues)
|
||||
|
||||
class ManageProfilesMenu : public BobbyMenuDisplay
|
||||
{
|
||||
friend class ManageProfileMenuItem;
|
||||
friend class ManageProfileModeMenuItem;
|
||||
using Base = BobbyMenuDisplay;
|
||||
public:
|
||||
ManageProfilesMenu();
|
||||
void start() override;
|
||||
void stop() override;
|
||||
|
||||
std::string text() const override;
|
||||
std::string action_text() const;
|
||||
void back() override;
|
||||
void lock();
|
||||
void unlock();
|
||||
private:
|
||||
ModeInterface *m_oldMode;
|
||||
IgnoreInputMode m_mode{0, bobbycar::protocol::ControlType::FieldOrientedControl, bobbycar::protocol::ControlMode::Torque};
|
||||
protected:
|
||||
bool m_locked{false};
|
||||
Actions m_action{Actions::Clear};
|
||||
int8_t m_firstIndex{-1};
|
||||
};
|
@ -174,7 +174,7 @@ esp_err_t webserver_status_handler(httpd_req_t *req)
|
||||
CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::BadRequest, "text/plain", msg);
|
||||
}
|
||||
#endif
|
||||
|
||||
CALL_AND_EXIT_ON_ERROR(httpd_resp_set_hdr, req, "Access-Control-Allow-Origin", "http://web.bobbycar.cloud");
|
||||
std::string wants_json_query;
|
||||
if (auto result = esphttpdutils::webserver_get_query(req))
|
||||
wants_json_query = *result;
|
||||
|
@ -281,6 +281,8 @@ esp_err_t webserver_root_handler(httpd_req_t *req)
|
||||
}
|
||||
}
|
||||
|
||||
CALL_AND_EXIT_ON_ERROR(httpd_resp_set_hdr, req, "Access-Control-Allow-Origin", "http://web.bobbycar.cloud");
|
||||
|
||||
CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::Ok, (key_result == ESP_OK) ? "application/json":"text/html", body)
|
||||
}
|
||||
|
||||
@ -354,6 +356,7 @@ esp_err_t webserver_triggerRawButton_handler(httpd_req_t *req)
|
||||
espgui::currentDisplay->rawButtonReleased(button);
|
||||
|
||||
CALL_AND_EXIT_ON_ERROR(httpd_resp_set_hdr, req, "Location", "/")
|
||||
CALL_AND_EXIT_ON_ERROR(httpd_resp_set_hdr, req, "Access-Control-Allow-Origin", "http://web.bobbycar.cloud");
|
||||
CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::TemporaryRedirect, "text/html", "Ok, continue at <a href=\"/\">/</a>")
|
||||
}
|
||||
|
||||
@ -427,6 +430,7 @@ esp_err_t webserver_triggerButton_handler(httpd_req_t *req)
|
||||
espgui::currentDisplay->buttonReleased(button);
|
||||
|
||||
CALL_AND_EXIT_ON_ERROR(httpd_resp_set_hdr, req, "Location", "/")
|
||||
CALL_AND_EXIT_ON_ERROR(httpd_resp_set_hdr, req, "Access-Control-Allow-Origin", "http://web.bobbycar.cloud");
|
||||
CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::TemporaryRedirect, "text/html", "Ok, continue at <a href=\"/\">/</a>")
|
||||
}
|
||||
|
||||
@ -441,6 +445,7 @@ esp_err_t webserver_triggerItem_handler(httpd_req_t *req)
|
||||
CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::BadRequest, "text/plain", msg);
|
||||
}
|
||||
#endif
|
||||
CALL_AND_EXIT_ON_ERROR(httpd_resp_set_hdr, req, "Access-Control-Allow-Origin", "http://web.bobbycar.cloud");
|
||||
|
||||
std::string query;
|
||||
if (auto result = esphttpdutils::webserver_get_query(req))
|
||||
@ -530,6 +535,8 @@ esp_err_t webserver_setValue_handler(httpd_req_t *req)
|
||||
}
|
||||
#endif
|
||||
|
||||
CALL_AND_EXIT_ON_ERROR(httpd_resp_set_hdr, req, "Access-Control-Allow-Origin", "http://web.bobbycar.cloud");
|
||||
|
||||
std::string query;
|
||||
if (auto result = esphttpdutils::webserver_get_query(req))
|
||||
query = *result;
|
||||
|
@ -43,7 +43,7 @@ esp_err_t webserver_ota_percentage_handler(httpd_req_t *req)
|
||||
CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::BadRequest, "text/plain", msg);
|
||||
}
|
||||
#endif
|
||||
|
||||
CALL_AND_EXIT_ON_ERROR(httpd_resp_set_hdr, req, "Access-Control-Allow-Origin", "http://web.bobbycar.cloud");
|
||||
std::string body;
|
||||
|
||||
std::string wants_json_query;
|
||||
@ -102,7 +102,7 @@ esp_err_t webserver_ota_handler(httpd_req_t *req)
|
||||
CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::BadRequest, "text/plain", msg);
|
||||
}
|
||||
#endif
|
||||
|
||||
CALL_AND_EXIT_ON_ERROR(httpd_resp_set_hdr, req, "Access-Control-Allow-Origin", "http://web.bobbycar.cloud");
|
||||
std::string body;
|
||||
|
||||
std::string wants_json_query;
|
||||
@ -370,7 +370,7 @@ esp_err_t webserver_trigger_ota_handler(httpd_req_t *req)
|
||||
CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::BadRequest, "text/plain", msg);
|
||||
}
|
||||
#endif
|
||||
|
||||
CALL_AND_EXIT_ON_ERROR(httpd_resp_set_hdr, req, "Access-Control-Allow-Origin", "http://web.bobbycar.cloud");
|
||||
std::string query;
|
||||
if (auto result = esphttpdutils::webserver_get_query(req))
|
||||
query = *result;
|
||||
|
Reference in New Issue
Block a user