driving statics menu improvements

This commit is contained in:
2021-11-21 02:16:37 +01:00
parent b8acf12fd1
commit 711896d20b
8 changed files with 177 additions and 164 deletions

View File

@@ -11,50 +11,83 @@
#include "icons/update.h" #include "icons/update.h"
#include "drivingstatistics.h" #include "drivingstatistics.h"
using namespace espgui; class WhPerKmText : public virtual espgui::TextInterface
{
class WhPerKmText : public virtual espgui::TextInterface { public:
public: std::string text() const override { std::string text() const override
{
float avgVoltage = 0; float avgVoltage = 0;
for (auto &controller : controllers) for (auto &controller : controllers)
{
avgVoltage += controller.getCalibratedVoltage(); avgVoltage += controller.getCalibratedVoltage();
}
avgVoltage = avgVoltage / controllers.size(); avgVoltage = avgVoltage / controllers.size();
auto watt = sumCurrent * avgVoltage; auto watt = sumCurrent * avgVoltage;
auto w_per_kmh = watt / avgSpeedKmh; auto w_per_kmh = watt / std::abs(avgSpeedKmh);
return fmt::format("{:.0f} Wh/km", w_per_kmh); return fmt::format("{:.0f} Wh/km", w_per_kmh);
} }
}; };
class UptimeText : public virtual espgui::TextInterface { class UptimeText : public virtual espgui::TextInterface
public: std::string text() const override { {
return get_current_uptime_string(); public:
std::string text() const override
{
const auto uptime = espchrono::millis_clock::now().time_since_epoch();
auto converted = date::make_time(uptime);
auto msecs = uptime
- converted.hours()
- converted.minutes()
- converted.seconds();
return fmt::format("Up: {:02d}:{:02d}:{:02d}&7.{:03d}",
converted.hours().count(),
converted.minutes().count(),
converted.seconds().count(),
msecs.count());
} }
}; };
class CurrentKilometersText : public virtual espgui::TextInterface { class CurrentKilometersText : public virtual espgui::TextInterface
public: std::string text() const override { {
public:
std::string text() const override
{
return fmt::format("Curr: {:.2f}m", drivingStatistics.meters_driven); return fmt::format("Curr: {:.2f}m", drivingStatistics.meters_driven);
} }
}; };
class TotalKilometersText : public virtual espgui::TextInterface { class TotalKilometersText : public virtual espgui::TextInterface
public: std::string text() const override { {
return fmt::format("total: {:.1f}km", drivingStatistics.totalMeters / 1000.f ); public:
std::string text() const override
{
return fmt::format("total: {:.1f}km", drivingStatistics.totalMeters / 1000.f);
} }
}; };
class TotalMetersText : public virtual espgui::TextInterface { class TotalMetersText : public virtual espgui::TextInterface
public: std::string text() const override { {
return fmt::format("total: {:.0f}m", drivingStatistics.totalMeters ); public:
std::string text() const override
{
return fmt::format("total: {:.0f}m", drivingStatistics.totalMeters);
} }
}; };
class CurrentDrivingTimeText : public virtual espgui::TextInterface { class CurrentDrivingTimeText : public virtual espgui::TextInterface
public: std::string text() const override { {
return get_current_driving_time_string(); public:
std::string text() const override
{
auto converted = date::make_time(drivingStatistics.currentDrivingTime);
auto msecs = drivingStatistics.currentDrivingTime
- converted.hours()
- converted.minutes()
- converted.seconds();
return fmt::format("Drive: {:02d}:{:02d}:{:02d}&s&7.{:03d}",
converted.hours().count(),
converted.minutes().count(),
converted.seconds().count(),
msecs.count());
} }
}; };
@@ -90,18 +123,22 @@ public:
} }
}; };
class SaveKilometersAction : public virtual ActionInterface { class SaveKilometersAction : public virtual espgui::ActionInterface
{
public: public:
void triggered() override { void triggered() override
{
drivingStatistics.last_cm_written = drivingStatistics.totalMeters * 100; drivingStatistics.last_cm_written = drivingStatistics.totalMeters * 100;
settings.savedStatistics.totalCentimeters = drivingStatistics.last_cm_written; settings.savedStatistics.totalCentimeters = drivingStatistics.last_cm_written;
saveSettings(); saveSettings();
} }
}; };
class ClearCurrentStatsAction : public virtual ActionInterface { class ClearCurrentStatsAction : public virtual espgui::ActionInterface
{
public: public:
void triggered() override { void triggered() override
{
drivingStatistics.meters_driven = 0.; drivingStatistics.meters_driven = 0.;
drivingStatistics.currentDrivingTime = {}; drivingStatistics.currentDrivingTime = {};
drivingStatistics.wh_used = 0; drivingStatistics.wh_used = 0;
@@ -109,6 +146,8 @@ public:
} }
}; };
using namespace espgui;
StatisticsMenu::StatisticsMenu() StatisticsMenu::StatisticsMenu()
{ {
constructMenuItem<makeComponent<MenuItem, WhPerKmText, DummyAction>>(); constructMenuItem<makeComponent<MenuItem, WhPerKmText, DummyAction>>();

View File

@@ -106,17 +106,3 @@ void calculateStatistics()
} }
} }
} }
std::string get_current_driving_time_string()
{
auto converted = date::make_time(drivingStatistics.currentDrivingTime);
auto msecs = drivingStatistics.currentDrivingTime
- converted.hours()
- converted.minutes()
- converted.seconds();
return fmt::format("Drive: {:02d}:{:02d}:{:02d}.{:03d}",
converted.hours().count(),
converted.minutes().count(),
converted.seconds().count(),
msecs.count());
}

