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 "drivingstatistics.h"
using namespace espgui;
class WhPerKmText : public virtual espgui::TextInterface {
public: std::string text() const override {
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;
auto w_per_kmh = watt / std::abs(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 UptimeText : public virtual espgui::TextInterface
{
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 {
public: std::string text() const override {
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: {:.1f}km", drivingStatistics.totalMeters / 1000.f );
class TotalKilometersText : public virtual espgui::TextInterface
{
public:
std::string text() const override
{
return fmt::format("total: {:.1f}km", drivingStatistics.totalMeters / 1000.f);
}
};
class TotalMetersText : public virtual espgui::TextInterface {
public: std::string text() const override {
return fmt::format("total: {:.0f}m", drivingStatistics.totalMeters );
class TotalMetersText : public virtual espgui::TextInterface
{
public:
std::string text() const override
{
return fmt::format("total: {:.0f}m", drivingStatistics.totalMeters);
}
};
class CurrentDrivingTimeText : public virtual espgui::TextInterface {
public: std::string text() const override {
return get_current_driving_time_string();
class CurrentDrivingTimeText : public virtual espgui::TextInterface
{
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:
void triggered() override {
void triggered() override
{
drivingStatistics.last_cm_written = drivingStatistics.totalMeters * 100;
settings.savedStatistics.totalCentimeters = drivingStatistics.last_cm_written;
saveSettings();
}
};
class ClearCurrentStatsAction : public virtual ActionInterface {
class ClearCurrentStatsAction : public virtual espgui::ActionInterface
{
public:
void triggered() override {
void triggered() override
{
drivingStatistics.meters_driven = 0.;
drivingStatistics.currentDrivingTime = {};
drivingStatistics.wh_used = 0;
@ -109,6 +146,8 @@ public:
}
};
using namespace espgui;
StatisticsMenu::StatisticsMenu()
{
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();
std::string getEfficiencyClassString();
uint16_t getEfficiencyClassColor();
std::string get_current_driving_time_string();

View File

@ -5,18 +5,16 @@
#include "globals.h"
#include "utils.h"
namespace {
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:
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)()>
class StaticStatusTextHelper : public virtual TextInterface
class StaticStatusTextHelper : public virtual espgui::TextInterface
{
public:
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
// esp-idf includes
#include <esp_log.h>
#ifdef FEATURE_NTP
#include <lwip/apps/snmp.h>
#include <esp_sntp.h>
void initTime();
void updateTime();
#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;
}
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;
}
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)
uint8_t time_to_percent(espchrono::milliseconds32 repeat, espchrono::milliseconds32 riseTime, espchrono::milliseconds32 fullTime, size_t numLeds, bool invert)
{
const auto now = espchrono::millis_clock::now().time_since_epoch() % repeat;
int activated = invert ? numLeds : 0;
if (now <= riseTime)
{
if (invert)
{
activated = numLeds - ((now*numLeds) / riseTime);
}
return numLeds - ((now*numLeds) / riseTime);
else
{
activated = (now*numLeds) / riseTime;
}
return (now*numLeds) / riseTime;
}
else if (now < riseTime + fullTime)
{
activated = invert ? 0 : numLeds;
}
return invert ? 0 : numLeds;
else
activated = invert ? numLeds : 0;
return activated;
return invert ? numLeds : 0;
}

View File

@ -58,5 +58,4 @@ void updateAccumulators();
void readPotis();
float wattToAmpere(float watt);
float wattToMotorCurrent(float watt);
std::string get_current_uptime_string();
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);
uint8_t time_to_percent(espchrono::milliseconds32 repeat, espchrono::milliseconds32 riseTime, espchrono::milliseconds32 fullTime, size_t numLeds, bool invert);