diff --git a/configs/config_allfeatures.cmake b/configs/config_allfeatures.cmake index c31fb31..ebb04d0 100644 --- a/configs/config_allfeatures.cmake +++ b/configs/config_allfeatures.cmake @@ -1,5 +1,5 @@ set(BOBBY_APP_NAME bobbyquad_allfeatures) -set(BOBBY_DEFAULT_OTA_NAME allfeatures) +set(BOBBY_DEFAULT_USERNAME allfeatures) add_definitions( -DUSER_SETUP_LOADED=1 diff --git a/configs/config_aveexy.cmake b/configs/config_aveexy.cmake index 5a182ac..26e56a7 100644 --- a/configs/config_aveexy.cmake +++ b/configs/config_aveexy.cmake @@ -1,5 +1,5 @@ set(BOBBY_APP_NAME bobbyquad_aveexy) -set(BOBBY_DEFAULT_OTA_NAME aveexy) +set(BOBBY_DEFAULT_USERNAME aveexy) add_definitions( -DUSER_SETUP_LOADED=1 diff --git a/configs/config_comred.cmake b/configs/config_comred.cmake index 200477c..4927903 100644 --- a/configs/config_comred.cmake +++ b/configs/config_comred.cmake @@ -1,5 +1,5 @@ set(BOBBY_APP_NAME bobbyquad_comred) -set(BOBBY_DEFAULT_OTA_NAME comred) +set(BOBBY_DEFAULT_USERNAMENAME comred) add_definitions( -DUSER_SETUP_LOADED=1 diff --git a/configs/config_comred_new.cmake b/configs/config_comred_new.cmake index f758436..fe9ea98 100644 --- a/configs/config_comred_new.cmake +++ b/configs/config_comred_new.cmake @@ -1,5 +1,5 @@ set(BOBBY_APP_NAME bobbyquad_comred_new) -set(BOBBY_DEFAULT_OTA_NAME comred_new) +set(BOBBY_DEFAULT_USERNAME comred_new) add_definitions( -DUSER_SETUP_LOADED=1 diff --git a/configs/config_feedc0de.cmake b/configs/config_feedc0de.cmake index 516be0a..a59e838 100644 --- a/configs/config_feedc0de.cmake +++ b/configs/config_feedc0de.cmake @@ -1,5 +1,5 @@ set(BOBBY_APP_NAME bobbyquad_feedc0de) -set(BOBBY_DEFAULT_OTA_NAME feedc0de) +set(BOBBY_DEFAULT_USERNAME feedc0de) set(BOBBYCAR_BUILDFLAGS # Pins diff --git a/configs/config_feedc0de_new.cmake b/configs/config_feedc0de_new.cmake index bc88230..daeca83 100644 --- a/configs/config_feedc0de_new.cmake +++ b/configs/config_feedc0de_new.cmake @@ -1,5 +1,5 @@ set(BOBBY_APP_NAME bobbyquad_feedc0de) -set(BOBBY_DEFAULT_OTA_NAME feedc0de) +set(BOBBY_DEFAULT_USERNAME feedc0de) set(BOBBYCAR_BUILDFLAGS # Pins diff --git a/configs/config_gernot.cmake b/configs/config_gernot.cmake index d37fe63..85055ca 100644 --- a/configs/config_gernot.cmake +++ b/configs/config_gernot.cmake @@ -1,5 +1,5 @@ set(BOBBY_APP_NAME bobbyquad_gernot) -set(BOBBY_DEFAULT_OTA_NAME gernot) +set(BOBBY_DEFAULT_USERNAME gernot) add_definitions( -DUSER_SETUP_LOADED=1 diff --git a/configs/config_greyhash.cmake b/configs/config_greyhash.cmake index d041659..23ef7f0 100644 --- a/configs/config_greyhash.cmake +++ b/configs/config_greyhash.cmake @@ -1,5 +1,5 @@ set(BOBBY_APP_NAME bobbyquad_greyhash) -set(BOBBY_DEFAULT_OTA_NAME greyhash) +set(BOBBY_DEFAULT_USERNAME greyhash) add_definitions( -DUSER_SETUP_LOADED=1 diff --git a/configs/config_mick.cmake b/configs/config_mick.cmake index 55098db..7e88d34 100644 --- a/configs/config_mick.cmake +++ b/configs/config_mick.cmake @@ -1,5 +1,5 @@ set(BOBBY_APP_NAME bobbyquad_mick) -set(BOBBY_DEFAULT_OTA_NAME mick) +set(BOBBY_DEFAULT_USERNAME mick) add_definitions( -DUSER_SETUP_LOADED=1 diff --git a/configs/config_nofeatures.cmake b/configs/config_nofeatures.cmake index 3018346..bc02294 100644 --- a/configs/config_nofeatures.cmake +++ b/configs/config_nofeatures.cmake @@ -1,5 +1,5 @@ set(BOBBY_APP_NAME bobbyquad_nofeatures) -set(BOBBY_DEFAULT_OTA_NAME nofeatures) +set(BOBBY_DEFAULT_USERNAME nofeatures) add_definitions( -DUSER_SETUP_LOADED=1 diff --git a/configs/config_peter.cmake b/configs/config_peter.cmake index 8f52ae0..5f5c000 100644 --- a/configs/config_peter.cmake +++ b/configs/config_peter.cmake @@ -1,5 +1,5 @@ set(BOBBY_APP_NAME bobbyquad_peter) -set(BOBBY_DEFAULT_OTA_NAME peter) +set(BOBBY_DEFAULT_USERNAME peter) add_definitions( -DUSER_SETUP_LOADED=1 diff --git a/configs/config_seatbot.cmake b/configs/config_seatbot.cmake index 8834602..34500bc 100644 --- a/configs/config_seatbot.cmake +++ b/configs/config_seatbot.cmake @@ -1,5 +1,5 @@ set(BOBBY_APP_NAME bobbyquad_seatbot) -set(BOBBY_DEFAULT_OTA_NAME seatbot) +set(BOBBY_DEFAULT_USERNAME seatbot) add_definitions( -DUSER_SETUP_LOADED=1 diff --git a/configs/config_testdevice.cmake b/configs/config_testdevice.cmake index 738b12b..235c2fd 100644 --- a/configs/config_testdevice.cmake +++ b/configs/config_testdevice.cmake @@ -1,5 +1,5 @@ set(BOBBY_APP_NAME testdevice) -set(BOBBY_DEFAULT_OTA_NAME testdevice) +set(BOBBY_DEFAULT_USERNAME testdevice) add_definitions( -DUSER_SETUP_LOADED=1 diff --git a/configs/config_testdevice2.cmake b/configs/config_testdevice2.cmake index 4d5a9fe..4326734 100644 --- a/configs/config_testdevice2.cmake +++ b/configs/config_testdevice2.cmake @@ -1,5 +1,5 @@ set(BOBBY_APP_NAME testdevice2) -set(BOBBY_DEFAULT_OTA_NAME testdevice2) +set(BOBBY_DEFAULT_USERNAME testdevice2) add_definitions( -DUSER_SETUP_LOADED=1 diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 6a36651..5227b44 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -175,6 +175,7 @@ set(headers drivingstatistics.h espnowfunctions.h esptexthelpers.h + feedbackemulator.h feedbackparser.h globals.h handbremse.h @@ -425,6 +426,7 @@ set(sources drivingstatistics.cpp espnowfunctions.cpp esptexthelpers.cpp + feedbackemulator.cpp feedbackparser.cpp globals.cpp handbremse.cpp @@ -544,8 +546,8 @@ string(REPLACE "\n" " " GIT_MESSAGE "${GIT_MESSAGE}") string(SUBSTRING "${GIT_MESSAGE}" 0 100 GIT_MESSAGE) string(STRIP "${GIT_BRANCH}" GIT_BRANCH) -if(NOT DEFINED BOBBY_DEFAULT_OTA_NAME) - message(FATAL_ERROR "Please define BOBBY_DEFAULT_OTA_NAME") +if(NOT DEFINED BOBBY_DEFAULT_USERNAME) + message(FATAL_ERROR "Please define BOBBY_DEFAULT_USERNAME") endif() target_compile_options(${COMPONENT_TARGET} @@ -561,6 +563,6 @@ target_compile_options(${COMPONENT_TARGET} -DGIT_SHORT_REV="${GIT_SHORT_REV}" -DGIT_MESSAGE="${GIT_MESSAGE}" -DGIT_BRANCH="${GIT_BRANCH}" - -DBOBBY_DEFAULT_OTA_NAME="${BOBBY_DEFAULT_OTA_NAME}" + -DBOBBY_DEFAULT_USERNAME="${BOBBY_DEFAULT_USERNAME}" ${BOBBYCAR_BUILDFLAGS} ) diff --git a/main/accessors/settingsaccessors.h b/main/accessors/settingsaccessors.h index 96a1120..6170d8e 100644 --- a/main/accessors/settingsaccessors.h +++ b/main/accessors/settingsaccessors.h @@ -129,8 +129,9 @@ struct CloudSendRateAccessor : public NewSettingsAccessor { ConfigWrapp struct UdpCloudSendIntervalAccessor : public NewSettingsAccessor { ConfigWrapper &getConfig() const override { return configs.boardcomputerHardware.timersSettings.udpSendRateMs; } }; struct UdpCloudEnabledAccessor : public NewSettingsAccessor { ConfigWrapper &getConfig() const override { return configs.udpCloudSettings.udpCloudEnabled; } }; -struct CloudDebugEnableAccessor : public NewSettingsAccessor { ConfigWrapper &getConfig() const override { return configs.udpCloudSettings.enableCloudDebug; } }; -struct UdpUseStdStringAccessor : public NewSettingsAccessor { ConfigWrapper &getConfig() const override { return configs.udpCloudSettings.udpUseStdString; } }; +struct UdpCloudDebugEnableAccessor : public NewSettingsAccessor { ConfigWrapper &getConfig() const override { return configs.udpCloudSettings.enableCloudDebug; } }; +struct UdpCloudHostAccessor : public NewSettingsAccessor { ConfigWrapper &getConfig() const override { return configs.udpCloudSettings.udpCloudHost; } }; +struct UdpCloudPortAccessor : public NewSettingsAccessor { ConfigWrapper &getConfig() const override { return configs.udpCloudSettings.udpCloudPort; } }; // DefaultMode struct DefaultModeModelModeAccessor : public RefAccessorSaveSettings { UnifiedModelMode &getRef() const override { return profileSettings.defaultMode.modelMode; } }; @@ -269,3 +270,4 @@ struct FlipScreenAccessor : public NewSettingsAccessor { ConfigWrapper { ConfigWrapper &getConfig() const override { return configs.anhaenger_id; } }; +struct UsernameAccessor : public NewSettingsAccessor { ConfigWrapper &getConfig() const override { return configs.otaUsername; } }; diff --git a/main/can.cpp b/main/can.cpp index a4c982b..2327382 100644 --- a/main/can.cpp +++ b/main/can.cpp @@ -82,6 +82,11 @@ void initCan() void updateCan() { + if (configs.emulateFeedback.value()) + { + return; + } + for (int i = 0; i < 4; i++) if (!tryParseCanInput()) break; diff --git a/main/displays/menus/debugmenu.cpp b/main/displays/menus/debugmenu.cpp index 96def16..55871cd 100644 --- a/main/displays/menus/debugmenu.cpp +++ b/main/displays/menus/debugmenu.cpp @@ -73,7 +73,7 @@ DebugMenu::DebugMenu() constructMenuItem, PushScreenAction, StaticMenuItemIcon<&bobbyicons::battery>>>(); if (configs.feature.udpcloud.isEnabled.value()) { - constructMenuItem, BobbyCheckbox, CloudDebugEnableAccessor>>(); + constructMenuItem, BobbyCheckbox, UdpCloudDebugEnableAccessor>>(); } constructMenuItem, DisabledColor, DummyAction>>(); #ifdef FEATURE_CAN diff --git a/main/displays/menus/settingsmenu.cpp b/main/displays/menus/settingsmenu.cpp index 031d97a..b26e076 100644 --- a/main/displays/menus/settingsmenu.cpp +++ b/main/displays/menus/settingsmenu.cpp @@ -1,9 +1,11 @@ #include "settingsmenu.h" // 3rdparty lib includes -#include "actions/pushscreenaction.h" -#include "actions/popscreenaction.h" -#include "icons/back.h" +#include +#include +#include +#include +#include // local includes #include "accessors/settingsaccessors.h" @@ -21,7 +23,6 @@ #include "displays/menus/featureflagsmenu.h" #include "displays/menus/gitmenu.h" #include "displays/menus/limitssettingsmenu.h" -#include "displays/menus/mainmenu.h" #include "displays/menus/modessettingsmenu.h" #include "displays/menus/networksettingsmenu.h" #include "displays/menus/selectbuildservermenu.h" @@ -37,8 +38,6 @@ #include "icons/time.h" #include "icons/update.h" #include "icons/wifi.h" -#include "textwithvaluehelper.h" -#include "utils.h" namespace { constexpr char TEXT_SETTINGS[] = "Settings"; @@ -56,6 +55,7 @@ constexpr char TEXT_MODESSETTINGS[] = "Modes settings"; constexpr char TEXT_CONTROLLERHARDWARESETTINGS[] = "Controller H/W settings"; constexpr char TEXT_BOARDCOMPUTERHARDWARESETTINGS[] = "Boardcomputer H/W settings"; constexpr char TEXT_FEATUREFLAGS[] = "Feature flags"; +constexpr char TEXT_USERNAME[] = "Username"; // ota-name constexpr char TEXT_ANHAENGER_ID[] = "Anhaenger ID"; constexpr char TEXT_AUTOCONNECTBMS[] = "Auto connect BMS"; constexpr char TEXT_BUZZER[] = "Buzzer"; @@ -83,6 +83,14 @@ using AnhaengerIdChangeScreen = espgui::makeComponent< espgui::ConfirmActionInterface, espgui::BackActionInterface >; + +using UsernameChangeScreen = espgui::makeComponent< + BobbyChangeValueDisplay, + espgui::StaticText, + UsernameAccessor, + espgui::ConfirmActionInterface, + espgui::BackActionInterface +>; } // namespace using namespace espgui; @@ -117,7 +125,8 @@ SettingsMenu::SettingsMenu() constructMenuItem, PushScreenAction, StaticMenuItemIcon<&bobbyicons::hardware>>>(); } constructMenuItem, PushScreenAction, StaticMenuItemIcon<&bobbyicons::demos>>>(); - constructMenuItem, espgui::PushScreenAction>>(); + constructMenuItem, PushScreenAction>>(); + constructMenuItem, PushScreenAction>>(); //#if defined(FEATURE_BLUETOOTH) && defined(FEATURE_BMS) // constructMenuItem, BobbyCheckbox, AutoConnectBmsAccessor>>(); //#endif diff --git a/main/displays/menus/udpcloudsettingsmenu.cpp b/main/displays/menus/udpcloudsettingsmenu.cpp index 2e4b346..ca3373b 100644 --- a/main/displays/menus/udpcloudsettingsmenu.cpp +++ b/main/displays/menus/udpcloudsettingsmenu.cpp @@ -3,7 +3,7 @@ // 3rdparty lib includes #include #include -#include +#include #include #include #include @@ -17,7 +17,8 @@ namespace { constexpr char TEXT_UDPCLOUDSETTINGS[] = "UDP Cloud settings"; constexpr char TEXT_UDPCLOUDENABLED[] = "Udp Cloud enabled"; constexpr char TEXT_UDPSENDRATE[] = "Udp send rate"; -constexpr char TEXT_UDPUSESTRING[] = "Udp use std::string"; +constexpr char TEXT_UDPHOST[] = "Udp host"; +constexpr char TEXT_UDPPORT[] = "Udp port"; constexpr char TEXT_BACK[] = "Back"; using UdpCloudSendRateChangeDisplay = espgui::makeComponent< @@ -27,6 +28,22 @@ using UdpCloudSendRateChangeDisplay = espgui::makeComponent< espgui::ConfirmActionInterface, espgui::BackActionInterface >; + +using UdpCloudHostChangeDisplay = espgui::makeComponent< + BobbyChangeValueDisplay, + espgui::StaticText, + UdpCloudHostAccessor, + espgui::ConfirmActionInterface, + espgui::BackActionInterface +>; + +using UdpCloudPortChangeDisplay = espgui::makeComponent< + BobbyChangeValueDisplay, + espgui::StaticText, + UdpCloudPortAccessor, + espgui::ConfirmActionInterface, + espgui::BackActionInterface +>; } // namespace using namespace espgui; @@ -34,8 +51,9 @@ using namespace espgui; UdpCloudSettingsMenu::UdpCloudSettingsMenu() { constructMenuItem, BobbyCheckbox, UdpCloudEnabledAccessor>>(); - constructMenuItem, BobbyCheckbox, UdpUseStdStringAccessor>>(); constructMenuItem, PushScreenAction>>(); + constructMenuItem, PushScreenAction>>(); + constructMenuItem, PushScreenAction>>(); constructMenuItem, PopScreenAction, StaticMenuItemIcon<&espgui::icons::back>>>(); } diff --git a/main/feedbackemulator.cpp b/main/feedbackemulator.cpp new file mode 100644 index 0000000..63f9346 --- /dev/null +++ b/main/feedbackemulator.cpp @@ -0,0 +1,55 @@ +#include "feedbackemulator.h" + +// 3rdparty lib includes +#include +#include + +// local includes +#include "globals.h" + +namespace feedbackemulator { +void init() +{} + +void update() +{ + if (!configs.emulateFeedback.value()) + { + return; + } + + for (auto &controller: controllers) + { + controller.feedback.left.dcLink = cpputils::randomNumber(-500, 500, espcpputils::esp_random_device{}); + controller.feedback.right.dcLink = cpputils::randomNumber(-500, 500, espcpputils::esp_random_device{}); + controller.feedback.left.speed = cpputils::randomNumber(-1000, 1000, espcpputils::esp_random_device{}); + controller.feedback.right.speed = cpputils::randomNumber(-1000, 1000, espcpputils::esp_random_device{}); + controller.feedback.left.error = cpputils::randomNumber(0, 4, espcpputils::esp_random_device{}); + controller.feedback.right.error = cpputils::randomNumber(0, 4, espcpputils::esp_random_device{}); + controller.feedback.left.angle = 0; + controller.feedback.right.angle = 0; + controller.feedback.left.dcPhaA = cpputils::randomNumber(-5, 5, espcpputils::esp_random_device{}); + controller.feedback.right.dcPhaA = cpputils::randomNumber(-5, 5, espcpputils::esp_random_device{}); + controller.feedback.left.dcPhaB = cpputils::randomNumber(-5, 5, espcpputils::esp_random_device{}); + controller.feedback.right.dcPhaB = cpputils::randomNumber(-5, 5, espcpputils::esp_random_device{}); + controller.feedback.left.dcPhaC = cpputils::randomNumber(-5, 5, espcpputils::esp_random_device{}); + controller.feedback.right.dcPhaC = cpputils::randomNumber(-5, 5, espcpputils::esp_random_device{}); + controller.feedback.left.chops = 0; + controller.feedback.right.chops = 0; + controller.feedback.left.hallA = true; + controller.feedback.left.hallB = false; + controller.feedback.left.hallC = true; + controller.feedback.right.hallA = false; + controller.feedback.right.hallB = true; + controller.feedback.right.hallC = false; + controller.feedback.batVoltage = cpputils::randomNumber(3000, 5000, espcpputils::esp_random_device{}); + controller.feedback.boardTemp = cpputils::randomNumber(200, 600, espcpputils::esp_random_device{}); + controller.feedback.left.id = 0; + controller.feedback.right.id = 0; + controller.feedback.left.iq = 0; + controller.feedback.right.iq = 0; + + controller.feedbackValid = true; + } +} +} // feedbackemulator diff --git a/main/feedbackemulator.h b/main/feedbackemulator.h new file mode 100644 index 0000000..6b1247b --- /dev/null +++ b/main/feedbackemulator.h @@ -0,0 +1,6 @@ +#pragma once + +namespace feedbackemulator { + void init(); + void update(); +} // namespace feedbackemulator diff --git a/main/newsettings.cpp b/main/newsettings.cpp index daa0e5b..69e6f10 100644 --- a/main/newsettings.cpp +++ b/main/newsettings.cpp @@ -23,7 +23,7 @@ std::string defaultHostname() std::string defaultUsername() { - return fmt::format("bobby_{}", BOBBY_DEFAULT_OTA_NAME); + return fmt::format("bobby_{}", BOBBY_DEFAULT_USERNAME); } ConfigManager configs; diff --git a/main/newsettings.h b/main/newsettings.h index 78919b1..7b1186d 100644 --- a/main/newsettings.h +++ b/main/newsettings.h @@ -324,10 +324,9 @@ public: ConfigWrapperLegacy reverseBeepDuration1{500, DoReset, {}, "revBeepDur1" }; ConfigWrapperLegacy cloudUrl {"ws://api.bobbycar.cloud/ws", DoReset, StringOr, "cloudUrl" }; - ConfigWrapperLegacy udpCloudHost {"updates.bobbycar.cloud", DoReset, {}, "udpCloudHost" }; ConfigWrapperLegacy otaUrl {std::string{}, DoReset, StringOr, "otaUrl" }; - ConfigWrapperLegacy otaUsername {std::string{BOBBY_DEFAULT_OTA_NAME}, DoReset, {}, "otaUsername" }; + ConfigWrapperLegacy otaUsername {std::string{BOBBY_DEFAULT_USERNAME}, DoReset, {}, "otaUsername" }; ConfigWrapperLegacy otaServerUrl {std::string{}, DoReset, StringOr, "otaServerUrl" }; ConfigWrapperLegacy otaServerBranch {std::string{}, DoReset, {}, "otaServerBranch" }; std::array otaServers { @@ -376,10 +375,11 @@ public: } cloudSettings; struct { - ConfigWrapperLegacy udpUid {0, DoReset, {}, "cloudUDPUid" }; + ConfigWrapperLegacy udpToken {std::string{}, DoReset, {}, "udpToken" }; ConfigWrapperLegacy udpCloudEnabled {false, DoReset, {}, "enUdpCloud" }; ConfigWrapperLegacy enableCloudDebug {false, DoReset, {}, "debugCloud" }; - ConfigWrapperLegacy udpUseStdString {false, DoReset, {}, "udpusestdstr" }; + ConfigWrapperLegacy udpCloudPort {24243, DoReset, {}, "udpCloudPort" }; + ConfigWrapperLegacy udpCloudHost {"updates.bobbycar.cloud", DoReset, {}, "udpCloudHost" }; } udpCloudSettings; struct { @@ -400,7 +400,7 @@ public: ConfigWrapperLegacy brightness {255, DoReset, {}, "ledbrightness" }; ConfigWrapperLegacy enableAnimBlink {false, DoReset, {}, "enAnimBlink" }; ConfigWrapperLegacy otaMode {OtaAnimationModes::GreenProgressBar, DoReset, {}, "ledOtaAnim" }; - ConfigWrapperLegacy maxMilliamps {3000, DoReset, {}, "ledMaxMilliamps" }; + ConfigWrapperLegacy maxMilliamps {3000, DoReset, {}, "ledMaxMilliamps" }; ConfigWrapperLegacy enableVisualizeBlink {false, DoReset, {}, "enVisualBlink" }; std::array, 8> custom_color { ConfigWrapperLegacy {0, DoReset, {}, "ledCustomCol1" }, @@ -480,6 +480,7 @@ public: } feature; ConfigWrapperLegacy anhaenger_id {0, DoReset, {}, "anhaenger_id" }; + ConfigWrapperLegacy emulateFeedback {false, DoReset, {}, "emuFeedback" }; struct { ConfigWrapperLegacy bleEnabled {true, DoReset, {}, "bleEnabled" }; @@ -671,7 +672,6 @@ public: x(reverseBeepDuration1) \ \ x(cloudUrl) \ - x(udpCloudHost) \ \ x(otaUrl) \ x(otaUsername) \ @@ -719,10 +719,11 @@ public: x(cloudSettings.cloudKey) \ x(cloudSettings.sendStatistic) \ \ - x(udpCloudSettings.udpUid) \ + x(udpCloudSettings.udpToken) \ x(udpCloudSettings.udpCloudEnabled) \ - x(udpCloudSettings.enableCloudDebug) \ - x(udpCloudSettings.udpUseStdString) \ + x(udpCloudSettings.enableCloudDebug) \ + x(udpCloudSettings.udpCloudPort) \ + x(udpCloudSettings.udpCloudHost) \ \ x(ledstrip.enableLedAnimation) \ x(ledstrip.enableBrakeLights) \ @@ -802,7 +803,8 @@ public: x(feature.udpcloud.isEnabled) \ x(feature.webserver.isEnabled) \ x(feature.webserver_disable_lock.isEnabled) \ - x(bleSettings.bleEnabled) + x(bleSettings.bleEnabled) \ + x(emulateFeedback) #define FEATURES(x) \ x(feature.ble) \ diff --git a/main/qrimport.h b/main/qrimport.h index 3220774..0c9d7c3 100644 --- a/main/qrimport.h +++ b/main/qrimport.h @@ -1,7 +1,7 @@ #pragma once /* * In this file there will be - * - a web-handler to get qr as plain text from http://qr.bobbycar.cloud/files/[OTA_NAME].qr that can be later triggered via in qrimportdisplay.h + * - a web-handler to get qr as plain text from http://qr.bobbycar.cloud/files/[USERNAME].qr that can be later triggered via in qrimportdisplay.h * - getter and setter that use NVS */ diff --git a/main/taskmanager.cpp b/main/taskmanager.cpp index b7eb6f2..ee3e8ef 100644 --- a/main/taskmanager.cpp +++ b/main/taskmanager.cpp @@ -43,6 +43,7 @@ #include "dnsannounce.h" #include "screens.h" #include "utils.h" +#include "feedbackemulator.h" using namespace std::chrono_literals; @@ -83,12 +84,13 @@ BobbySchedulerTask schedulerTasksArr[] { BobbySchedulerTask { "ledstrip", initLedStrip, updateLedStrip, 30ms, false }, BobbySchedulerTask { "espnow", espnow::initESPNow, espnow::handle, 100ms, false }, BobbySchedulerTask { "cloud", initCloud, updateCloud, 50ms, false }, - BobbySchedulerTask { "udpcloud", udpCloudInit, udpCloudUpdate, 50ms, false }, + BobbySchedulerTask { "udpcloud", udpCloudInit, udpCloudUpdate, 25ms, false }, BobbySchedulerTask { "drivingmode", initDrivingMode, updateDrivingMode, 20ms, false }, BobbySchedulerTask { "drivingstatistics", initStatistics, calculateStatistics, 100ms, false }, BobbySchedulerTask { "dnsannounce", init_dns_announce, handle_dns_announce, 100ms, false }, BobbySchedulerTask { "updateDisp", not_needed, updateDisplay, 20ms, true }, BobbySchedulerTask { "redrawDisp", not_needed, redrawDisplay, 20ms, true }, + BobbySchedulerTask { "feedbackEmulator", feedbackemulator::init, feedbackemulator::update, 500ms, false}, }; } // namespace diff --git a/main/udpcloud.cpp b/main/udpcloud.cpp index b7cf492..984c6c4 100644 --- a/main/udpcloud.cpp +++ b/main/udpcloud.cpp @@ -1,25 +1,24 @@ #include "udpcloud.h" +// system includes +#include +#include +#include + // 3rd party includes #include #include -#include -#include -#include +#include #include +#include // local includes -#include "udpsender.h" -#include "espwifistack.h" -#include "esp_log.h" -#include "fmt/format.h" -#include "globals.h" -#include "utils.h" -#include "lwip/dns.h" -#include "espchrono.h" #include "battery.h" #include "drivingstatistics.h" +#include "globals.h" #include "newsettings.h" +#include "udpsender.h" +#include "utils.h" using namespace std::chrono_literals; @@ -27,6 +26,9 @@ namespace { constexpr const char * const TAG = "bobbycloud"; espchrono::millis_clock::time_point timestampLastFailed; +espchrono::millis_clock::time_point lastSend; + +uint8_t packageType{0}; // cycle through packages. } // namespace // Little "flash" on statusdisplay when udp stuff is happening @@ -42,305 +44,154 @@ void udpCloudUpdate() if (!configs.feature.udpcloud.isEnabled.value()) return; - if (configs.udpCloudSettings.udpCloudEnabled.value() && configs.udpCloudSettings.udpUid.touched()) + if (configs.udpCloudSettings.udpCloudEnabled.value() && configs.udpCloudSettings.udpToken.touched()) sendUdpCloudPacket(); } -void spamUdpBroadcast() +std::optional buildUdpCloudJson() { - wifi_stack::UdpSender sender; + StaticJsonDocument<512> doc; - if (!sender.ready()) + switch (++packageType) { - ESP_LOGE(TAG, "could not init udp sender!"); - return; + default: + packageType = 0; + case 0: + { + // uptime, potis + const auto uptime = espchrono::millis_clock::now().time_since_epoch() / 1ms; + doc["upt"] = uptime; + + if (gas) + doc["pcg"] = *gas; // poti calculated gas + if (raw_gas) + doc["prg"] = *raw_gas; // poti raw gas + if (brems) + doc["pcb"] = *brems; // poti calculated brems + if (raw_brems) + doc["prb"] = *raw_brems; // poti raw brems + + doc["loc"] = isLocked; + doc["mdr"] = drivingStatistics.meters_driven; + doc["mdt"] = drivingStatistics.totalMeters; + doc["cdt"] = drivingStatistics.currentDrivingTime / 1ms; + doc["sha"] = GIT_REV; + break; } - - std::string buf; - const auto uptime = espchrono::millis_clock::now().time_since_epoch() / 1ms; - - buf = fmt::format("uptime: {}", uptime); - - if (const auto result = sender.send(ESP_IF_WIFI_STA, 187, buf); !result) + case 1: { - ESP_LOGE(TAG, "broadcast failed"); - } -} -std::string buildUdpCloudJson() -{ - static std::string version_string; - if (version_string.empty() || version_string == "-") - { - if (const esp_app_desc_t *app_desc = esp_ota_get_app_description()) + if (const auto avgVoltage = controllers.getAvgVoltage(); avgVoltage) { - version_string = app_desc->version; - } - else - { - version_string = "-"; + doc["bap"] = getBatteryPercentage(*avgVoltage, BatteryCellType(configs.battery.cellType.value())); + doc["bav"] = *avgVoltage; // battery voltage + doc["pwr"] = sumCurrent * *avgVoltage; // total watt } + doc["whl"] = getRemainingWattHours(); // watt hours left + doc["kml"] = getRemainingWattHours() / configs.battery.watthoursPerKilometer.value(); // calculated kilometers left + doc["ekm"] = getEstimatedKmLeft(); // kilometers left live calculation + break; } - StaticJsonDocument<1024> doc; - std::string buf; - const auto uptime = espchrono::millis_clock::now().time_since_epoch() / 1ms; - - float watt{0}; - const auto avgVoltage = controllers.getAvgVoltage(); - if(avgVoltage) - watt = sumCurrent * *avgVoltage; - - // const auto w_per_kmh = watt / avgSpeedKmh; - - // User ID - doc["uid"] = configs.udpCloudSettings.udpUid.value(); - doc["upt"] = uptime; - - const auto addController = [&](const Controller &controller, const bool isBack) { + case 2: + { + const auto &controller = controllers.front; if (controller.feedbackValid) { - auto arr = doc.createNestedObject(!isBack ? "f":"b"); - // Voltage - arr["V"] = controller.getCalibratedVoltage(); + doc["fbv"] = controller.getCalibratedVoltage(); // Amperes - arr["lA"] = fixCurrent(controller.feedback.left.dcLink); - arr["rA"] = fixCurrent(controller.feedback.right.dcLink); + doc["fla"] = fixCurrent(controller.feedback.left.dcLink); + doc["fra"] = fixCurrent(controller.feedback.right.dcLink); // Temperature - arr[!isBack ? "fT":"bT"] = fixBoardTemp(controller.feedback.boardTemp); + doc["fbt"] = fixBoardTemp(controller.feedback.boardTemp); // Errors - arr[!isBack ? "flE":"blE"] = controller.feedback.left.error; - arr[!isBack ? "frE":"brE"] = controller.feedback.right.error; + doc["fle"] = controller.feedback.left.error; + doc["fre"] = controller.feedback.right.error; // Speed - arr[!isBack ? "flS":"blS"] = convertToKmh(controller.feedback.left.speed) * (controller.invertLeft?-1:1); - arr[!isBack ? "frS":"brS"] = convertToKmh(controller.feedback.right.speed) * (controller.invertRight?-1:1); + doc["fls"] = convertToKmh(controller.feedback.left.speed) * (controller.invertLeft?-1:1); + doc["frs"] = convertToKmh(controller.feedback.right.speed) * (controller.invertRight?-1:1); } else { - doc[!isBack ? "f":"b"] = nullptr; + return std::nullopt; } - }; - - addController(controllers.front, false); - addController(controllers.back, true); - - // Potis + break; + } + case 3: { - auto arr = doc.createNestedObject("p"); - if (gas) - arr["g"] = *gas; - if (raw_gas) - arr["rg"] = *raw_gas; - if (brems) - arr["b"] = *brems; - if (raw_brems) - arr["rb"] = *raw_brems; + const auto &controller = controllers.back; + if (controller.feedbackValid) + { + doc["bbv"] = controller.getCalibratedVoltage(); + + // Amperes + doc["bla"] = fixCurrent(controller.feedback.left.dcLink); + doc["bra"] = fixCurrent(controller.feedback.right.dcLink); + + // Temperature + doc["bbt"] = fixBoardTemp(controller.feedback.boardTemp); + + // Errors + doc["ble"] = controller.feedback.left.error; + doc["bre"] = controller.feedback.right.error; + + // Speed + doc["bls"] = convertToKmh(controller.feedback.left.speed) * (controller.invertLeft?-1:1); + doc["brs"] = convertToKmh(controller.feedback.right.speed) * (controller.invertRight?-1:1); + } + else + { + return std::nullopt; + } + break; + } } - // Statistics - if(avgVoltage) + // if empty, return empty string + if (doc.isNull()) { - doc["bP"] = getBatteryPercentage(*avgVoltage, BatteryCellType(configs.battery.cellType.value())); - doc["bV"] = *avgVoltage; + return std::nullopt; } - doc["l"] = isLocked; - doc["mN"] = drivingStatistics.meters_driven; - doc["mT"] = drivingStatistics.totalMeters; - doc["dT"] = drivingStatistics.currentDrivingTime / 1ms; - doc["cW"] = watt; - doc["wN"] = drivingStatistics.wh_used; - doc["wL"] = getRemainingWattHours(); - doc["kmL"] = getRemainingWattHours() / configs.battery.watthoursPerKilometer.value(); - doc["ver"] = version_string.substr(0, 6); + doc["__t"] = configs.udpCloudSettings.udpToken.value(); + + std::string buf; serializeJson(doc, buf); return buf; } -// Same as buildUdpCloudJson, but doesnt use ArduinoJson (Probably will not expand; added for performance testing) -std::string buildUdpCloudString() -{ - static std::string version_string; - if (version_string.empty() || version_string == "-") - { - if (const esp_app_desc_t *app_desc = esp_ota_get_app_description()) - { - version_string = app_desc->version; - } - else - { - version_string = "-"; - } - } -// StaticJsonDocument<1024> doc; - std::string buf; - buf.reserve(1024); - - const auto uptime = espchrono::millis_clock::now().time_since_epoch() / 1ms; - - float watt{0}; - const auto avgVoltage = controllers.getAvgVoltage(); - if(avgVoltage) - watt = sumCurrent * *avgVoltage; - // const auto w_per_kmh = watt / avgSpeedKmh; - - buf += "{"; - - // User ID - if(configs.udpCloudSettings.udpUid.value()) - buf += fmt::format("\"uid\":{},", configs.udpCloudSettings.udpUid.value()); - else - buf += "\"uid\":null,"; - - if(uptime) - buf += fmt::format("\"upt\":{},", uptime); - else - buf += "\"uid\":null,"; - - const auto addController = [&](const Controller &controller, const bool isBack) { - if (controller.feedbackValid) - { - buf += fmt::format("\"{}\":{{", !isBack ? "f":"b"); - // Voltage - if (controller.getCalibratedVoltage()) - buf += fmt::format("\"V\":{},", controller.getCalibratedVoltage()); - else - buf += "\"V\":null,"; - - // Amperes - if (controller.feedback.left.dcLink) - buf += fmt::format("\"lA\":{},", fixCurrent(controller.feedback.left.dcLink)); - else - buf += "\"lA\":null,"; - - if (controller.feedback.right.dcLink) - buf += fmt::format("\"rA\":{},", fixCurrent(controller.feedback.right.dcLink)); - else - buf += "\"rA\":null,"; - - // Temperature - if (controller.feedback.right.dcLink) - buf += fmt::format("\"{}\":{},", !isBack ? "fT":"bT", fixBoardTemp(controller.feedback.boardTemp)); - else - buf += fmt::format("\"{}\":null,", !isBack ? "fT":"bT"); - - // Errors - if (controller.feedback.left.error) - buf += fmt::format("\"{}\":{},", !isBack ? "flE":"blE", controller.feedback.left.error); - else - buf += fmt::format("\"{}\":null,", !isBack ? "flE":"blE"); - - if (controller.feedback.right.error) - buf += fmt::format("\"{}\":{},", !isBack ? "frE":"brE", controller.feedback.right.error); - else - buf += fmt::format("\"{}\":null,", !isBack ? "frE":"brE"); - - - // Speed - if (controller.feedback.left.speed) - buf += fmt::format("\"{}\":{},", !isBack ? "flS":"blS", convertToKmh(controller.feedback.left.speed) * (controller.invertLeft?-1:1)); - else - buf += fmt::format("\"{}\":null,", !isBack ? "flS":"blS"); - - if (controller.feedback.right.speed) - buf += fmt::format("\"{}\":{},", !isBack ? "frS":"brS", convertToKmh(controller.feedback.right.speed) * (controller.invertRight?-1:1)); - else - buf += fmt::format("\"{}\":null,", !isBack ? "frS":"brS"); - - buf += "},"; - } - else - { - buf += fmt::format("\"{}\":null,", !isBack ? "f":"b"); - } - }; - - addController(controllers.front, false); - addController(controllers.back, true); - - // Potis - { - buf += "\"p\":{"; - if (gas) - buf += fmt::format("\"g\":{},",*gas); - else - buf += "\"g\":null,"; - - if (raw_gas) - buf += fmt::format("\"rg\":{},",*raw_gas); - else - buf += "\"rg\":null,"; - - if (brems) - buf += fmt::format("\"b\":{},",*brems); - else - buf += "\"b\":null,"; - - if (raw_brems) - buf += fmt::format("\"rb\":{},",*raw_brems); - else - buf += "\"rb\":null,"; - - buf += "},"; - } - - // Statistics - if(avgVoltage) - { - buf += fmt::format("\"bP\":{},", getBatteryPercentage(*avgVoltage, BatteryCellType(configs.battery.cellType.value()))); - buf += fmt::format("\"bV\":{},", *avgVoltage); - } - buf += fmt::format("\"l\":{},", isLocked); - buf += fmt::format("\"mN\":{},", drivingStatistics.meters_driven); - buf += fmt::format("\"mT\":{},", drivingStatistics.totalMeters); - buf += fmt::format("\"dT\":{},", drivingStatistics.currentDrivingTime / 1ms); - buf += fmt::format("\"cW\":{},", watt); - buf += fmt::format("\"wN\":{},", drivingStatistics.wh_used); - buf += fmt::format("\"wL\":{},", getRemainingWattHours()); - buf += fmt::format("\"kmL\":{},", getRemainingWattHours() / configs.battery.watthoursPerKilometer.value()); - buf += fmt::format("\"ver\":{}", version_string.substr(0, 6)); - - buf += "}"; - - return buf; -} - void sendUdpCloudPacket() { - EVERY_N_MILLIS(configs.boardcomputerHardware.timersSettings.udpSendRateMs.value()) { - if (espchrono::ago(timestampLastFailed) < 2s) - { - visualSendUdpPacket = false; - return; - } + if (espchrono::ago(timestampLastFailed) < 2s) + { + visualSendUdpPacket = false; + return; + } - if (configs.udpCloudHost.value().empty()) - { - visualSendUdpPacket = false; - return; - } + if (configs.udpCloudSettings.udpCloudHost.value().empty() || configs.udpCloudSettings.udpCloudPort.value() == 0) + { + visualSendUdpPacket = false; + return; + } - if (wifi_stack::get_sta_status() != wifi_stack::WiFiStaStatus::CONNECTED) - { - visualSendUdpPacket = false; - return; - } + if (wifi_stack::get_sta_status() != wifi_stack::WiFiStaStatus::CONNECTED) + { + visualSendUdpPacket = false; + return; + } + + if(espchrono::ago(lastSend) / 1ms > configs.boardcomputerHardware.timersSettings.udpSendRateMs.value()) + { + lastSend = espchrono::millis_clock::now(); ip_addr_t udpCloudIp; - if (const auto res = dns_gethostbyname(configs.udpCloudHost.value().c_str(), &udpCloudIp, nullptr, nullptr); res != ERR_OK) + if (const auto res = dns_gethostbyname(configs.udpCloudSettings.udpCloudHost.value().c_str(), &udpCloudIp, nullptr, nullptr); res != ERR_OK) { - if (res == ERR_INPROGRESS) - { - ESP_LOGD(TAG, "dns_gethostbyname() failed because: %i", res); - } - else - { - ESP_LOGE(TAG, "dns_gethostbyname() failed because: %i", res); - } + ESP_LOGE(TAG, "dns_gethostbyname() failed because: (%s) (%i)", lwip_strerr(res), res); timestampLastFailed = espchrono::millis_clock::now(); visualSendUdpPacket = false; return; @@ -355,14 +206,21 @@ void sendUdpCloudPacket() } sockaddr_in receipient; - receipient.sin_port = htons(24242); + receipient.sin_port = htons(configs.udpCloudSettings.udpCloudPort.value()); receipient.sin_addr.s_addr = udpCloudIp.u_addr.ip4.addr; receipient.sin_family = AF_INET; wifi_stack::UdpSender udpCloudSender; std::string buf; - buf = configs.udpCloudSettings.udpUseStdString.value() ? buildUdpCloudString() : buildUdpCloudJson(); + if (const auto json = buildUdpCloudJson(); !json) + { + return; + } + else + { + buf = *json; + } if (const auto result = udpCloudSender.send(receipient, buf); !result) { @@ -370,7 +228,8 @@ void sendUdpCloudPacket() ESP_LOGE(TAG, "send to cloud failed: %.*s (ip=%s)", result.error().size(), result.error().data(), wifi_stack::toString(udpCloudIp.u_addr.ip4).c_str()); } - ESP_LOGD(TAG, "now: %s", buf.c_str()); + // ESP_LOGI(TAG, "%s", buf.c_str()); + visualSendUdpPacket = !visualSendUdpPacket; - } + } } diff --git a/main/udpcloud.h b/main/udpcloud.h index 71976ee..e4f8791 100644 --- a/main/udpcloud.h +++ b/main/udpcloud.h @@ -1,6 +1,7 @@ #pragma once // system includes +#include #include // Little "flash" on statusdisplay when udp stuff is happening @@ -9,7 +10,5 @@ extern bool visualSendUdpPacket; void udpCloudInit(); void udpCloudUpdate(); -void spamUdpBroadcast(); -std::string buildUdpCloudJson(); -std::string buildUdpCloudString(); +std::optional buildUdpCloudJson(); void sendUdpCloudPacket();