View File

@@ -20,4 +20,3 @@ void calculateStatistics();
float getAvgWhPerKm(); float getAvgWhPerKm();
std::string getEfficiencyClassString(); std::string getEfficiencyClassString();
uint16_t getEfficiencyClassColor(); uint16_t getEfficiencyClassColor();
std::string get_current_driving_time_string();

View File

@@ -5,18 +5,16 @@
#include "globals.h" #include "globals.h"
#include "utils.h" #include "utils.h"
namespace {
template<const char *Ttext, typename Ttype, Ttype *Tptr, typename TreturnType, TreturnType (Ttype::*Tmethod)()> template<const char *Ttext, typename Ttype, Ttype *Tptr, typename TreturnType, TreturnType (Ttype::*Tmethod)()>
class StatusTextHelper : public virtual TextInterface class StatusTextHelper : public virtual espgui::TextInterface
{ {
public: public:
std::string text() const override { using std::to_string; using ::to_string; return Ttext + to_string((Tptr->*Tmethod)()); } std::string text() const override { using std::to_string; using ::to_string; return Ttext + to_string((Tptr->*Tmethod)()); }
}; };
template<const char *Ttext, typename TreturnType, TreturnType (*Tmethod)()> template<const char *Ttext, typename TreturnType, TreturnType (*Tmethod)()>
class StaticStatusTextHelper : public virtual TextInterface class StaticStatusTextHelper : public virtual espgui::TextInterface
{ {
public: public:
std::string text() const override { using std::to_string; using ::to_string; return Ttext + to_string(Tmethod()); } std::string text() const override { using std::to_string; using ::to_string; return Ttext + to_string(Tmethod()); }
}; };
}

View File

