driving statics menu improvements
This commit is contained in:
@@ -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>>();
|
||||||
|
@@ -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());
|
|
||||||
}
|
|
||||||
|
@@ -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();
|
|
||||||
|
@@ -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()); }
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
@@ -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
|
||||||
|
@@ -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
|
|
||||||
}
|
|
||||||
|
@@ -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;
|
|
||||||
}
|
}
|
||||||
|
@@ -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);
|
|
||||||
|
Reference in New Issue
Block a user