diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index a136156..8bc82a1 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -78,6 +78,7 @@ set(headers displays/menus/dynamicdebugmenu.h displays/menus/enablemenu.h displays/menus/espnowmenu.h + displays/menus/espnowsettingsmenu.h displays/menus/feedbackdebugmenu.h displays/menus/gametrakmodesettingsmenu.h displays/menus/genericwifisettingsmenu.h @@ -282,6 +283,7 @@ set(sources displays/menus/dynamicdebugmenu.cpp displays/menus/enablemenu.cpp displays/menus/espnowmenu.cpp + displays/menus/espnowsettingsmenu.cpp displays/menus/feedbackdebugmenu.cpp displays/menus/gametrakmodesettingsmenu.cpp displays/menus/genericwifisettingsmenu.cpp diff --git a/main/accessors/settingsaccessors.h b/main/accessors/settingsaccessors.h index 57a61f3..19cc59b 100644 --- a/main/accessors/settingsaccessors.h +++ b/main/accessors/settingsaccessors.h @@ -14,15 +14,19 @@ struct RefAccessorSaveSettings : public virtual espgui::RefAccessor void setValue(T value) override { espgui::RefAccessor::setValue(value); saveSettings(); }; }; +// Bms #ifdef FEATURE_BMS struct AutoConnectBmsAccessor : public RefAccessorSaveSettings { bool &getRef() const override { return settings.autoConnectBms; } }; #endif + +// Buzzer struct ReverseBeepAccessor : public RefAccessorSaveSettings { bool &getRef() const override { return settings.buzzer.reverseBeep; } }; struct ReverseBeepFreq0Accessor : public RefAccessorSaveSettings { uint8_t &getRef() const override { return settings.buzzer.reverseBeepFreq0; } }; struct ReverseBeepFreq1Accessor : public RefAccessorSaveSettings { uint8_t &getRef() const override { return settings.buzzer.reverseBeepFreq1; } }; struct ReverseBeepDuration0Accessor : public RefAccessorSaveSettings { int16_t &getRef() const override { return settings.buzzer.reverseBeepDuration0; } }; struct ReverseBeepDuration1Accessor : public RefAccessorSaveSettings { int16_t &getRef() const override { return settings.buzzer.reverseBeepDuration1; } }; +// Limits struct IMotMaxAccessor : public RefAccessorSaveSettings { int16_t &getRef() const override { return settings.limits.iMotMax; } }; struct IDcMaxAccessor : public RefAccessorSaveSettings { int16_t &getRef() const override { return settings.limits.iDcMax; } }; struct NMotMaxKmhAccessor : public virtual espgui::AccessorInterface @@ -34,22 +38,27 @@ struct NMotMaxRpmAccessor : public RefAccessorSaveSettings { int16_t &g struct FieldWeakMaxAccessor : public RefAccessorSaveSettings { int16_t &getRef() const override { return settings.limits.fieldWeakMax; } }; struct PhaseAdvMaxAccessor : public RefAccessorSaveSettings { int16_t &getRef() const override { return settings.limits.phaseAdvMax; } }; +// WiFi struct WifiStaEnabledAccessor : public RefAccessorSaveSettings { bool &getRef() const override { return settings.wifiSettings.wifiStaEnabled; } }; struct WifiApEnabledAccessor : public RefAccessorSaveSettings { bool &getRef() const override { return settings.wifiSettings.wifiApEnabled; } }; +// Bluetooth #ifdef FEATURE_BLUETOOTH struct AutoBluetoothModeAccessor : public RefAccessorSaveSettings { BluetoothMode &getRef() const override { return settings.bluetoothSettings.autoBluetoothMode; } }; #endif +// Bluetooth Low Energy #ifdef FEATURE_BLE struct BleEnabledAccessor : public RefAccessorSaveSettings { bool &getRef() const override { return settings.bleSettings.bleEnabled; } }; #endif +// Cloud #ifdef FEATURE_CLOUD struct CloudEnabledAccessor : public RefAccessorSaveSettings { bool &getRef() const override { return settings.cloudSettings.cloudEnabled; } }; struct CloudTransmitTimeoutAccessor : public RefAccessorSaveSettings { int16_t &getRef() const override { return settings.cloudSettings.cloudTransmitTimeout; } }; #endif +// Time struct TimezoneOffsetAccessor : public virtual espgui::AccessorInterface { int32_t getValue() const override { return settings.timeSettings.timezoneOffset.count(); } @@ -66,6 +75,7 @@ struct TimeSyncIntervalAccessor : public virtual espgui::AccessorInterface { bool &getRef() const override { return settings.controllerHardware.enableFrontLeft; } }; struct FrontRightEnabledAccessor : public RefAccessorSaveSettings { bool &getRef() const override { return settings.controllerHardware.enableFrontRight; } }; struct BackLeftEnabledAccessor : public RefAccessorSaveSettings { bool &getRef() const override { return settings.controllerHardware.enableBackLeft; } }; @@ -89,6 +99,8 @@ struct SwapFrontBackAccessor : public RefAccessorSaveSettings { void setValue(bool value) override { RefAccessorSaveSettings::setValue(value); updateSwapFrontBack(); }; #endif }; + +// CAN #ifdef FEATURE_CAN struct SendFrontCanCmdAccessor : public RefAccessorSaveSettings { bool &getRef() const override { return settings.controllerHardware.sendFrontCanCmd; } }; struct SendBackCanCmdAccessor : public RefAccessorSaveSettings { bool &getRef() const override { return settings.controllerHardware.sendBackCanCmd; } }; @@ -96,6 +108,7 @@ struct CanTransmitTimeoutAccessor : public RefAccessorSaveSettings { in struct CanReceiveTimeoutAccessor : public RefAccessorSaveSettings { int16_t &getRef() const override { return settings.controllerHardware.canReceiveTimeout; } }; #endif +// Input devices struct SampleCountAccessor : public RefAccessorSaveSettings { int16_t &getRef() const override { return settings.boardcomputerHardware.sampleCount; } }; struct GasMinAccessor : public RefAccessorSaveSettings { int16_t &getRef() const override { return settings.boardcomputerHardware.gasMin; } }; struct GasMaxAccessor : public RefAccessorSaveSettings { int16_t &getRef() const override { return settings.boardcomputerHardware.gasMax; } }; @@ -117,9 +130,13 @@ struct ModeUpdateRateAccessor : public RefAccessorSaveSettings { int16_ struct StatsUpdateRateAccessor : public RefAccessorSaveSettings { int16_t &getRef() const override { return settings.boardcomputerHardware.timersSettings.statsUpdateRate; } }; struct DisplayUpdateRateAccessor : public RefAccessorSaveSettings { int16_t &getRef() const override { return settings.boardcomputerHardware.timersSettings.displayUpdateRate; } }; struct DisplayRedrawRateAccessor : public RefAccessorSaveSettings { int16_t &getRef() const override { return settings.boardcomputerHardware.timersSettings.displayRedrawRate; } }; + +// CAN #ifdef FEATURE_CAN struct CanReceiveRateAccessor : public RefAccessorSaveSettings { int16_t &getRef() const override { return settings.boardcomputerHardware.timersSettings.canReceiveRate; } }; #endif + +// Cloud #ifdef FEATURE_CLOUD struct CloudCollectRateAccessor : public RefAccessorSaveSettings { int16_t &getRef() const override { return settings.boardcomputerHardware.timersSettings.cloudCollectRate; } }; struct CloudSendRateAccessor : public RefAccessorSaveSettings { int16_t &getRef() const override { return settings.boardcomputerHardware.timersSettings.cloudSendRate; } }; @@ -129,6 +146,7 @@ struct CloudDebugEnableAccessor : public RefAccessorSaveSettings { bool &g struct UdpUseStdStringAccessor : public RefAccessorSaveSettings { bool &getRef() const override { return settings.cloudSettings.udpUseStdString; } }; #endif +// DefaultMode struct DefaultModeModelModeAccessor : public RefAccessorSaveSettings { UnifiedModelMode &getRef() const override { return settings.defaultMode.modelMode; } }; struct DefaultModeHybridModelModeAccessor : public RefAccessorSaveSettings { UnifiedModelMode &getRef() const override { return settings.hybrid.hybridMode; } }; struct DefaultModeSquareGasAccessor : public RefAccessorSaveSettings { bool &getRef() const override { return settings.defaultMode.squareGas; } }; @@ -153,15 +171,19 @@ struct DefaultModeEnableHybridAccessor : public RefAccessorSaveSettings { struct DefaultModeHybridActivationLimitAccessor : public RefAccessorSaveSettings { int16_t &getRef() const override { return settings.hybrid.activationLimit; } }; struct DefaultModeHybridDeactivationLimitAccessor : public RefAccessorSaveSettings { int16_t &getRef() const override { return settings.hybrid.deactivationLimit; } }; +// TempomatMode struct TempomatModeModelModeAccessor : public RefAccessorSaveSettings { UnifiedModelMode &getRef() const override { return settings.tempomatMode.modelMode; } }; +// LarsmMode struct LarsmModeModelModeAccessor : public RefAccessorSaveSettings { UnifiedModelMode &getRef() const override { return settings.larsmMode.modelMode; } }; struct LarsmModeModeAccessor : public RefAccessorSaveSettings { LarsmModeMode &getRef() const override { return settings.larsmMode.mode; } }; struct LarsmModeIterationsAccessor : public RefAccessorSaveSettings { uint8_t &getRef() const override { return settings.larsmMode.iterations; } }; +// MotortestMode struct MotortestModeMultiplikatorAccessor : public RefAccessorSaveSettings { uint8_t &getRef() const override { return settings.motortestMode.multiplikator; } }; struct MotortestMaxPwmAccessor : public RefAccessorSaveSettings { uint16_t &getRef() const override { return settings.motortestMode.maxPwm; } }; +// Ledstrip #ifdef FEATURE_LEDSTRIP struct EnableLedAnimationAccessor : public RefAccessorSaveSettings { bool &getRef() const override { return settings.ledstrip.enableLedAnimation; } }; struct EnableBrakeLightsAccessor : public RefAccessorSaveSettings { bool &getRef() const override { return settings.ledstrip.enableBrakeLights; } }; @@ -190,13 +212,19 @@ struct BatteryParallelCellsAccessor : public RefAccessorSaveSettings { struct BatteryWHperKMAccessor : public RefAccessorSaveSettings { uint16_t &getRef() const override { return settings.battery.watthoursPerKilometer; } }; struct BatteryApplyCalibrationAccessor : public RefAccessorSaveSettings { bool &getRef() const override { return settings.battery.applyCalibration; } }; - +// Lockscreen struct LockscreenAllowPresetSwitchAccessor : public RefAccessorSaveSettings { bool &getRef() const override { return settings.lockscreen.allowPresetSwitch; } }; template struct LockscreenPinDigitAccessor : public RefAccessorSaveSettings { int8_t &getRef() const override { return settings.lockscreen.pin[index]; } }; +// Handbremse struct HandbremsEnabledAccessor : public RefAccessorSaveSettings { bool &getRef() const override { return settings.handbremse.enable; } }; struct HandbremsModeAccessor : public RefAccessorSaveSettings { HandbremseMode &getRef() const override { return settings.handbremse.mode; } }; struct HandbremsTimeoutAccessor : public RefAccessorSaveSettings { uint16_t &getRef() const override { return settings.handbremse.triggerTimeout; } }; struct HandbremsAutomaticAccessor : public RefAccessorSaveSettings { bool &getRef() const override { return settings.handbremse.automatic; } }; struct HandbremsVisualizeAccessor : public RefAccessorSaveSettings { bool &getRef() const override { return settings.handbremse.visualize; } }; + +// ESP Now +struct ESPNowSyncTimeEnabledAccessor : public RefAccessorSaveSettings { bool &getRef() const override { return settings.espnow.syncTime; } }; +struct ESPNowSyncTimeWithOthersEnabledAccessor : public RefAccessorSaveSettings { bool &getRef() const override { return settings.espnow.syncTimeWithOthers; } }; +struct ESPNowSyncBlinkEnabledAccessor : public RefAccessorSaveSettings { bool &getRef() const override { return settings.espnow.syncBlink; } }; diff --git a/main/displays/menus/espnowmenu.cpp b/main/displays/menus/espnowmenu.cpp index effc935..c9f1aee 100644 --- a/main/displays/menus/espnowmenu.cpp +++ b/main/displays/menus/espnowmenu.cpp @@ -6,8 +6,10 @@ #include "actions/toggleboolaction.h" #include "checkboxicon.h" #include "icons/back.h" +#include "icons/settings.h" #include "icons/time.h" -#include "settingsmenu.h" +#include "displays/menus/espnowsettingsmenu.h" +#include "displays/menus/settingsmenu.h" using namespace espgui; @@ -18,6 +20,7 @@ EspNowMenu::EspNowMenu() { constructMenuItem, espnowmenu::SendBobbycarTimesyncMessageAction, StaticMenuItemIcon<&bobbyicons::time>>>(); constructMenuItem, ToggleBoolAction, CheckboxIcon, espnowmenu::ReceiveTimeStampAccessor>>(); constructMenuItem, ToggleBoolAction, CheckboxIcon, espnowmenu::ReceiveTsFromOtherBobbycarsAccessor>>(); + constructMenuItem, SwitchScreenAction, StaticMenuItemIcon<&bobbyicons::settings>>>(); constructMenuItem, SwitchScreenAction, StaticMenuItemIcon<&espgui::icons::back>>>(); } diff --git a/main/displays/menus/espnowsettingsmenu.cpp b/main/displays/menus/espnowsettingsmenu.cpp new file mode 100644 index 0000000..e642012 --- /dev/null +++ b/main/displays/menus/espnowsettingsmenu.cpp @@ -0,0 +1,29 @@ +#include "espnowsettingsmenu.h" + +#ifdef FEATURE_ESPNOW +#include "accessors/settingsaccessors.h" +#include "actions/dummyaction.h" +#include "actions/switchscreenaction.h" +#include "actions/toggleboolaction.h" +#include "checkboxicon.h" +#include "icons/back.h" +#include "icons/time.h" +#include "espnowmenu.h" + +using namespace espgui; + +namespace espnowsettingsmenu { +} // namespace + +EspNowSettingsMenu::EspNowSettingsMenu() { + constructMenuItem, ToggleBoolAction, CheckboxIcon, ESPNowSyncTimeEnabledAccessor>>(); + constructMenuItem, ToggleBoolAction, CheckboxIcon, ESPNowSyncTimeWithOthersEnabledAccessor>>(); + constructMenuItem, ToggleBoolAction, CheckboxIcon, ESPNowSyncBlinkEnabledAccessor>>(); + constructMenuItem, SwitchScreenAction, StaticMenuItemIcon<&espgui::icons::back>>>(); +} + +void EspNowSettingsMenu::back() +{ + switchScreen(); +} +#endif diff --git a/main/displays/menus/espnowsettingsmenu.h b/main/displays/menus/espnowsettingsmenu.h new file mode 100644 index 0000000..577d463 --- /dev/null +++ b/main/displays/menus/espnowsettingsmenu.h @@ -0,0 +1,29 @@ +#pragma once + +#ifdef FEATURE_ESPNOW + +#include +#include +#include +#include +#include +#include +#include + +#include "espnowfunctions.h" + +using namespace espgui; + +namespace espnowsettingsmenu { +} // namespace + +class EspNowSettingsMenu : + public espgui::MenuDisplay, + public espgui::StaticText +{ +public: + EspNowSettingsMenu(); + void back() override; +}; + +#endif diff --git a/main/espnowfunctions.cpp b/main/espnowfunctions.cpp index 22d2c97..34cc4a2 100644 --- a/main/espnowfunctions.cpp +++ b/main/espnowfunctions.cpp @@ -43,7 +43,7 @@ void onReceive(const uint8_t *mac_addr, const uint8_t *data, int data_len) } else { - ESP_LOGW(TAG, "Invalid message: Could not find ':'"); + ESP_LOGW(TAG, "Invalid message: Could not find ':' (%s)", data_str.c_str()); } } @@ -116,15 +116,6 @@ void handle() return; } - if (receiveTimeStamp) - { - const auto thisYear = int(espchrono::toDateTime(espchrono::utc_clock::now()).date.year()); - if (abs(thisYear - espnow::lastYear) > 1) - { - receiveTimeStamp = false; - } - } - if(message_queue.size()) { for (const esp_now_message_t &msg : message_queue) @@ -134,7 +125,7 @@ void handle() if (msg.type == "T") { - if (!receiveTimeStamp) + if (!receiveTimeStamp || !settings.espnow.syncTime) return; if (const auto result = cpputils::fromString(msg.content); result) @@ -148,8 +139,17 @@ void handle() } else if (msg.type == "BOBBYT") { - if (!receiveTsFromOtherBobbycars) + if (!receiveTsFromOtherBobbycars || !settings.espnow.syncTimeWithOthers) return; + + if (const auto result = cpputils::fromString(msg.content); result) + { + onRecvTs(*result, true); + } + else + { + ESP_LOGW(TAG, "could not parse number: %.*s", result.error().size(), result.error().data()); + } } else { @@ -159,11 +159,22 @@ void handle() } } -void onRecvTs(uint64_t millis) +void onRecvTs(uint64_t millis, bool isFromBobbycar) { const auto milliseconds = std::chrono::milliseconds(millis); const auto timepoint = espchrono::utc_clock::time_point(milliseconds); + ESP_LOGW(TAG, "setting current time to %s", espchrono::toString(timepoint.time_since_epoch()).c_str()); time_set_now(timepoint); + + if (receiveTimeStamp) + { + if (const auto thisYear = int(espchrono::toDateTime(espchrono::utc_clock::now()).date.year()); abs(thisYear - espnow::lastYear) > 1) + { + espnow::lastYear = thisYear; + receiveTimeStamp = false; + } + } + receiveTsFromOtherBobbycars = false; } diff --git a/main/espnowfunctions.h b/main/espnowfunctions.h index 009adb3..988900a 100644 --- a/main/espnowfunctions.h +++ b/main/espnowfunctions.h @@ -23,7 +23,7 @@ extern std::list peers; void onReceive(const uint8_t *mac_addr, const uint8_t *data, int data_len); void initESPNow(); void handle(); -void onRecvTs(uint64_t millis); +void onRecvTs(uint64_t millis, bool isFromBobbycar = false); esp_err_t send_espnow_message(std::string message); } // namespace espnow #endif diff --git a/main/presets.h b/main/presets.h index 34c1f72..bec092c 100644 --- a/main/presets.h +++ b/main/presets.h @@ -300,6 +300,19 @@ constexpr Settings::SavedStatistics defaultSavedStatistics { .totalCentimeters = 0, }; +#ifdef FEATURE_ESPNOW +constexpr Settings::ESPNOW defaultEspNowSettings { +#ifndef FEATURE_NTP + .syncTime = true, + .syncTimeWithOthers = true, +#else + .syncTime = false, + .syncTimeWithOthers = false, +#endif + .syncBlink = false +}; +#endif + constexpr Settings defaultSettings { #ifdef FEATURE_BMS .autoConnectBms = false, @@ -330,7 +343,10 @@ constexpr Settings defaultSettings { .hybrid = defaultHybrid, .lockscreen = defaultLockscreen, .savedStatistics = defaultSavedStatistics, - .handbremse = defaultHandbremse + .handbremse = defaultHandbremse, +#ifdef FEATURE_ESPNOW + .espnow = defaultEspNowSettings, +#endif }; StringSettings makeDefaultStringSettings(); diff --git a/main/settings.h b/main/settings.h index 87549e4..9840a25 100644 --- a/main/settings.h +++ b/main/settings.h @@ -224,6 +224,13 @@ struct Settings bool enable; bool visualize; } handbremse; +#ifdef FEATURE_ESPNOW + struct ESPNOW { + bool syncTime; + bool syncTimeWithOthers; + bool syncBlink; + } espnow; +#endif template void executeForEveryCommonSetting(T &&callable); @@ -362,6 +369,14 @@ void Settings::executeForEveryCommonSetting(T &&callable) callable("handBremsM", handbremse.mode); callable("handBremsT", handbremse.triggerTimeout); callable("handBremsV", handbremse.visualize); + +#ifdef FEATURE_ESPNOW + callable("espnowSyncT", espnow.syncTime); + callable("espnowSyncTWO", espnow.syncTimeWithOthers); +#ifdef FEATURE_LEDSTRIP + callable("espnowSyncBl", espnow.syncBlink); +#endif +#endif } template diff --git a/main/texts.cpp b/main/texts.cpp index ec23560..dca1e63 100644 --- a/main/texts.cpp +++ b/main/texts.cpp @@ -550,4 +550,10 @@ char TEXT_ESPNOW_MENU[] = "ESP-Now Menu"; char TEXT_ESPNOW_RECEIVETS[] = "Recv Ts State"; char TEXT_ESPNOW_RECEIVETSFROMBOBBY[] = "Recv BobbyTs State"; char TEXT_ESPNOW_SENDTSMSG[] = "Broadcast Time"; + +//EspNowSettingsMenu +char TEXT_ESPNOW_SETTINGS[] = "ESP-Now settings"; +char TEXT_ESPNOW_SYNCTIME[] = "Sync time (no NTP)"; +char TEXT_ESPNOW_SYNCWITHOTHERS[] = "Sync time with others"; +char TEXT_ESPNOW_SYNCBLINK[] = "Sync blink"; } // namespace diff --git a/main/texts.h b/main/texts.h index ed83a05..22ec3b5 100644 --- a/main/texts.h +++ b/main/texts.h @@ -550,6 +550,12 @@ extern char TEXT_ESPNOW_MENU[]; extern char TEXT_ESPNOW_RECEIVETS[]; extern char TEXT_ESPNOW_RECEIVETSFROMBOBBY[]; extern char TEXT_ESPNOW_SENDTSMSG[]; + +//EspNowSettingsMenu +extern char TEXT_ESPNOW_SETTINGS[]; +extern char TEXT_ESPNOW_SYNCTIME[]; +extern char TEXT_ESPNOW_SYNCWITHOTHERS[]; +extern char TEXT_ESPNOW_SYNCBLINK[]; } // namespace using namespace bobbytexts;