@@ -0,0 +1,103 @@
#include "time_bobbycar.h"
// esp-idf includes
#include <esp_log.h>
#ifdef FEATURE_NTP
#include <lwip/apps/snmp.h>
#include <esp_sntp.h>
#endif
// 3rdparty lib includes
#include <espchrono.h>
#include <espstrutils.h>
// local includes
#include "globals.h"
namespace {
constexpr const char * const TAG = "BOBBYTIME";
} // namespace
auto espchrono::local_clock::timezone() noexcept -> time_zone
{
return time_zone{minutes32{settings.timeSettings.timezoneOffset}, settings.timeSettings.daylightSavingMode};
}
#ifdef FEATURE_NTP
void time_sync_notification_cb(struct timeval *tv);
void initTime()
{
sntp_setoperatingmode(SNTP_OPMODE_POLL);
static_assert(SNTP_MAX_SERVERS >= 1);
sntp_setservername(0, stringSettings.timeServer.c_str());
sntp_set_time_sync_notification_cb(time_sync_notification_cb);
sntp_set_sync_mode(settings.timeSettings.timeSyncMode);
sntp_set_sync_interval(espchrono::milliseconds32{settings.timeSettings.timeSyncInterval}.count());
if (settings.timeSettings.timeServerEnabled)
{
ESP_LOGI("BOBBY", "sntp_init() ...");
sntp_init();
if (!sntp_enabled())
{
ESP_LOGE("BOBBY", "sntp_init() failed");
}
}
}
void updateTime()
{
if (bool(sntp_enabled()) != settings.timeSettings.timeServerEnabled)
{
if (settings.timeSettings.timeServerEnabled)
{
ESP_LOGD("BOBBY", "calling sntp_init()...");
sntp_init();
ESP_LOGI("BOBBY", "sntp_init() finished");
}
else
{
ESP_LOGD("BOBBY", "calling sntp_stop()...");
sntp_stop();
ESP_LOGI("BOBBY", "sntp_stop() finished");
}
}
if (stringSettings.timeServer != sntp_getservername(0))
{
ESP_LOGD("BOBBY", "calling sntp_getservername() with %s...", stringSettings.timeServer.c_str());
sntp_setservername(0, stringSettings.timeServer.c_str());
ESP_LOGI("BOBBY", "sntp_getservername() finished");
}
if (settings.timeSettings.timeSyncMode != sntp_get_sync_mode())
{
ESP_LOGD("BOBBY", "calling sntp_set_sync_mode() with %s...", espcpputils::toString(settings.timeSettings.timeSyncMode).c_str());
sntp_set_sync_mode(settings.timeSettings.timeSyncMode);
ESP_LOGI("BOBBY", "sntp_set_sync_mode() finished");
}
if (settings.timeSettings.timeSyncInterval != espchrono::milliseconds32{sntp_get_sync_interval()})
{
ESP_LOGD("BOBBY", "calling sntp_set_sync_interval() with %s...", espchrono::toString(settings.timeSettings.timeSyncInterval).c_str());
sntp_set_sync_interval(espchrono::milliseconds32{settings.timeSettings.timeSyncInterval}.count());
ESP_LOGI("BOBBY", "sntp_set_sync_interval() finished");
}
}
tl::expected<void, std::string> time_requestSync()
{
ESP_LOGI("BOBBY", "called");
if (!sntp_restart())
return tl::make_unexpected("sntp_restart() failed");
return {};
}
void time_sync_notification_cb(struct timeval *tv)
{
if (tv)
ESP_LOGI("BOBBY", "%ld", tv->tv_sec);
else
ESP_LOGI("BOBBY", "nullptr");
}
#endif

View File

