Added driving statistics
This commit is contained in:
@@ -23,6 +23,7 @@
|
|||||||
#include "displays/garagedisplay.h"
|
#include "displays/garagedisplay.h"
|
||||||
#include "displays/menus/otamenu.h"
|
#include "displays/menus/otamenu.h"
|
||||||
#include "displays/poweroffdisplay.h"
|
#include "displays/poweroffdisplay.h"
|
||||||
|
#include "displays/menus/statisticsmenu.h"
|
||||||
#include "actions/rebootaction.h"
|
#include "actions/rebootaction.h"
|
||||||
#include "displays/menus/debugmenu.h"
|
#include "displays/menus/debugmenu.h"
|
||||||
#include "icons/battery.h"
|
#include "icons/battery.h"
|
||||||
@@ -43,16 +44,18 @@
|
|||||||
#endif
|
#endif
|
||||||
#include "icons/poweroff.h"
|
#include "icons/poweroff.h"
|
||||||
#include "icons/reboot.h"
|
#include "icons/reboot.h"
|
||||||
|
#include "icons/statistics.h"
|
||||||
|
|
||||||
using namespace espgui;
|
using namespace espgui;
|
||||||
|
|
||||||
MainMenu::MainMenu()
|
MainMenu::MainMenu()
|
||||||
{
|
{
|
||||||
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_STATUS>, SwitchScreenAction<StatusDisplay>, StaticMenuItemIcon<&espgui::icons::back>>>();
|
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_STATUS>, SwitchScreenAction<StatusDisplay>, StaticMenuItemIcon<&espgui::icons::back>>>();
|
||||||
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_SELECTMODE>, SwitchScreenAction<SelectModeMenu>, StaticMenuItemIcon<&bobbyicons::modes>>>();
|
|
||||||
#ifdef FEATURE_LEDSTRIP
|
#ifdef FEATURE_LEDSTRIP
|
||||||
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_LEDSTRIP>, SwitchScreenAction<LedstripMenu>, StaticMenuItemIcon<&bobbyicons::neopixel>>>();
|
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_LEDSTRIP>, SwitchScreenAction<LedstripMenu>, StaticMenuItemIcon<&bobbyicons::neopixel>>>();
|
||||||
#endif
|
#endif
|
||||||
|
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_STATISTICSMENU>, SwitchScreenAction<StatisticsMenu>, StaticMenuItemIcon<&bobbyicons::statistics>>>();
|
||||||
|
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_SELECTMODE>, SwitchScreenAction<SelectModeMenu>, StaticMenuItemIcon<&bobbyicons::modes>>>();
|
||||||
if (SHOWITEM) { constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_MODESETTINGS>, ModeSettingsAction>>(); }
|
if (SHOWITEM) { constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_MODESETTINGS>, ModeSettingsAction>>(); }
|
||||||
if (SHOWITEM) { constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_PRESETS>, SwitchScreenAction<PresetsMenu>, StaticMenuItemIcon<&bobbyicons::presets>>>(); }
|
if (SHOWITEM) { constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_PRESETS>, SwitchScreenAction<PresetsMenu>, StaticMenuItemIcon<&bobbyicons::presets>>>(); }
|
||||||
if (SHOWITEM) { constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_PROFILES>, SwitchScreenAction<ProfilesMenu>>>(); }
|
if (SHOWITEM) { constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_PROFILES>, SwitchScreenAction<ProfilesMenu>>>(); }
|
||||||
|
90
main/displays/menus/statisticsmenu.cpp
Normal file
90
main/displays/menus/statisticsmenu.cpp
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
#include "statisticsmenu.h"
|
||||||
|
|
||||||
|
// local includes
|
||||||
|
#include "mainmenu.h"
|
||||||
|
#include "actions/dummyaction.h"
|
||||||
|
#include "actioninterface.h"
|
||||||
|
#include "fmt/core.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
using namespace espgui;
|
||||||
|
|
||||||
|
class WhPerKmText : public virtual espgui::TextInterface {
|
||||||
|
public: std::string text() const override {
|
||||||
|
float avgVoltage = 0;
|
||||||
|
for (auto &controller : controllers)
|
||||||
|
{
|
||||||
|
avgVoltage += controller.getCalibratedVoltage();
|
||||||
|
}
|
||||||
|
avgVoltage = avgVoltage / controllers.size();
|
||||||
|
|
||||||
|
auto watt = sumCurrent * avgVoltage;
|
||||||
|
auto w_per_kmh = watt / avgSpeedKmh;
|
||||||
|
return fmt::format("{:.0f} Wh/km", w_per_kmh);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class UptimeText : public virtual espgui::TextInterface {
|
||||||
|
public: std::string text() const override {
|
||||||
|
return get_current_uptime_string();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CurrentKilometersText : public virtual espgui::TextInterface {
|
||||||
|
public: std::string text() const override {
|
||||||
|
return fmt::format("curr: {:.2f}m", drivingStatistics.meters_driven);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class TotalKilometersText : public virtual espgui::TextInterface {
|
||||||
|
public: std::string text() const override {
|
||||||
|
return fmt::format("total: {:.2f}m", drivingStatistics.totalMeters );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CurrentDrivingTimeText : public virtual espgui::TextInterface {
|
||||||
|
public: std::string text() const override {
|
||||||
|
return get_current_driving_time_string();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class SavedTotalCentimetersText : public virtual espgui::TextInterface {
|
||||||
|
public: std::string text() const override {
|
||||||
|
return fmt::format("saved: {}cm", settings.savedStatistics.totalCentimeters );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class SaveKilometersAction : public virtual ActionInterface {
|
||||||
|
public:
|
||||||
|
void triggered() override {
|
||||||
|
drivingStatistics.last_cm_written = drivingStatistics.totalMeters * 100;
|
||||||
|
settings.savedStatistics.totalCentimeters = drivingStatistics.last_cm_written;
|
||||||
|
saveSettings();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class ClearCurrentStatsAction : public virtual ActionInterface {
|
||||||
|
public:
|
||||||
|
void triggered() override {
|
||||||
|
drivingStatistics.meters_driven = 0.;
|
||||||
|
drivingStatistics.currentDrivingTime = 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
StatisticsMenu::StatisticsMenu()
|
||||||
|
{
|
||||||
|
constructMenuItem<makeComponent<MenuItem, WhPerKmText, DummyAction>>();
|
||||||
|
constructMenuItem<makeComponent<MenuItem, UptimeText, DummyAction>>();
|
||||||
|
constructMenuItem<makeComponent<MenuItem, CurrentKilometersText, DummyAction>>();
|
||||||
|
constructMenuItem<makeComponent<MenuItem, CurrentDrivingTimeText, DummyAction>>();
|
||||||
|
constructMenuItem<makeComponent<MenuItem, TotalKilometersText, DummyAction>>();
|
||||||
|
constructMenuItem<makeComponent<MenuItem, SavedTotalCentimetersText, DummyAction>>();
|
||||||
|
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_STATSSAVE>, SaveKilometersAction>>();
|
||||||
|
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_STATSCLEAR>, ClearCurrentStatsAction>>();
|
||||||
|
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_BACK>, SwitchScreenAction<MainMenu>, StaticMenuItemIcon<&espgui::icons::back>>>();
|
||||||
|
}
|
||||||
|
|
||||||
|
void StatisticsMenu::back()
|
||||||
|
{
|
||||||
|
switchScreen<MainMenu>();
|
||||||
|
}
|
22
main/displays/menus/statisticsmenu.h
Normal file
22
main/displays/menus/statisticsmenu.h
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// 3rdparty lib includes
|
||||||
|
#include <menudisplay.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 espgui::StaticText<TEXT_STATISTICSMENU>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
StatisticsMenu();
|
||||||
|
|
||||||
|
void back() override;
|
||||||
|
};
|
@@ -47,3 +47,5 @@ BluetoothSerial bluetoothSerial;
|
|||||||
|
|
||||||
ModeInterface *lastMode{};
|
ModeInterface *lastMode{};
|
||||||
ModeInterface *currentMode{};
|
ModeInterface *currentMode{};
|
||||||
|
|
||||||
|
DrivingStatistics drivingStatistics;
|
||||||
|
@@ -56,6 +56,15 @@ extern std::string dns_lastIpAddress_v6_global;
|
|||||||
|
|
||||||
extern bool simplified;
|
extern bool simplified;
|
||||||
|
|
||||||
|
struct DrivingStatistics {
|
||||||
|
float meters_driven;
|
||||||
|
float currentDrivingTime;
|
||||||
|
double totalMeters;
|
||||||
|
uint32_t last_cm_written;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern DrivingStatistics drivingStatistics;
|
||||||
|
|
||||||
extern Settings settings;
|
extern Settings settings;
|
||||||
extern StringSettings stringSettings;
|
extern StringSettings stringSettings;
|
||||||
extern SettingsPersister settingsPersister;
|
extern SettingsPersister settingsPersister;
|
||||||
|
@@ -524,5 +524,33 @@ extern "C" void app_main()
|
|||||||
dns_lastIpAddress_v6_global = "-";
|
dns_lastIpAddress_v6_global = "-";
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
EVERY_N_MILLIS( 10 ) {
|
||||||
|
|
||||||
|
if ((settings.savedStatistics.totalCentimeters / 100.f) > drivingStatistics.totalMeters)
|
||||||
|
{
|
||||||
|
drivingStatistics.totalMeters = settings.savedStatistics.totalCentimeters / 100.f;
|
||||||
|
drivingStatistics.last_cm_written = settings.savedStatistics.totalCentimeters;
|
||||||
|
}
|
||||||
|
|
||||||
|
static auto last_km_calculation = espchrono::millis_clock::now();
|
||||||
|
const auto duration = espchrono::ago(last_km_calculation).count() / 1000.0f;
|
||||||
|
last_km_calculation = espchrono::millis_clock::now();
|
||||||
|
|
||||||
|
const float meters_driven_now = (abs(avgSpeedKmh) / 3.6) * duration;
|
||||||
|
drivingStatistics.meters_driven += meters_driven_now;
|
||||||
|
drivingStatistics.totalMeters += meters_driven_now;
|
||||||
|
|
||||||
|
if (abs(avgSpeedKmh) > 1)
|
||||||
|
{
|
||||||
|
drivingStatistics.currentDrivingTime += duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (drivingStatistics.totalMeters > ((drivingStatistics.last_cm_written / 100.f) + 100))
|
||||||
|
{
|
||||||
|
drivingStatistics.last_cm_written = drivingStatistics.totalMeters * 100;
|
||||||
|
settings.savedStatistics.totalCentimeters = drivingStatistics.last_cm_written;
|
||||||
|
saveSettings();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -273,6 +273,10 @@ constexpr Settings::Hybrid defaultHybrid {
|
|||||||
.deactivationLimit = 950,
|
.deactivationLimit = 950,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
constexpr Settings::SavedStatistics defaultSavedStatistics {
|
||||||
|
.totalCentimeters = 0,
|
||||||
|
};
|
||||||
|
|
||||||
constexpr Settings defaultSettings {
|
constexpr Settings defaultSettings {
|
||||||
#ifdef FEATURE_BMS
|
#ifdef FEATURE_BMS
|
||||||
.autoConnectBms = false,
|
.autoConnectBms = false,
|
||||||
@@ -300,7 +304,8 @@ constexpr Settings defaultSettings {
|
|||||||
#endif
|
#endif
|
||||||
.battery = defaultBattery,
|
.battery = defaultBattery,
|
||||||
.hybrid = defaultHybrid,
|
.hybrid = defaultHybrid,
|
||||||
.lockscreen = defaultLockscreen
|
.lockscreen = defaultLockscreen,
|
||||||
|
.savedStatistics = defaultSavedStatistics,
|
||||||
};
|
};
|
||||||
|
|
||||||
StringSettings makeDefaultStringSettings();
|
StringSettings makeDefaultStringSettings();
|
||||||
|
@@ -197,6 +197,10 @@ struct Settings
|
|||||||
std::array<int8_t, 4> pin;
|
std::array<int8_t, 4> pin;
|
||||||
} lockscreen;
|
} lockscreen;
|
||||||
|
|
||||||
|
struct SavedStatistics {
|
||||||
|
uint32_t totalCentimeters;
|
||||||
|
} savedStatistics;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void executeForEveryCommonSetting(T &&callable);
|
void executeForEveryCommonSetting(T &&callable);
|
||||||
|
|
||||||
@@ -317,6 +321,7 @@ void Settings::executeForEveryCommonSetting(T &&callable)
|
|||||||
|
|
||||||
callable("lockAlwPresetSw", lockscreen.allowPresetSwitch);
|
callable("lockAlwPresetSw", lockscreen.allowPresetSwitch);
|
||||||
callable("lockscreenPin", lockscreen.pin);
|
callable("lockscreenPin", lockscreen.pin);
|
||||||
|
callable("totalCentimeter", savedStatistics.totalCentimeters);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
#include "globals.h"
|
||||||
|
|
||||||
using namespace std::chrono_literals;
|
using namespace std::chrono_literals;
|
||||||
|
|
||||||
@@ -317,3 +318,32 @@ float wattToAmpere(float watt) {
|
|||||||
float wattToMotorCurrent(float watt) {
|
float wattToMotorCurrent(float watt) {
|
||||||
return wattToAmpere(watt) / 4;
|
return wattToAmpere(watt) / 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string get_current_uptime_string() {
|
||||||
|
const auto uptime_time_point = espchrono::utc_clock::now();
|
||||||
|
const auto dateTimeUptime = espchrono::toDateTime(uptime_time_point);
|
||||||
|
std::string out = fmt::format("Up: {:02d}:{:02d}:{:02d}", dateTimeUptime.hour, dateTimeUptime.minute, dateTimeUptime.second);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
void secondsToHMS( const float seconds, uint16_t &h, uint16_t &m, uint16_t &s )
|
||||||
|
{
|
||||||
|
uint32_t t = seconds;
|
||||||
|
|
||||||
|
s = t % 60;
|
||||||
|
|
||||||
|
t = (t - s)/60;
|
||||||
|
m = t % 60;
|
||||||
|
|
||||||
|
t = (t - m)/60;
|
||||||
|
h = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string get_current_driving_time_string() {
|
||||||
|
uint16_t hour{};
|
||||||
|
uint16_t minute{};
|
||||||
|
uint16_t second{};
|
||||||
|
secondsToHMS(drivingStatistics.currentDrivingTime, hour, minute, second);
|
||||||
|
std::string out = fmt::format("Drive: {:02d}:{:02d}:{:02d}", hour, minute, second);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
@@ -58,3 +58,6 @@ void updateAccumulators();
|
|||||||
void readPotis();
|
void readPotis();
|
||||||
float wattToAmpere(float watt);
|
float wattToAmpere(float watt);
|
||||||
float wattToMotorCurrent(float watt);
|
float wattToMotorCurrent(float watt);
|
||||||
|
std::string get_current_uptime_string();
|
||||||
|
std::string get_current_driving_time_string();
|
||||||
|
void secondsToHMS( const float seconds, uint16_t &h, uint8_t &m, uint8_t &s );
|
||||||
|
Reference in New Issue
Block a user