Determine double battery usage in MQTT at run-time

This commit is contained in:
Jaakko Haakana 2025-06-01 21:15:42 +03:00
parent 8cb4884af7
commit 3789d72833
5 changed files with 68 additions and 60 deletions

View file

@ -88,11 +88,6 @@ void setup() {
&logging_loop_task, WIFI_CORE);
#endif
#ifdef MQTT
xTaskCreatePinnedToCore((TaskFunction_t)&mqtt_loop, "mqtt_loop", 4096, NULL, TASK_MQTT_PRIO, &mqtt_loop_task,
WIFI_CORE);
#endif
init_CAN();
init_contactors();
@ -126,6 +121,12 @@ void setup() {
};
// Start tasks
#ifdef MQTT
xTaskCreatePinnedToCore((TaskFunction_t)&mqtt_loop, "mqtt_loop", 4096, NULL, TASK_MQTT_PRIO, &mqtt_loop_task,
WIFI_CORE);
#endif
xTaskCreatePinnedToCore((TaskFunction_t)&core_loop, "core_loop", 4096, NULL, TASK_CORE_PRIO, &main_loop_task,
CORE_FUNCTION_CORE);
#ifdef PERIODIC_BMS_RESET_AT

View file

@ -47,6 +47,9 @@ class Battery {
// This allows for battery specific SOC plausibility calculations to be performed.
virtual bool soc_plausible() { return true; }
// Battery reports total_charged_battery_Wh and total_discharged_battery_Wh
virtual bool supports_charged_energy() { return false; }
virtual BatteryHtmlRenderer& get_status_renderer() { return defaultRenderer; }
private:

View file

@ -15,6 +15,7 @@ class MebBattery : public CanBattery {
virtual void update_values();
virtual void transmit_can(unsigned long currentMillis);
bool supports_real_BMS_status() { return true; }
bool supports_charged_energy() { return true; }
BatteryHtmlRenderer& get_status_renderer() { return renderer; }

View file

@ -30,6 +30,8 @@ class TeslaBattery : public CanBattery {
bool supports_reset_BMS() { return true; }
void reset_BMS() { datalayer.battery.settings.user_requests_tesla_bms_reset = true; }
bool supports_charged_energy() { return true; }
BatteryHtmlRenderer& get_status_renderer() { return renderer; }
private:

View file

@ -89,11 +89,8 @@ SensorConfig sensorConfigTemplate[] = {
{"bms_status", "BMS Status", "", "", ""},
{"pause_status", "Pause Status", "", "", ""}};
#ifdef DOUBLE_BATTERY
// Enough space for two batteries
SensorConfig sensorConfigs[((sizeof(sensorConfigTemplate) / sizeof(sensorConfigTemplate[0])) * 2) - 2];
#else
SensorConfig sensorConfigs[sizeof(sensorConfigTemplate) / sizeof(sensorConfigTemplate[0])];
#endif // DOUBLE_BATTERY
void create_sensor_configs() {
int number_of_templates = sizeof(sensorConfigTemplate) / sizeof(sensorConfigTemplate[0]);
@ -101,7 +98,8 @@ void create_sensor_configs() {
SensorConfig config = sensorConfigTemplate[i];
config.value_template = strdup(("{{ value_json." + std::string(config.object_id) + " }}").c_str());
sensorConfigs[i] = config;
#ifdef DOUBLE_BATTERY
if (battery2) {
if (config.object_id == "pause_status" || config.object_id == "bms_status") {
continue;
}
@ -110,7 +108,7 @@ void create_sensor_configs() {
sensorConfigs[i + number_of_templates].object_id = strdup(String(config.object_id + String("_2")).c_str());
sensorConfigs[i + number_of_templates].value_template =
strdup(("{{ value_json." + std::string(config.object_id) + "_2 }}").c_str());
#endif // DOUBLE_BATTERY
}
}
}
@ -164,7 +162,8 @@ static String generateButtonTopic(const char* subtype) {
return topic_name + "/command/" + String(subtype);
}
void set_battery_attributes(JsonDocument& doc, const DATALAYER_BATTERY_TYPE& battery, const String& suffix) {
void set_battery_attributes(JsonDocument& doc, const DATALAYER_BATTERY_TYPE& battery, const String& suffix,
bool supports_charged) {
doc["SOC" + suffix] = ((float)battery.status.reported_soc) / 100.0;
doc["SOC_real" + suffix] = ((float)battery.status.real_soc) / 100.0;
doc["state_of_health" + suffix] = ((float)battery.status.soh_pptt) / 100.0;
@ -185,13 +184,14 @@ void set_battery_attributes(JsonDocument& doc, const DATALAYER_BATTERY_TYPE& bat
doc["remaining_capacity" + suffix] = ((float)battery.status.reported_remaining_capacity_Wh);
doc["max_discharge_power" + suffix] = ((float)battery.status.max_discharge_power_W);
doc["max_charge_power" + suffix] = ((float)battery.status.max_charge_power_W);
#if defined(MEB_BATTERY) || defined(TESLA_BATTERY)
if (supports_charged) {
if (datalayer.battery.status.total_charged_battery_Wh != 0 &&
datalayer.battery.status.total_discharged_battery_Wh != 0) {
doc["charged_energy" + suffix] = ((float)datalayer.battery.status.total_charged_battery_Wh);
doc["discharged_energy" + suffix] = ((float)datalayer.battery.status.total_discharged_battery_Wh);
}
#endif
}
}
static std::vector<EventData> order_events;
@ -231,14 +231,15 @@ static bool publish_common_info(void) {
//only publish these values if BMS is active and we are comunication with the battery (can send CAN messages to the battery)
if (datalayer.battery.status.CAN_battery_still_alive && allowed_to_send_CAN && millis() > BOOTUP_TIME) {
set_battery_attributes(doc, datalayer.battery, "");
set_battery_attributes(doc, datalayer.battery, "", battery->supports_charged_energy());
}
#ifdef DOUBLE_BATTERY
if (battery2) {
//only publish these values if BMS is active and we are comunication with the battery (can send CAN messages to the battery)
if (datalayer.battery2.status.CAN_battery_still_alive && allowed_to_send_CAN && millis() > BOOTUP_TIME) {
set_battery_attributes(doc, datalayer.battery2, "_2");
set_battery_attributes(doc, datalayer.battery2, "_2", battery2->supports_charged_energy());
}
}
#endif // DOUBLE_BATTERY
serializeJson(doc, mqtt_msg);
if (mqtt_publish(state_topic.c_str(), mqtt_msg, false) == false) {
#ifdef DEBUG_LOG
@ -256,9 +257,7 @@ static bool publish_common_info(void) {
static bool publish_cell_voltages(void) {
static JsonDocument doc;
static String state_topic = topic_name + "/spec_data";
#ifdef DOUBLE_BATTERY
static String state_topic_2 = topic_name + "/spec_data_2";
#endif // DOUBLE_BATTERY
#ifdef HA_AUTODISCOVERY
bool failed_to_publish = false;
@ -280,7 +279,9 @@ static bool publish_cell_voltages(void) {
}
doc.clear(); // clear after sending autoconfig
}
#ifdef DOUBLE_BATTERY
if (battery2) {
// TODO: Combine this identical block with the previous one.
// If the cell voltage number isn't initialized...
if (datalayer.battery2.info.number_of_cells != 0u) {
@ -297,7 +298,7 @@ static bool publish_cell_voltages(void) {
}
doc.clear(); // clear after sending autoconfig
}
#endif // DOUBLE_BATTERY
}
}
if (failed_to_publish == false) {
ha_cell_voltages_published = true;
@ -324,7 +325,7 @@ static bool publish_cell_voltages(void) {
doc.clear();
}
#ifdef DOUBLE_BATTERY
if (battery2) {
// If cell voltages have been populated...
if (datalayer.battery2.info.number_of_cells != 0u &&
datalayer.battery2.status.cell_voltages_mV[datalayer.battery2.info.number_of_cells - 1] != 0u) {
@ -344,7 +345,7 @@ static bool publish_cell_voltages(void) {
}
doc.clear();
}
#endif // DOUBLE_BATTERY
}
return true;
}