Added udp cloud
This commit is contained in:
@ -49,6 +49,7 @@ set(headers
|
||||
texts.h
|
||||
time_bobbycar.h
|
||||
types.h
|
||||
udpcloud.h
|
||||
unifiedmodelmode.h
|
||||
utils.h
|
||||
webserver_displaycontrol.h
|
||||
@ -239,6 +240,7 @@ set(sources
|
||||
texts.cpp
|
||||
time_bobbycar.cpp
|
||||
types.cpp
|
||||
udpcloud.cpp
|
||||
unifiedmodelmode.cpp
|
||||
utils.cpp
|
||||
webserver.cpp
|
||||
|
@ -22,6 +22,7 @@ void Lockscreen::start()
|
||||
currentMode = &m_mode;
|
||||
|
||||
profileButtonDisabled = !settings.lockscreen.allowPresetSwitch;
|
||||
isLocked = true;
|
||||
}
|
||||
|
||||
void Lockscreen::initScreen()
|
||||
@ -122,6 +123,7 @@ void Lockscreen::stop()
|
||||
}
|
||||
|
||||
profileButtonDisabled = false;
|
||||
isLocked = false;
|
||||
}
|
||||
|
||||
void Lockscreen::confirm()
|
||||
|
@ -14,6 +14,7 @@ float gametrakDist;
|
||||
float avgSpeed{};
|
||||
float avgSpeedKmh{};
|
||||
float sumCurrent{};
|
||||
bool isLocked{};
|
||||
|
||||
char deviceName[32] = STRING(DEVICE_PREFIX) "_ERR";
|
||||
|
||||
|
@ -43,6 +43,7 @@ extern float avgSpeedKmh;
|
||||
extern float sumCurrent;
|
||||
|
||||
extern char deviceName[32];
|
||||
extern bool isLocked;
|
||||
|
||||
#ifdef GLOBALS_PLUGIN
|
||||
#include GLOBALS_PLUGIN
|
||||
|
@ -62,6 +62,7 @@ using namespace std::chrono_literals;
|
||||
#endif
|
||||
#ifdef FEATURE_CLOUD
|
||||
#include "cloud.h"
|
||||
#include "udpcloud.h"
|
||||
#endif
|
||||
#include "wifi_bobbycar.h"
|
||||
#include "time_bobbycar.h"
|
||||
@ -447,5 +448,6 @@ extern "C" void app_main()
|
||||
handle_dns_announce();
|
||||
#endif
|
||||
calculateStatistics();
|
||||
sendUdpCloudPacket();
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ StringSettings makeDefaultStringSettings()
|
||||
},
|
||||
#ifdef FEATURE_CLOUD
|
||||
.cloudUrl = {},
|
||||
.udpCloudUrl = {},
|
||||
#endif
|
||||
#ifdef FEATURE_OTA
|
||||
.otaUrl = {},
|
||||
|
@ -173,7 +173,8 @@ constexpr Settings::BoardcomputerHardware defaultBoardcomputerHardware {
|
||||
#ifdef FEATURE_CLOUD
|
||||
constexpr Settings::CloudSettings defaultCloudSettings {
|
||||
.cloudEnabled = false,
|
||||
.cloudTransmitTimeout = 10
|
||||
.cloudTransmitTimeout = 10,
|
||||
.udpUid = 0,
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -121,6 +121,7 @@ struct Settings
|
||||
struct CloudSettings {
|
||||
bool cloudEnabled;
|
||||
int16_t cloudTransmitTimeout; // in ms
|
||||
uint32_t udpUid;
|
||||
} cloudSettings;
|
||||
#endif
|
||||
|
||||
@ -286,6 +287,7 @@ void Settings::executeForEveryCommonSetting(T &&callable)
|
||||
#ifdef FEATURE_CLOUD
|
||||
callable("cloudEnabled", cloudSettings.cloudEnabled);
|
||||
callable("clodTransmTmout", cloudSettings.cloudTransmitTimeout);
|
||||
callable("cloudUDPUid", cloudSettings.udpUid);
|
||||
#endif
|
||||
|
||||
#ifdef FEATURE_LEDSTRIP
|
||||
|
@ -15,6 +15,7 @@ struct StringSettings
|
||||
|
||||
#ifdef FEATURE_CLOUD
|
||||
std::string cloudUrl;
|
||||
std::string udpCloudUrl;
|
||||
#endif
|
||||
|
||||
#ifdef FEATURE_OTA
|
||||
@ -75,6 +76,7 @@ void StringSettings::executeForEveryCommonSetting(T &&callable)
|
||||
|
||||
#ifdef FEATURE_CLOUD
|
||||
callable("cloudUrl", cloudUrl);
|
||||
callable("udpUrl", udpCloudUrl);
|
||||
#endif
|
||||
|
||||
#ifdef FEATURE_OTA
|
||||
|
176
main/udpcloud.cpp
Normal file
176
main/udpcloud.cpp
Normal file
@ -0,0 +1,176 @@
|
||||
constexpr const char * const TAG = "bobbycloud";
|
||||
|
||||
// 3rd party includes
|
||||
#include <ArduinoJson.h>
|
||||
#include <FastLED.h>
|
||||
|
||||
// local includes
|
||||
#include "udpcloud.h"
|
||||
#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"
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
espchrono::millis_clock::time_point timestampLastFailed;
|
||||
|
||||
void spamUdpBroadcast()
|
||||
{
|
||||
wifi_stack::UdpSender sender;
|
||||
|
||||
if (!sender.ready())
|
||||
{
|
||||
ESP_LOGE(TAG, "could not init udp sender!");
|
||||
return;
|
||||
}
|
||||
|
||||
std::string buf;
|
||||
const auto uptime = espchrono::millis_clock::now().time_since_epoch().count();
|
||||
|
||||
buf = fmt::format("uptime: {}", uptime);
|
||||
|
||||
if (const auto result = sender.send(ESP_IF_WIFI_STA, 187, buf); !result)
|
||||
{
|
||||
ESP_LOGE(TAG, "broadcast failed");
|
||||
}
|
||||
}
|
||||
|
||||
std::string buildUdpCloudJson()
|
||||
{
|
||||
StaticJsonDocument<1024> doc;
|
||||
std::string buf;
|
||||
const auto uptime = espchrono::millis_clock::now().time_since_epoch().count();
|
||||
|
||||
float avgVoltage = 0;
|
||||
for (auto &controller : controllers)
|
||||
{
|
||||
avgVoltage += controller.getCalibratedVoltage();
|
||||
}
|
||||
avgVoltage = avgVoltage / controllers.size();
|
||||
|
||||
const auto watt = sumCurrent * avgVoltage;
|
||||
// const auto w_per_kmh = watt / avgSpeedKmh;
|
||||
|
||||
// User ID
|
||||
doc["uid"] = settings.cloudSettings.udpUid;
|
||||
doc["upt"] = uptime;
|
||||
|
||||
const auto addController = [&](const Controller &controller, const bool isBack) {
|
||||
if (controller.feedbackValid)
|
||||
{
|
||||
auto arr = doc.createNestedObject(!isBack ? "f":"b");
|
||||
// Voltage
|
||||
arr["V"] = controller.getCalibratedVoltage();
|
||||
|
||||
// Amperes
|
||||
arr["lA"] = fixCurrent(controller.feedback.left.dcLink);
|
||||
arr["rA"] = fixCurrent(controller.feedback.right.dcLink);
|
||||
|
||||
// Temperature
|
||||
arr[!isBack ? "fT":"bT"] = fixBoardTemp(controller.feedback.boardTemp);
|
||||
|
||||
// Errors
|
||||
arr[!isBack ? "flE":"blE"] = controller.feedback.left.error;
|
||||
arr[!isBack ? "frE":"brE"] = controller.feedback.right.error;
|
||||
|
||||
// Speed
|
||||
arr[!isBack ? "flS":"blS"] = convertToKmh(controller.feedback.left.speed);
|
||||
arr[!isBack ? "frS":"brS"] = convertToKmh(controller.feedback.right.speed);
|
||||
}
|
||||
};
|
||||
|
||||
addController(controllers.front, false);
|
||||
addController(controllers.back, true);
|
||||
|
||||
// Potis
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
// Statistics
|
||||
doc["bP"] = getBatteryPercentage(avgVoltage, BatteryCellType(settings.battery.cellType));
|
||||
doc["bV"] = avgVoltage;
|
||||
doc["l"] = isLocked;
|
||||
// doc["mM"] = currentMode->displayName();
|
||||
doc["mN"] = drivingStatistics.meters_driven;
|
||||
doc["mT"] = drivingStatistics.totalMeters;
|
||||
doc["dT"] = drivingStatistics.currentDrivingTime;
|
||||
doc["cW"] = watt;
|
||||
doc["wN"] = drivingStatistics.wh_used;
|
||||
doc["wL"] = getRemainingWattHours();
|
||||
doc["kmL"] = getRemainingWattHours() / settings.battery.watthoursPerKilometer;
|
||||
|
||||
serializeJson(doc, buf);
|
||||
return buf;
|
||||
}
|
||||
|
||||
void sendUdpCloudPacket()
|
||||
{
|
||||
EVERY_N_MILLIS(30) {
|
||||
if (espchrono::ago(timestampLastFailed) < 3s)
|
||||
return;
|
||||
|
||||
if (stringSettings.udpCloudUrl.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (wifi_stack::get_sta_status() != wifi_stack::WiFiStaStatus::CONNECTED)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ip_addr_t udpCloudIp;
|
||||
|
||||
if (const auto res = dns_gethostbyname(stringSettings.udpCloudUrl.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);
|
||||
}
|
||||
timestampLastFailed = espchrono::millis_clock::now();
|
||||
return;
|
||||
}
|
||||
|
||||
if (udpCloudIp.type != IPADDR_TYPE_V4)
|
||||
{
|
||||
ESP_LOGE(TAG, "unsupported ip type: %hhu", udpCloudIp.type);
|
||||
return;
|
||||
}
|
||||
|
||||
sockaddr_in receipient;
|
||||
receipient.sin_port = htons(24242);
|
||||
receipient.sin_addr.s_addr = udpCloudIp.u_addr.ip4.addr;
|
||||
receipient.sin_family = AF_INET;
|
||||
|
||||
wifi_stack::UdpSender udpCloudSender;
|
||||
std::string buf = buildUdpCloudJson();
|
||||
|
||||
|
||||
if (const auto result = udpCloudSender.send(receipient, buf); !result)
|
||||
{
|
||||
ESP_LOGE(TAG, "send to cloud failed");
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "now: %s", buf.c_str());
|
||||
}
|
||||
}
|
6
main/udpcloud.h
Normal file
6
main/udpcloud.h
Normal file
@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
|
||||
void spamUdpBroadcast();
|
||||
std::string buildUdpCloudJson();
|
||||
void sendUdpCloudPacket();
|
Reference in New Issue
Block a user