Eliminate mqtt compile time dependency to battery type

This commit is contained in:
Jaakko Haakana 2025-06-02 08:24:59 +03:00
parent 3789d72833
commit dbe3de7422
3 changed files with 47 additions and 36 deletions

View file

@ -43,9 +43,14 @@ class NissanLeafBattery : public CanBattery {
virtual void transmit_can(unsigned long currentMillis);
bool supports_reset_SOH();
void reset_SOH() { datalayer_extended.nissanleaf.UserRequestSOHreset = true; }
bool soc_plausible() {
// When pack voltage is close to max, and SOC% is still low, SOC is not plausible
return !((datalayer.battery.status.voltage_dV > (datalayer.battery.info.max_design_voltage_dV - 100)) &&
(datalayer.battery.status.real_soc < 6500));
}
BatteryHtmlRenderer& get_status_renderer() { return renderer; }
private:

View file

@ -62,38 +62,47 @@ struct SensorConfig {
const char* value_template;
const char* unit;
const char* device_class;
// A function that returns true for the battery if it supports this config
std::function<bool(Battery*)> condition;
};
static std::function<bool(Battery*)> always = [](Battery* b) {
return true;
};
static std::function<bool(Battery*)> supports_charged = [](Battery* b) {
return b->supports_charged_energy();
};
SensorConfig sensorConfigTemplate[] = {
{"SOC", "SOC (Scaled)", "", "%", "battery"},
{"SOC_real", "SOC (real)", "", "%", "battery"},
{"state_of_health", "State Of Health", "", "%", "battery"},
{"temperature_min", "Temperature Min", "", "°C", "temperature"},
{"temperature_max", "Temperature Max", "", "°C", "temperature"},
{"cpu_temp", "CPU Temperature", "", "°C", "temperature"},
{"stat_batt_power", "Stat Batt Power", "", "W", "power"},
{"battery_current", "Battery Current", "", "A", "current"},
{"cell_max_voltage", "Cell Max Voltage", "", "V", "voltage"},
{"cell_min_voltage", "Cell Min Voltage", "", "V", "voltage"},
{"cell_voltage_delta", "Cell Voltage Delta", "", "mV", "voltage"},
{"battery_voltage", "Battery Voltage", "", "V", "voltage"},
{"total_capacity", "Battery Total Capacity", "", "Wh", "energy"},
{"remaining_capacity", "Battery Remaining Capacity (scaled)", "", "Wh", "energy"},
{"remaining_capacity_real", "Battery Remaining Capacity (real)", "", "Wh", "energy"},
{"max_discharge_power", "Battery Max Discharge Power", "", "W", "power"},
{"max_charge_power", "Battery Max Charge Power", "", "W", "power"},
#if defined(MEB_BATTERY) || defined(TESLA_BATTERY)
{"charged_energy", "Battery Charged Energy", "", "Wh", "energy"},
{"discharged_energy", "Battery Discharged Energy", "", "Wh", "energy"},
#endif
{"bms_status", "BMS Status", "", "", ""},
{"pause_status", "Pause Status", "", "", ""}};
{"SOC", "SOC (Scaled)", "", "%", "battery", always},
{"SOC_real", "SOC (real)", "", "%", "battery", always},
{"state_of_health", "State Of Health", "", "%", "battery", always},
{"temperature_min", "Temperature Min", "", "°C", "temperature", always},
{"temperature_max", "Temperature Max", "", "°C", "temperature", always},
{"cpu_temp", "CPU Temperature", "", "°C", "temperature", always},
{"stat_batt_power", "Stat Batt Power", "", "W", "power", always},
{"battery_current", "Battery Current", "", "A", "current", always},
{"cell_max_voltage", "Cell Max Voltage", "", "V", "voltage", always},
{"cell_min_voltage", "Cell Min Voltage", "", "V", "voltage", always},
{"cell_voltage_delta", "Cell Voltage Delta", "", "mV", "voltage", always},
{"battery_voltage", "Battery Voltage", "", "V", "voltage", always},
{"total_capacity", "Battery Total Capacity", "", "Wh", "energy", always},
{"remaining_capacity", "Battery Remaining Capacity (scaled)", "", "Wh", "energy", always},
{"remaining_capacity_real", "Battery Remaining Capacity (real)", "", "Wh", "energy", always},
{"max_discharge_power", "Battery Max Discharge Power", "", "W", "power", always},
{"max_charge_power", "Battery Max Charge Power", "", "W", "power", always},
{"charged_energy", "Battery Charged Energy", "", "Wh", "energy", supports_charged},
{"discharged_energy", "Battery Discharged Energy", "", "Wh", "energy", supports_charged},
{"bms_status", "BMS Status", "", "", "", always},
{"pause_status", "Pause Status", "", "", "", always}};
// Enough space for two batteries
SensorConfig sensorConfigs[((sizeof(sensorConfigTemplate) / sizeof(sensorConfigTemplate[0])) * 2) - 2];
void create_sensor_configs() {
int number_of_templates = sizeof(sensorConfigTemplate) / sizeof(sensorConfigTemplate[0]);
for (int i = 0; i < number_of_templates; i++) {
SensorConfig config = sensorConfigTemplate[i];
config.value_template = strdup(("{{ value_json." + std::string(config.object_id) + " }}").c_str());
@ -203,13 +212,19 @@ static bool publish_common_info(void) {
if (ha_common_info_published == false) {
for (int i = 0; i < sizeof(sensorConfigs) / sizeof(sensorConfigs[0]); i++) {
SensorConfig& config = sensorConfigs[i];
if (!config.condition(battery)) {
continue;
}
doc["name"] = config.name;
doc["state_topic"] = state_topic;
doc["unique_id"] = topic_name + "_" + String(config.object_id);
doc["object_id"] = object_id_prefix + String(config.object_id);
doc["value_template"] = config.value_template;
if (config.unit != nullptr && strlen(config.unit) > 0)
if (config.unit != nullptr && strlen(config.unit) > 0) {
doc["unit_of_measurement"] = config.unit;
}
if (config.device_class != nullptr && strlen(config.device_class) > 0) {
doc["device_class"] = config.device_class;
doc["state_class"] = "measurement";

View file

@ -156,18 +156,9 @@ void update_machineryprotection() {
clear_event(EVENT_SOH_LOW);
}
#ifdef NISSAN_LEAF_BATTERY
// Check if SOC% is plausible
if (datalayer.battery.status.voltage_dV >
(datalayer.battery.info.max_design_voltage_dV -
100)) { // When pack voltage is close to max, and SOC% is still low, raise event
if (datalayer.battery.status.real_soc < 6500) { // 65.00%
set_event(EVENT_SOC_PLAUSIBILITY_ERROR, datalayer.battery.status.real_soc);
} else {
clear_event(EVENT_SOC_PLAUSIBILITY_ERROR);
}
if (!battery->soc_plausible()) {
set_event(EVENT_SOC_PLAUSIBILITY_ERROR, datalayer.battery.status.real_soc);
}
#endif //NISSAN_LEAF_BATTERY
// Check diff between highest and lowest cell
cell_deviation_mV =