@@ -1,101 +1,6 @@
#pragma once #pragma once
// esp-idf includes
#include <esp_log.h>
#ifdef FEATURE_NTP #ifdef FEATURE_NTP
#include <lwip/apps/snmp.h> void initTime();
#include <esp_sntp.h> void updateTime();
#endif #endif
// 3rdparty lib includes
#include <espchrono.h>
#include <espstrutils.h>
// local includes
#include "globals.h"
auto espchrono::local_clock::timezone() noexcept -> time_zone
{
return time_zone{minutes32{settings.timeSettings.timezoneOffset}, settings.timeSettings.daylightSavingMode};
}
namespace {
#ifdef FEATURE_NTP
void time_sync_notification_cb(struct timeval *tv);
void initTime()
{
sntp_setoperatingmode(SNTP_OPMODE_POLL);
static_assert(SNTP_MAX_SERVERS >= 1);
sntp_setservername(0, stringSettings.timeServer.c_str());
sntp_set_time_sync_notification_cb(time_sync_notification_cb);
sntp_set_sync_mode(settings.timeSettings.timeSyncMode);
sntp_set_sync_interval(espchrono::milliseconds32{settings.timeSettings.timeSyncInterval}.count());
if (settings.timeSettings.timeServerEnabled)
{
ESP_LOGI("BOBBY", "sntp_init() ...");
sntp_init();
if (!sntp_enabled())
{
ESP_LOGE("BOBBY", "sntp_init() failed");
}
}
}
void updateTime()
{
if (bool(sntp_enabled()) != settings.timeSettings.timeServerEnabled)
{
if (settings.timeSettings.timeServerEnabled)
{
ESP_LOGD("BOBBY", "calling sntp_init()...");
sntp_init();
ESP_LOGI("BOBBY", "sntp_init() finished");
}
else
{
ESP_LOGD("BOBBY", "calling sntp_stop()...");
sntp_stop();
ESP_LOGI("BOBBY", "sntp_stop() finished");
}
}
if (stringSettings.timeServer != sntp_getservername(0))
{
ESP_LOGD("BOBBY", "calling sntp_getservername() with %s...", stringSettings.timeServer.c_str());
sntp_setservername(0, stringSettings.timeServer.c_str());
ESP_LOGI("BOBBY", "sntp_getservername() finished");
}
if (settings.timeSettings.timeSyncMode != sntp_get_sync_mode())
{
ESP_LOGD("BOBBY", "calling sntp_set_sync_mode() with %s...", espcpputils::toString(settings.timeSettings.timeSyncMode).c_str());
sntp_set_sync_mode(settings.timeSettings.timeSyncMode);
ESP_LOGI("BOBBY", "sntp_set_sync_mode() finished");
}
if (settings.timeSettings.timeSyncInterval != espchrono::milliseconds32{sntp_get_sync_interval()})
{
ESP_LOGD("BOBBY", "calling sntp_set_sync_interval() with %s...", espchrono::toString(settings.timeSettings.timeSyncInterval).c_str());
sntp_set_sync_interval(espchrono::milliseconds32{settings.timeSettings.timeSyncInterval}.count());
ESP_LOGI("BOBBY", "sntp_set_sync_interval() finished");
}
}
tl::expected<void, std::string> time_requestSync()
{
ESP_LOGI("BOBBY", "called");
if (!sntp_restart())
return tl::make_unexpected("sntp_restart() failed");
return {};
}
void time_sync_notification_cb(struct timeval *tv)
{
if (tv)
ESP_LOGI("BOBBY", "%ld", tv->tv_sec);
else
ESP_LOGI("BOBBY", "nullptr");
}
#endif
}

View File

@@ -322,34 +322,18 @@ float wattToMotorCurrent(float watt)
return wattToAmpere(watt) / 4; return wattToAmpere(watt) / 4;
} }
std::string get_current_uptime_string() uint8_t time_to_percent(espchrono::milliseconds32 repeat, espchrono::milliseconds32 riseTime, espchrono::milliseconds32 fullTime, size_t numLeds, bool invert)
{
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;
}
uint8_t time_to_percent(std::chrono::duration<long, std::ratio<1,1000>> repeat, std::chrono::duration<long, std::ratio<1,1000>> riseTime, std::chrono::duration<long, std::ratio<1,1000>> fullTime, size_t numLeds, bool invert)
{ {
const auto now = espchrono::millis_clock::now().time_since_epoch() % repeat; const auto now = espchrono::millis_clock::now().time_since_epoch() % repeat;
int activated = invert ? numLeds : 0;
if (now <= riseTime) if (now <= riseTime)
{ {
if (invert) if (invert)
{ return numLeds - ((now*numLeds) / riseTime);
activated = numLeds - ((now*numLeds) / riseTime);
}
else else
{ return (now*numLeds) / riseTime;
activated = (now*numLeds) / riseTime;
}
} }
else if (now < riseTime + fullTime) else if (now < riseTime + fullTime)
{ return invert ? 0 : numLeds;
activated = invert ? 0 : numLeds;
}
else else
activated = invert ? numLeds : 0; return invert ? numLeds : 0;
return activated;
} }

View File

@@ -58,5 +58,4 @@ 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(); uint8_t time_to_percent(espchrono::milliseconds32 repeat, espchrono::milliseconds32 riseTime, espchrono::milliseconds32 fullTime, size_t numLeds, bool invert);
uint8_t time_to_percent(std::chrono::duration<long, std::ratio<1,1000>> repeat, std::chrono::duration<long, std::ratio<1,1000>> riseTime, std::chrono::duration<long, std::ratio<1,1000>> fullTime, size_t numLeds, bool invert);