Files
bobbycar-boardcomputer-firm…/main/cloud.h
T
2021-08-10 05:03:50 +02:00

191 lines
6.1 KiB
C++

#pragma once
// esp-idf includes
#include <esp_log.h>
// 3rdparty lib includes
#include <wrappers/websocket_client.h>
#include <espwifistack.h>
// local includes
#include "globals.h"
namespace {
#ifdef FEATURE_CLOUD
espcpputils::websocket_client cloudClient;
bool cloudStarted{};
espchrono::millis_clock::time_point lastCreateTry;
espchrono::millis_clock::time_point lastStartTry;
void createCloud();
void destroyCloud();
void startCloud();
void initCloud()
{
if (settings.cloudSettings.cloudEnabled)
{
createCloud();
if (!cloudClient)
return;
if (wifi_stack::get_sta_status() != wifi_stack::WiFiStaStatus::WL_CONNECTED)
return;
startCloud();
}
}
void handleCloud()
{
if (settings.cloudSettings.cloudEnabled)
{
if (!cloudClient)
{
if (espchrono::ago(lastCreateTry) < 10s)
return;
createCloud();
}
if (!cloudClient)
return;
if (!cloudStarted)
{
if (espchrono::ago(lastStartTry) < 10s)
return;
if (wifi_stack::get_sta_status() != wifi_stack::WiFiStaStatus::WL_CONNECTED)
return;
startCloud();
}
if (!cloudStarted)
return;
if (!cloudClient.is_connected())
return;
std::string rssi = "null";
if (wifi_stack::get_sta_status() == wifi_stack::WiFiStaStatus::WL_CONNECTED)
if (const auto &result = wifi_stack::get_sta_ap_info(); result)
rssi = std::to_string(result->rssi);
std::string msg = "{"
"\"type\": \"fullStatus\","
"\"partial\": false, "
"\"status\": {"
"\"millis\":" + std::to_string(std::chrono::milliseconds{espchrono::millis_clock::now().time_since_epoch()}.count()) + ","
"\"rssi\":" + rssi + ","
"\"front.valid\":" + std::to_string(controllers.front.feedbackValid) + ","
"\"back.valid\":" + std::to_string(controllers.back.feedbackValid) + ","
"\"front.left.pwm\":" + std::to_string(controllers.front.command.left.pwm) + ","
"\"front.right.pwm\":" + std::to_string(controllers.front.command.right.pwm) + ","
"\"back.left.pwm\":" + std::to_string(controllers.back.command.left.pwm) + ","
"\"back.right.pwm\":" + std::to_string(controllers.back.command.right.pwm) + ","
"\"front.volt\":" + std::to_string(controllers.front.feedback.batVoltage) + ","
"\"back.volt\":" + std::to_string(controllers.back.feedback.batVoltage) + ","
"\"front.temp\":" + std::to_string(controllers.front.feedback.boardTemp) + ","
"\"back.temp\":" + std::to_string(controllers.back.feedback.boardTemp) + ","
"\"front.bad\":" + std::to_string(controllers.front.feedback.timeoutCntSerial) + ","
"\"back.bad\":" + std::to_string(controllers.back.feedback.timeoutCntSerial) + ","
"\"front.left.speed\":" + std::to_string(controllers.front.feedback.left.speed) + ","
"\"front.right.speed\":" + std::to_string(controllers.front.feedback.right.speed) + ","
"\"back.left.speed\":" + std::to_string(controllers.back.feedback.left.speed) + ","
"\"back.right.speed\":" + std::to_string(controllers.back.feedback.right.speed) + ","
"\"front.left.current\":" + std::to_string(controllers.front.feedback.left.dcLink) + ","
"\"front.right.current\":" + std::to_string(controllers.front.feedback.right.dcLink) + ","
"\"back.left.current\":" + std::to_string(controllers.back.feedback.left.dcLink) + ","
"\"back.right.current\":" + std::to_string(controllers.back.feedback.right.dcLink) + ","
"\"front.left.error\":" + std::to_string(controllers.front.feedback.left.error) + ","
"\"front.right.error\":" + std::to_string(controllers.front.feedback.right.error) + ","
"\"back.left.error\":" + std::to_string(controllers.back.feedback.left.error) + ","
"\"back.right.error\":" + std::to_string(controllers.back.feedback.right.error) +
"}"
"}";
const auto timeout = std::chrono::ceil<espcpputils::ticks>(espchrono::milliseconds32{settings.cloudSettings.cloudTransmitTimeout}).count();
const auto written = cloudClient.send_text(msg, timeout);
if (written < 0)
{
ESP_LOGE("BOBBY", "cloudClient.send_text() failed with %i", written);
}
else if (written != msg.size())
{
ESP_LOGE("BOBBY", "websocket sent size mismatch, sent=%i, expected=%i", written, msg.size());
}
}
else if (cloudClient)
{
destroyCloud();
}
}
void createCloud()
{
ESP_LOGI("BOBBY", "called");
if (cloudClient)
{
ESP_LOGE(TAG, "cloud client already created");
return;
}
lastCreateTry = espchrono::millis_clock::now();
const esp_websocket_client_config_t config = {
.uri = stringSettings.cloudUrl.c_str(),
};
cloudClient = espcpputils::websocket_client{&config};
if (!cloudClient)
{
ESP_LOGE(TAG, "websocket could not be constructed");
return;
}
ESP_LOGI("BOBBY", "cloud client created");
}
void startCloud()
{
ESP_LOGI("BOBBY", "called");
if (!cloudClient)
{
ESP_LOGE(TAG, "cloud client not created");
return;
}
if (cloudStarted)
{
ESP_LOGE(TAG, "cloud client already started");
return;
}
lastStartTry = espchrono::millis_clock::now();
const auto result = cloudClient.start();
ESP_LOG_LEVEL_LOCAL((result == ESP_OK ? ESP_LOG_INFO : ESP_LOG_ERROR), "BOBBY", "cloudClient.start() returned: %s", esp_err_to_name(result));
if (result == ESP_OK)
cloudStarted = true;
}
void destroyCloud()
{
ESP_LOGI("BOBBY", "called");
if (!cloudClient)
{
ESP_LOGE(TAG, "cloud client not created");
return;
}
cloudClient = {};
cloudStarted = false;
}
#endif
} // namespace