Files

249 lines
7.0 KiB
C++
Raw Permalink Normal View History

#include "udpcloud.h"
2021-11-21 01:37:51 +01:00
// system includes
#include <esp_log.h>
#include <esp_ota_ops.h>
#include <lwip/dns.h>
2021-11-21 01:37:51 +01:00
// 3rd party includes
#include <ArduinoJson.h>
#include <FastLED.h>
#include <espchrono.h>
2021-12-11 22:28:19 +01:00
#include <espwifistack.h>
#include <fmt/format.h>
2021-11-21 01:37:51 +01:00
// local includes
#include "battery.h"
#include "drivingstatistics.h"
#include "globals.h"
2021-12-29 05:51:49 +01:00
#include "newsettings.h"
2022-10-30 02:47:13 +01:00
#include "taskmanager.h"
#include "udpsender.h"
#include "utils.h"
2021-11-21 01:37:51 +01:00
using namespace std::chrono_literals;
namespace {
constexpr const char * const TAG = "bobbycloud";
espchrono::millis_clock::time_point timestampLastFailed;
2022-10-05 13:00:35 +02:00
espchrono::millis_clock::time_point lastSend;
2022-10-06 10:43:03 +02:00
espchrono::millis_clock::time_point lastDNSQuery;
uint8_t packageType{0}; // cycle through packages.
2022-10-06 10:43:03 +02:00
std::optional<sockaddr_in> receipient;
ip_addr_t udpCloudIp;
} // namespace
// Little "flash" on statusdisplay when udp stuff is happening
bool visualSendUdpPacket;
void udpCloudInit()
{
}
void udpCloudUpdate()
{
2022-04-29 22:40:49 +02:00
if (!configs.feature.udpcloud.isEnabled.value())
return;
if (configs.udpCloudSettings.udpCloudEnabled.value() && configs.udpCloudSettings.udpToken.touched())
sendUdpCloudPacket();
}
2021-11-21 01:37:51 +01:00
std::optional<std::string> buildUdpCloudJson()
2021-11-21 01:37:51 +01:00
{
StaticJsonDocument<512> doc;
switch (++packageType)
2021-11-26 18:27:44 +01:00
{
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;
}
case 1:
2022-10-06 10:43:03 +02:00
case 4:
{
if (const auto avgVoltage = controllers.getAvgVoltage(); avgVoltage)
2021-11-26 18:27:44 +01:00
{
doc["bap"] = getBatteryPercentage(*avgVoltage, BatteryCellType(configs.battery.cellType.value()));
doc["bav"] = *avgVoltage; // battery voltage
doc["pwr"] = sumCurrent * *avgVoltage; // total watt
2021-11-26 18:27:44 +01:00
}
doc["whl"] = getRemainingWattHours(); // watt hours left
doc["kml"] = getRemainingWattHours() / configs.battery.watthoursPerKilometer.value(); // calculated kilometers left
doc["ekm"] = getEstimatedKmLeft(); // kilometers left live calculation
break;
2021-11-26 18:27:44 +01:00
}
case 2:
2022-10-06 10:43:03 +02:00
case 5:
{
const auto &controller = controllers.front;
if (controller.feedbackValid)
{
doc["fbv"] = controller.getCalibratedVoltage();
2021-11-21 01:37:51 +01:00
// Amperes
doc["fla"] = fixCurrent(controller.feedback.left.dcLink);
doc["fra"] = fixCurrent(controller.feedback.right.dcLink);
2021-11-21 01:37:51 +01:00
// Temperature
doc["fbt"] = fixBoardTemp(controller.feedback.boardTemp);
2021-11-21 01:37:51 +01:00
// Errors
doc["fle"] = controller.feedback.left.error;
doc["fre"] = controller.feedback.right.error;
2021-11-21 01:37:51 +01:00
// Speed
doc["fls"] = convertToKmh(controller.feedback.left.speed) * (controller.invertLeft?-1:1);
doc["frs"] = convertToKmh(controller.feedback.right.speed) * (controller.invertRight?-1:1);
}
else
{
return std::nullopt;
}
break;
}
case 3:
2022-10-06 10:43:03 +02:00
case 6:
{
const auto &controller = controllers.back;
2021-11-21 01:37:51 +01:00
if (controller.feedbackValid)
{
doc["bbv"] = controller.getCalibratedVoltage();
2021-11-21 01:37:51 +01:00
// Amperes
doc["bla"] = fixCurrent(controller.feedback.left.dcLink);
doc["bra"] = fixCurrent(controller.feedback.right.dcLink);
2021-11-21 01:37:51 +01:00
// Temperature
doc["bbt"] = fixBoardTemp(controller.feedback.boardTemp);
2021-11-21 01:37:51 +01:00
// Errors
doc["ble"] = controller.feedback.left.error;
doc["bre"] = controller.feedback.right.error;
2021-11-21 01:37:51 +01:00
// Speed
doc["bls"] = convertToKmh(controller.feedback.left.speed) * (controller.invertLeft?-1:1);
doc["brs"] = convertToKmh(controller.feedback.right.speed) * (controller.invertRight?-1:1);
2021-11-21 01:37:51 +01:00
}
2021-11-26 18:27:44 +01:00
else
{
return std::nullopt;
2021-11-26 18:27:44 +01:00
}
break;
}
2021-11-21 01:37:51 +01:00
}
// if empty, return empty string
if (doc.isNull())
2022-01-27 01:09:52 +01:00
{
return std::nullopt;
2022-01-27 01:09:52 +01:00
}
2021-11-21 01:37:51 +01:00
doc["__t"] = configs.udpCloudSettings.udpToken.value();
2022-10-30 02:47:13 +01:00
doc["per"] = drivingModeTask.callCount();
std::string buf;
2021-11-21 01:37:51 +01:00
serializeJson(doc, buf);
return buf;
}
2022-10-05 13:00:35 +02:00
void sendUdpCloudPacket()
2021-11-26 18:27:44 +01:00
{
2022-10-05 13:00:35 +02:00
if (espchrono::ago(timestampLastFailed) < 2s)
2021-11-26 18:27:44 +01:00
{
2022-10-05 13:00:35 +02:00
visualSendUdpPacket = false;
return;
2021-11-26 18:27:44 +01:00
}
if (configs.udpCloudSettings.udpCloudHost.value().empty() || configs.udpCloudSettings.udpCloudPort.value() == 0)
2021-11-26 18:27:44 +01:00
{
2022-10-05 13:00:35 +02:00
visualSendUdpPacket = false;
return;
2021-11-26 18:27:44 +01:00
}
2022-10-05 13:00:35 +02:00
if (wifi_stack::get_sta_status() != wifi_stack::WiFiStaStatus::CONNECTED)
2022-01-27 01:09:52 +01:00
{
2022-10-05 13:00:35 +02:00
visualSendUdpPacket = false;
return;
2022-01-27 01:09:52 +01:00
}
2021-11-21 01:37:51 +01:00
2022-10-06 10:43:03 +02:00
if (espchrono::ago(lastDNSQuery) > 10s || !receipient.has_value())
2022-10-05 13:00:35 +02:00
{
2022-10-06 10:43:03 +02:00
lastDNSQuery = espchrono::millis_clock::now();
receipient = sockaddr_in{};
if (const auto res = dns_gethostbyname(configs.udpCloudSettings.udpCloudHost.value().c_str(), &udpCloudIp, nullptr, nullptr); res != ERR_OK)
2021-11-21 01:37:51 +01:00
{
ESP_LOGE(TAG, "dns_gethostbyname() failed because: (%s) (%i)", lwip_strerr(res), res);
2021-11-21 01:37:51 +01:00
timestampLastFailed = espchrono::millis_clock::now();
visualSendUdpPacket = false;
2021-11-21 01:37:51 +01:00
return;
}
if (udpCloudIp.type != IPADDR_TYPE_V4)
{
ESP_LOGE(TAG, "unsupported ip type: %hhu", udpCloudIp.type);
2021-12-13 20:24:49 +01:00
timestampLastFailed = espchrono::millis_clock::now();
visualSendUdpPacket = false;
2021-11-21 01:37:51 +01:00
return;
}
2022-10-06 10:43:03 +02:00
(*receipient).sin_port = htons(configs.udpCloudSettings.udpCloudPort.value());
(*receipient).sin_addr.s_addr = udpCloudIp.u_addr.ip4.addr;
(*receipient).sin_family = AF_INET;
}
if(espchrono::ago(lastSend) / 1ms > configs.boardcomputerHardware.timersSettings.udpSendRateMs.value())
{
lastSend = espchrono::millis_clock::now();
if (!receipient)
{
return;
}
2021-11-21 01:37:51 +01:00
wifi_stack::UdpSender udpCloudSender;
std::string buf;
if (const auto json = buildUdpCloudJson(); !json)
{
return;
}
else
{
buf = *json;
}
2021-11-21 01:37:51 +01:00
2022-10-06 10:43:03 +02:00
if (const auto result = udpCloudSender.send(*receipient, buf); !result)
2021-11-21 01:37:51 +01:00
{
2021-12-13 20:24:49 +01:00
timestampLastFailed = espchrono::millis_clock::now();
2021-12-11 22:28:19 +01:00
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());
2021-11-21 01:37:51 +01:00
}
2022-10-06 22:37:31 +02:00
visualSendUdpPacket = !visualSendUdpPacket;
2022-10-05 13:00:35 +02:00
}
2021-11-21 01:37:51 +01:00
}