diff --git a/main/accessors/settingsaccessors.h b/main/accessors/settingsaccessors.h index bc59c07..315d8ed 100644 --- a/main/accessors/settingsaccessors.h +++ b/main/accessors/settingsaccessors.h @@ -121,6 +121,7 @@ struct DisplayRedrawRateAccessor : public RefAccessorSaveSettings { int struct CanReceiveRateAccessor : public RefAccessorSaveSettings { int16_t &getRef() const override { return settings.boardcomputerHardware.timersSettings.canReceiveRate; } }; #endif #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; } }; #endif diff --git a/main/cloud.h b/main/cloud.h index 1b97bc7..0a423da 100644 --- a/main/cloud.h +++ b/main/cloud.h @@ -1,5 +1,5 @@ #pragma once -#define FEATURE_CLOUD + // esp-idf includes #include @@ -19,6 +19,7 @@ espcpputils::websocket_client cloudClient; bool cloudStarted{}; espchrono::millis_clock::time_point lastCreateTry; espchrono::millis_clock::time_point lastStartTry; +std::string cloudBuffer; void createCloud(); void destroyCloud(); @@ -41,7 +42,99 @@ void initCloud() } } -void handleCloud() +void cloudCollect() +{ + if (!cloudClient) + { + cloudBuffer.clear(); + return; + } + + if (!cloudStarted) + { + cloudBuffer.clear(); + return; + } + + if (!cloudClient.is_connected()) + { + cloudBuffer.clear(); + return; + } + + if (cloudBuffer.empty()) + cloudBuffer = '['; + else + cloudBuffer += ','; + + cloudBuffer += fmt::format("[{},{},{}", + std::chrono::milliseconds{espchrono::millis_clock::now().time_since_epoch()}.count(), + std::chrono::milliseconds{espchrono::utc_clock::now().time_since_epoch()}.count(), + heap_caps_get_free_size(MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT)); + if (wifi_stack::get_sta_status() == wifi_stack::WiFiStaStatus::CONNECTED) + { + if (const auto &result = wifi_stack::get_sta_ap_info(); result) + cloudBuffer += fmt::format(",{}", result->rssi); + else + cloudBuffer += ",null"; + } + else + cloudBuffer += ",null"; + + if (raw_gas) + cloudBuffer += fmt::format(",{}", *raw_gas); + else + cloudBuffer += ",null"; + + if (raw_brems) + cloudBuffer += fmt::format(",{}", *raw_brems); + else + cloudBuffer += ",null"; + + if (gas) + cloudBuffer += fmt::format(",{:.1f}", *gas); + else + cloudBuffer += ",null"; + + if (brems) + cloudBuffer += fmt::format(",{:.1f}", *brems); + else + cloudBuffer += ",null"; + + constexpr const auto addController = [](const Controller &controller){ + if (!controller.feedbackValid) + { + cloudBuffer += ",null"; + return; + } + + cloudBuffer += fmt::format(",[{:.02f},{:.02f}", + fixBatVoltage(controller.feedback.batVoltage), + fixBoardTemp(controller.feedback.boardTemp)); + + constexpr const auto addMotor = [](const bobbycar::protocol::serial::MotorState &command, + const bobbycar::protocol::serial::MotorFeedback &feedback, + bool invert){ + cloudBuffer += fmt::format(",[{},{:.2f},{:.2f},{}]", + command.pwm * (invert?-1:1), + convertToKmh(feedback.speed) * (invert?-1:1), + fixCurrent(feedback.dcLink), + feedback.error); + }; + + addMotor(controller.command.left, controller.feedback.left, controller.invertLeft); + addMotor(controller.command.right, controller.feedback.right, controller.invertRight); + + cloudBuffer += ']'; + }; + + addController(controllers.front); + addController(controllers.back); + + cloudBuffer += "]"; +} + +void cloudSend() { if (settings.cloudSettings.cloudEnabled && !stringSettings.cloudUrl.empty() && @@ -72,84 +165,24 @@ void handleCloud() if (!cloudClient.is_connected()) return; - static std::string msg; - msg = fmt::format("[[{},{},{}", - std::chrono::milliseconds{espchrono::millis_clock::now().time_since_epoch()}.count(), - std::chrono::milliseconds{espchrono::utc_clock::now().time_since_epoch()}.count(), - heap_caps_get_free_size(MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT)); - if (wifi_stack::get_sta_status() == wifi_stack::WiFiStaStatus::CONNECTED) - { - if (const auto &result = wifi_stack::get_sta_ap_info(); result) - msg += fmt::format(",{}", result->rssi); - else - msg += ",null"; - } - else - msg += ",null"; + if (cloudBuffer.empty()) + return; - if (raw_gas) - msg += fmt::format(",{}", *raw_gas); - else - msg += ",null"; - - if (raw_brems) - msg += fmt::format(",{}", *raw_brems); - else - msg += ",null"; - - if (gas) - msg += fmt::format(",{:.1f}", *gas); - else - msg += ",null"; - - if (brems) - msg += fmt::format(",{:.1f}", *brems); - else - msg += ",null"; - - constexpr const auto addController = [](const Controller &controller){ - if (!controller.feedbackValid) - { - msg += ",null"; - return; - } - - msg += fmt::format(",[{:.02f},{:.02f}", - fixBatVoltage(controller.feedback.batVoltage), - fixBoardTemp(controller.feedback.boardTemp)); - - constexpr const auto addMotor = [](const bobbycar::protocol::serial::MotorState &command, - const bobbycar::protocol::serial::MotorFeedback &feedback, - bool invert){ - msg += fmt::format(",[{},{:.2f},{:.2f},{}]", - command.pwm * (invert?-1:1), - convertToKmh(feedback.speed) * (invert?-1:1), - fixCurrent(feedback.dcLink), - feedback.error); - }; - - addMotor(controller.command.left, controller.feedback.left, controller.invertLeft); - addMotor(controller.command.right, controller.feedback.right, controller.invertRight); - - msg += ']'; - }; - - addController(controllers.front); - addController(controllers.back); - - msg += "]]"; + cloudBuffer += ']'; const auto timeout = std::chrono::ceil(espchrono::milliseconds32{settings.cloudSettings.cloudTransmitTimeout}).count(); - const auto written = cloudClient.send_text(msg, timeout); + const auto written = cloudClient.send_text(cloudBuffer, timeout); if (written < 0) { ESP_LOGE("BOBBY", "cloudClient.send_text() failed with %i", written); } - else if (written != msg.size()) + else if (written != cloudBuffer.size()) { - ESP_LOGE("BOBBY", "websocket sent size mismatch, sent=%i, expected=%i", written, msg.size()); + ESP_LOGE("BOBBY", "websocket sent size mismatch, sent=%i, expected=%i", written, cloudBuffer.size()); } + + cloudBuffer.clear(); } else if (cloudClient) { diff --git a/main/displays/menus/cloudsettingsmenu.h b/main/displays/menus/cloudsettingsmenu.h index 3a0371e..348be8c 100644 --- a/main/displays/menus/cloudsettingsmenu.h +++ b/main/displays/menus/cloudsettingsmenu.h @@ -1,5 +1,8 @@ #pragma once +// 3rdparty lib includes +#include + // local includes #include "menudisplay.h" #include "menuitem.h" @@ -11,6 +14,8 @@ #include "accessors/settingsaccessors.h" #include "icons/back.h" #include "texts.h" +#include "accessors/settingsaccessors.h" +#include "cloud.h" // forward declares namespace { @@ -26,6 +31,30 @@ using CloudTransmitTimeoutChangeScreen = makeComponent< BackActionInterface>, SwitchScreenAction >; + +struct CloudBufferLengthText : public virtual TextInterface { +public: + std::string text() const override + { + return fmt::format("buffer: {}", cloudBuffer.size()); + } +}; + +using CloudCollectRateChangeDisplay = makeComponent< + ChangeValueDisplay, + StaticText, + CloudCollectRateAccessor, + BackActionInterface>, + SwitchScreenAction +>; + +using CloudSendRateChangeDisplay = makeComponent< + ChangeValueDisplay, + StaticText, + CloudSendRateAccessor, + BackActionInterface>, + SwitchScreenAction +>; } // namespace namespace { @@ -43,6 +72,9 @@ public: constructMenuItem>(); constructMenuItem>(); constructMenuItem>(); + constructMenuItem>(); + constructMenuItem, SwitchScreenAction>>(); + constructMenuItem, SwitchScreenAction>>(); constructMenuItem, SwitchScreenAction, StaticMenuItemIcon<&espgui::icons::back>>>(); } }; diff --git a/main/displays/menus/timersmenu.h b/main/displays/menus/timersmenu.h index c58a51a..1ecc470 100644 --- a/main/displays/menus/timersmenu.h +++ b/main/displays/menus/timersmenu.h @@ -69,16 +69,6 @@ using CanReceiveRateChangeDisplay = makeComponent< >; #endif -#ifdef FEATURE_CLOUD -using CloudSendRateChangeDisplay = makeComponent< - ChangeValueDisplay, - StaticText, - CloudSendRateAccessor, - BackActionInterface>, - SwitchScreenAction ->; -#endif - class TimersMenu : public MenuDisplay, public StaticText, @@ -94,9 +84,6 @@ public: constructMenuItem, SwitchScreenAction>>(); #ifdef FEATURE_CAN constructMenuItem, SwitchScreenAction>>(); -#endif -#ifdef FEATURE_CLOUD - constructMenuItem, SwitchScreenAction>>(); #endif constructMenuItem, SwitchScreenAction, StaticMenuItemIcon<&espgui::icons::back>>>(); } diff --git a/main/main.cpp b/main/main.cpp index 745aa63..ce6c348 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -162,7 +162,8 @@ std::optional lastCanParse; std::optional lastBleUpdate; #endif #ifdef FEATURE_CLOUD -std::optional lastCloudUpdate; +std::optional lastCloudCollect; +std::optional lastCloudSend; #endif #ifdef FEATURE_NTP std::optional lastNtpUpdate; @@ -459,11 +460,18 @@ extern "C" void app_main() #endif #ifdef FEATURE_CLOUD - if (!lastCloudUpdate || now - *lastCloudUpdate >= 1000ms/settings.boardcomputerHardware.timersSettings.cloudSendRate) + if (!lastCloudCollect || now - *lastCloudCollect >= std::chrono::milliseconds{settings.boardcomputerHardware.timersSettings.cloudCollectRate}) { - handleCloud(); + cloudCollect(); - lastCloudUpdate = now; + lastCloudCollect = now; + } + + if (!lastCloudSend || now - *lastCloudSend >= 1000ms/settings.boardcomputerHardware.timersSettings.cloudSendRate) + { + cloudSend(); + + lastCloudSend = now; } #endif diff --git a/main/presets.h b/main/presets.h index 90d6a96..d966ced 100644 --- a/main/presets.h +++ b/main/presets.h @@ -142,6 +142,7 @@ constexpr Settings::BoardcomputerHardware::TimersSettings defaultTimersSettings .canReceiveRate = 100, #endif #ifdef FEATURE_CLOUD + .cloudCollectRate = 100, .cloudSendRate = 1, #endif }; diff --git a/main/settings.h b/main/settings.h index aef1fe2..49b66c4 100644 --- a/main/settings.h +++ b/main/settings.h @@ -110,6 +110,7 @@ struct Settings int16_t canReceiveRate; #endif #ifdef FEATURE_CLOUD + int16_t cloudCollectRate; int16_t cloudSendRate; #endif } timersSettings; @@ -237,6 +238,7 @@ void Settings::executeForEveryCommonSetting(T &&callable) callable("canReceiveRate", boardcomputerHardware.timersSettings.canReceiveRate); #endif #ifdef FEATURE_CLOUD + callable("cloudCollectRat", boardcomputerHardware.timersSettings.cloudCollectRate); callable("cloudSendRate", boardcomputerHardware.timersSettings.cloudSendRate); #endif diff --git a/main/texts.h b/main/texts.h index ca25734..fe86b2f 100644 --- a/main/texts.h +++ b/main/texts.h @@ -45,6 +45,8 @@ constexpr char TEXT_BLEENABLED[] = "BLE enabled"; constexpr char TEXT_CLOUDSETTINGS[] = "Cloud settings"; constexpr char TEXT_CLOUDENABLED[] = "Cloud enabled"; constexpr char TEXT_CLOUDTRANSMITTIMEOUT[] = "Transmit timeout"; +constexpr char TEXT_CLOUDCOLLECTRATE[] = "Cloud collect rate"; +constexpr char TEXT_CLOUDSENDRATE[] = "Cloud send rate"; //constexpr char TEXT_BACK[] = "Back"; #endif @@ -344,9 +346,6 @@ constexpr char TEXT_DISPLAYREDRAWRATE[] = "Display redraw rate"; #ifdef FEATURE_CAN constexpr char TEXT_CANRECEIVERATE[] = "CAN receive rate"; #endif -#ifdef FEATURE_CLOUD -constexpr char TEXT_CLOUDSENDRATE[] = "Cloud send rate"; -#endif //constexpr char TEXT_BACK[] = "Back"; //TimeSettingsMenu