diff --git a/esphome/components/daly_hkms_bms/binary_sensor.py b/esphome/components/daly_hkms_bms/binary_sensor.py new file mode 100644 index 0000000000..ab3afb27af --- /dev/null +++ b/esphome/components/daly_hkms_bms/binary_sensor.py @@ -0,0 +1,48 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import binary_sensor +from . import DalyHkmsBmsComponent, CONF_DALY_HKMS_BMS_ID + +CONF_CHARGING_MOS_ENABLED = "charging_mos_enabled" +CONF_DISCHARGING_MOS_ENABLED = "discharging_mos_enabled" +CONF_PRECHARGING_MOS_ENABLED = "precharging_mos_enabled" +CONF_BALANCING_ACTIVE = "balancing_active" + +TYPES = [ + CONF_CHARGING_MOS_ENABLED, + CONF_DISCHARGING_MOS_ENABLED, + CONF_PRECHARGING_MOS_ENABLED, + CONF_BALANCING_ACTIVE, +] + +CONFIG_SCHEMA = cv.All( + cv.Schema( + { + cv.GenerateID(CONF_DALY_HKMS_BMS_ID): cv.use_id(DalyHkmsBmsComponent), + cv.Optional( + CONF_CHARGING_MOS_ENABLED + ): binary_sensor.binary_sensor_schema(), + cv.Optional( + CONF_DISCHARGING_MOS_ENABLED + ): binary_sensor.binary_sensor_schema(), + cv.Optional( + CONF_PRECHARGING_MOS_ENABLED + ): binary_sensor.binary_sensor_schema(), + cv.Optional( + CONF_BALANCING_ACTIVE + ): binary_sensor.binary_sensor_schema(), + } + ).extend(cv.COMPONENT_SCHEMA) +) + + +async def setup_conf(config, key, hub): + if sensor_config := config.get(key): + var = await binary_sensor.new_binary_sensor(sensor_config) + cg.add(getattr(hub, f"set_{key}_binary_sensor")(var)) + + +async def to_code(config): + hub = await cg.get_variable(config[CONF_DALY_HKMS_BMS_ID]) + for key in TYPES: + await setup_conf(config, key, hub) diff --git a/esphome/components/daly_hkms_bms/daly_hkms_bms.cpp b/esphome/components/daly_hkms_bms/daly_hkms_bms.cpp index 237e9127f0..7451b8b88b 100644 --- a/esphome/components/daly_hkms_bms/daly_hkms_bms.cpp +++ b/esphome/components/daly_hkms_bms/daly_hkms_bms.cpp @@ -1,4 +1,5 @@ #include "daly_hkms_bms.h" +#include "daly_hkms_bms_registers.h" #include "esphome/core/log.h" namespace esphome { @@ -14,9 +15,6 @@ static const uint8_t DALY_MODBUS_RESPONSE_ADDRESS_OFFSET = 0x50; static const uint8_t MODBUS_CMD_READ_HOLDING_REGISTERS = 0x03; -static const uint16_t MODBUS_ADDR_SUM_VOLT = 56; -static const uint16_t MODBUS_REGISTER_COUNT = 3; - void DalyHkmsBmsComponent::set_daly_address(uint8_t daly_address) { this->daly_address_ = daly_address; @@ -49,7 +47,14 @@ void DalyHkmsBmsComponent::update() { this->waiting_to_update_ = false; // send the request using Modbus directly instead of ModbusDevice so we can send the data with the request address - this->parent_->send(this->daly_address_ + DALY_MODBUS_REQUEST_ADDRESS_OFFSET, MODBUS_CMD_READ_HOLDING_REGISTERS, MODBUS_ADDR_SUM_VOLT, MODBUS_REGISTER_COUNT, 0, nullptr); + uint8_t modbus_request_address = this->daly_address_ + DALY_MODBUS_REQUEST_ADDRESS_OFFSET; + this->parent_->send( + modbus_request_address, + MODBUS_CMD_READ_HOLDING_REGISTERS, + 0x00, + DALY_MODBUS_REGISTER_COUNT, + 0, + nullptr); this->last_send_ = millis(); } @@ -62,23 +67,105 @@ void DalyHkmsBmsComponent::on_modbus_data(const std::vector &data) { this->last_send_ = 0; // Also ignore the data if the message is too short. Otherwise we will publish invalid values. - if (data.size() < MODBUS_REGISTER_COUNT * 2) + if (data.size() < DALY_MODBUS_REGISTER_COUNT * 2) return; -#ifdef USE_SENSOR - if (this->voltage_sensor_) { - float voltage = encode_uint16(data[0], data[1]) / 10.0; - this->voltage_sensor_->publish_state(voltage); - } - - if (this->current_sensor_) { - float current = (encode_uint16(data[2], data[3]) - 30000) / 10.0; - this->current_sensor_->publish_state(current); - } + auto get_register = [&](size_t i) -> uint16_t { + return encode_uint16(data[i * 2], data[i * 2 + 1]); + }; - if (this->battery_level_sensor_) { - float current = encode_uint16(data[4], data[5]) / 10.0; - this->battery_level_sensor_->publish_state(current); + auto publish_sensor_state = [&](sensor::Sensor *sensor, size_t i, int16_t offset, float factor, + int32_t unavailable_value = -1) -> void { + if (sensor == nullptr) + return; + uint16_t register_value = get_register(i); + float value = register_value == unavailable_value ? NAN : (register_value + offset) * factor; + sensor->publish_state(value); + }; + +#ifdef USE_SENSOR + publish_sensor_state(this->cell_1_voltage_sensor_ , DALY_MODBUS_ADDR_CELL_VOLT_1 , 0, 0.001); + publish_sensor_state(this->cell_2_voltage_sensor_ , DALY_MODBUS_ADDR_CELL_VOLT_1 + 1 , 0, 0.001); + publish_sensor_state(this->cell_3_voltage_sensor_ , DALY_MODBUS_ADDR_CELL_VOLT_1 + 2 , 0, 0.001); + publish_sensor_state(this->cell_4_voltage_sensor_ , DALY_MODBUS_ADDR_CELL_VOLT_1 + 3 , 0, 0.001); + publish_sensor_state(this->cell_5_voltage_sensor_ , DALY_MODBUS_ADDR_CELL_VOLT_1 + 4 , 0, 0.001); + publish_sensor_state(this->cell_6_voltage_sensor_ , DALY_MODBUS_ADDR_CELL_VOLT_1 + 5 , 0, 0.001); + publish_sensor_state(this->cell_7_voltage_sensor_ , DALY_MODBUS_ADDR_CELL_VOLT_1 + 6 , 0, 0.001); + publish_sensor_state(this->cell_8_voltage_sensor_ , DALY_MODBUS_ADDR_CELL_VOLT_1 + 7 , 0, 0.001); + publish_sensor_state(this->cell_9_voltage_sensor_ , DALY_MODBUS_ADDR_CELL_VOLT_1 + 8 , 0, 0.001); + publish_sensor_state(this->cell_10_voltage_sensor_, DALY_MODBUS_ADDR_CELL_VOLT_1 + 9 , 0, 0.001); + publish_sensor_state(this->cell_11_voltage_sensor_, DALY_MODBUS_ADDR_CELL_VOLT_1 + 10, 0, 0.001); + publish_sensor_state(this->cell_12_voltage_sensor_, DALY_MODBUS_ADDR_CELL_VOLT_1 + 11, 0, 0.001); + publish_sensor_state(this->cell_13_voltage_sensor_, DALY_MODBUS_ADDR_CELL_VOLT_1 + 12, 0, 0.001); + publish_sensor_state(this->cell_14_voltage_sensor_, DALY_MODBUS_ADDR_CELL_VOLT_1 + 13, 0, 0.001); + publish_sensor_state(this->cell_15_voltage_sensor_, DALY_MODBUS_ADDR_CELL_VOLT_1 + 14, 0, 0.001); + publish_sensor_state(this->cell_16_voltage_sensor_, DALY_MODBUS_ADDR_CELL_VOLT_1 + 15, 0, 0.001); + + publish_sensor_state(this->temperature_1_sensor_, DALY_MODBUS_ADDR_CELL_TEMP_1 , -40, 1, 255); + publish_sensor_state(this->temperature_2_sensor_, DALY_MODBUS_ADDR_CELL_TEMP_1 + 1, -40, 1, 255); + publish_sensor_state(this->temperature_3_sensor_, DALY_MODBUS_ADDR_CELL_TEMP_1 + 2, -40, 1, 255); + publish_sensor_state(this->temperature_4_sensor_, DALY_MODBUS_ADDR_CELL_TEMP_1 + 3, -40, 1, 255); + publish_sensor_state(this->temperature_5_sensor_, DALY_MODBUS_ADDR_CELL_TEMP_1 + 4, -40, 1, 255); + publish_sensor_state(this->temperature_6_sensor_, DALY_MODBUS_ADDR_CELL_TEMP_1 + 5, -40, 1, 255); + publish_sensor_state(this->temperature_7_sensor_, DALY_MODBUS_ADDR_CELL_TEMP_1 + 6, -40, 1, 255); + publish_sensor_state(this->temperature_8_sensor_, DALY_MODBUS_ADDR_CELL_TEMP_1 + 7, -40, 1, 255); + + publish_sensor_state(this->voltage_sensor_, DALY_MODBUS_ADDR_VOLT, 0, 0.1); + publish_sensor_state(this->current_sensor_, DALY_MODBUS_ADDR_CURR, -30000, 0.1); + publish_sensor_state(this->battery_level_sensor_, DALY_MODBUS_ADDR_SOC, 0, 0.1); + + publish_sensor_state(this->cells_number_sensor_, DALY_MODBUS_ADDR_CELL_COUNT, 0, 1); + publish_sensor_state(this->temps_number_sensor_, DALY_MODBUS_ADDR_CELL_TEMP_COUNT, 0, 1); + + publish_sensor_state(this->max_cell_voltage_sensor_, DALY_MODBUS_ADDR_CELL_VOLT_MAX, 0, 0.001); + publish_sensor_state(this->max_cell_voltage_number_sensor_, DALY_MODBUS_ADDR_CELL_VOLT_MAX_NUM, 0, 1); + + publish_sensor_state(this->min_cell_voltage_sensor_, DALY_MODBUS_ADDR_CELL_VOLT_MIN, 0, 0.001); + publish_sensor_state(this->min_cell_voltage_number_sensor_, DALY_MODBUS_ADDR_CELL_VOLT_MIN_NUM, 0, 1); + + publish_sensor_state(this->max_temperature_sensor_, DALY_MODBUS_ADDR_CELL_TEMP_MAX, -40, 1, 255); + publish_sensor_state(this->max_temperature_probe_number_sensor_, DALY_MODBUS_ADDR_CELL_TEMP_MAX_NUM, 0, 1); + + publish_sensor_state(this->min_temperature_sensor_, DALY_MODBUS_ADDR_CELL_TEMP_MIN, -40, 1, 255); + publish_sensor_state(this->min_temperature_probe_number_sensor_, DALY_MODBUS_ADDR_CELL_TEMP_MIN_NUM, 0, 1); + + publish_sensor_state(this->remaining_capacity_sensor_, DALY_MODBUS_ADDR_REMAINING_CAPACITY, 0, 0.1); + publish_sensor_state(this->cycles_sensor_, DALY_MODBUS_ADDR_CYCLES, 0, 1); + + publish_sensor_state(this->temperature_mos_sensor_, DALY_MODBUS_ADDR_MOS_TEMP, -40, 1, 255); + publish_sensor_state(this->temperature_board_sensor_, DALY_MODBUS_ADDR_BOARD_TEMP, -40, 1, 255); +#endif + +#ifdef USE_TEXT_SENSOR + if (this->status_text_sensor_ != nullptr) { + switch (get_register(DALY_MODBUS_ADDR_CHG_DSCHG_STATUS)) { + case 0: + this->status_text_sensor_->publish_state("Stationary"); + break; + case 1: + this->status_text_sensor_->publish_state("Charging"); + break; + case 2: + this->status_text_sensor_->publish_state("Discharging"); + break; + default: + break; + } + } +#endif + +#ifdef USE_BINARY_SENSOR + if (this->balancing_active_binary_sensor_) { + this->balancing_active_binary_sensor_->publish_state(get_register(DALY_MODBUS_ADDR_BALANCE_STATUS) > 0); + } + if (this->charging_mos_enabled_binary_sensor_) { + this->charging_mos_enabled_binary_sensor_->publish_state(get_register(DALY_MODBUS_ADDR_CHG_MOS_ACTIVE) > 0); + } + if (this->discharging_mos_enabled_binary_sensor_) { + this->discharging_mos_enabled_binary_sensor_->publish_state(get_register(DALY_MODBUS_ADDR_DSCHG_MOS_ACTIVE) > 0); + } + if (this->precharging_mos_enabled_binary_sensor_) { + this->precharging_mos_enabled_binary_sensor_->publish_state(get_register(DALY_MODBUS_ADDR_PRECHG_MOS_ACTIVE) > 0); } #endif } diff --git a/esphome/components/daly_hkms_bms/daly_hkms_bms.h b/esphome/components/daly_hkms_bms/daly_hkms_bms.h index 07eede0e25..7fecbed1c7 100644 --- a/esphome/components/daly_hkms_bms/daly_hkms_bms.h +++ b/esphome/components/daly_hkms_bms/daly_hkms_bms.h @@ -1,7 +1,16 @@ #pragma once #include "esphome/core/component.h" +#include "esphome/core/defines.h" +#ifdef USE_SENSOR #include "esphome/components/sensor/sensor.h" +#endif +#ifdef USE_TEXT_SENSOR +#include "esphome/components/text_sensor/text_sensor.h" +#endif +#ifdef USE_BINARY_SENSOR +#include "esphome/components/binary_sensor/binary_sensor.h" +#endif #include "esphome/components/modbus/modbus.h" #include @@ -22,6 +31,55 @@ class DalyHkmsBmsComponent : public PollingComponent, public modbus::ModbusDevic SUB_SENSOR(voltage) SUB_SENSOR(current) SUB_SENSOR(battery_level) + SUB_SENSOR(max_cell_voltage) + SUB_SENSOR(max_cell_voltage_number) + SUB_SENSOR(min_cell_voltage) + SUB_SENSOR(min_cell_voltage_number) + SUB_SENSOR(max_temperature) + SUB_SENSOR(max_temperature_probe_number) + SUB_SENSOR(min_temperature) + SUB_SENSOR(min_temperature_probe_number) + SUB_SENSOR(remaining_capacity) + SUB_SENSOR(cycles) + SUB_SENSOR(cells_number) + SUB_SENSOR(temps_number) + SUB_SENSOR(temperature_1) + SUB_SENSOR(temperature_2) + SUB_SENSOR(temperature_3) + SUB_SENSOR(temperature_4) + SUB_SENSOR(temperature_5) + SUB_SENSOR(temperature_6) + SUB_SENSOR(temperature_7) + SUB_SENSOR(temperature_8) + SUB_SENSOR(temperature_mos) + SUB_SENSOR(temperature_board) + SUB_SENSOR(cell_1_voltage) + SUB_SENSOR(cell_2_voltage) + SUB_SENSOR(cell_3_voltage) + SUB_SENSOR(cell_4_voltage) + SUB_SENSOR(cell_5_voltage) + SUB_SENSOR(cell_6_voltage) + SUB_SENSOR(cell_7_voltage) + SUB_SENSOR(cell_8_voltage) + SUB_SENSOR(cell_9_voltage) + SUB_SENSOR(cell_10_voltage) + SUB_SENSOR(cell_11_voltage) + SUB_SENSOR(cell_12_voltage) + SUB_SENSOR(cell_13_voltage) + SUB_SENSOR(cell_14_voltage) + SUB_SENSOR(cell_15_voltage) + SUB_SENSOR(cell_16_voltage) +#endif + +#ifdef USE_TEXT_SENSOR + SUB_TEXT_SENSOR(status) +#endif + +#ifdef USE_BINARY_SENSOR + SUB_BINARY_SENSOR(charging_mos_enabled) + SUB_BINARY_SENSOR(discharging_mos_enabled) + SUB_BINARY_SENSOR(precharging_mos_enabled) + SUB_BINARY_SENSOR(balancing_active) #endif protected: diff --git a/esphome/components/daly_hkms_bms/daly_hkms_bms_registers.h b/esphome/components/daly_hkms_bms/daly_hkms_bms_registers.h new file mode 100644 index 0000000000..ae0402deea --- /dev/null +++ b/esphome/components/daly_hkms_bms/daly_hkms_bms_registers.h @@ -0,0 +1,53 @@ +#pragma once +namespace esphome { +namespace daly_hkms_bms { + +// 0x00 - 0x2F +static const uint16_t DALY_MODBUS_ADDR_CELL_VOLT_1 = 0x00; + +// 0x30 - 0x37 +static const uint16_t DALY_MODBUS_ADDR_CELL_TEMP_1 = 0x30; + +static const uint16_t DALY_MODBUS_ADDR_VOLT = 0x38; +static const uint16_t DALY_MODBUS_ADDR_CURR = 0x39; +static const uint16_t DALY_MODBUS_ADDR_SOC = 0x3A; +static const uint16_t DALY_MODBUS_ADDR_SOH = 0x3B; + +static const uint16_t DALY_MODBUS_ADDR_CELL_COUNT = 0x3C; +static const uint16_t DALY_MODBUS_ADDR_CELL_TEMP_COUNT = 0x3D; +static const uint16_t DALY_MODBUS_ADDR_CELL_VOLT_MAX = 0x3E; +static const uint16_t DALY_MODBUS_ADDR_CELL_VOLT_MAX_NUM = 0x3F; +static const uint16_t DALY_MODBUS_ADDR_CELL_VOLT_MIN = 0x40; +static const uint16_t DALY_MODBUS_ADDR_CELL_VOLT_MIN_NUM = 0x41; +static const uint16_t DALY_MODBUS_ADDR_CELL_VOLT_DIFF = 0x42; +static const uint16_t DALY_MODBUS_ADDR_CELL_TEMP_MAX = 0x43; +static const uint16_t DALY_MODBUS_ADDR_CELL_TEMP_MAX_NUM = 0x44; +static const uint16_t DALY_MODBUS_ADDR_CELL_TEMP_MIN = 0x45; +static const uint16_t DALY_MODBUS_ADDR_CELL_TEMP_MIN_NUM = 0x46; +static const uint16_t DALY_MODBUS_ADDR_CELL_TEMP_DIFF = 0x47; + +static const uint16_t DALY_MODBUS_ADDR_CHG_DSCHG_STATUS = 0x48; +static const uint16_t DALY_MODBUS_ADDR_REMAINING_CAPACITY = 0x4B; +static const uint16_t DALY_MODBUS_ADDR_CYCLES = 0x4C; +static const uint16_t DALY_MODBUS_ADDR_BALANCE_STATUS = 0x4D; +static const uint16_t DALY_MODBUS_ADDR_BALANCE_STATUS_PER_CELL_1_TO_16 = 0x4F; +static const uint16_t DALY_MODBUS_ADDR_BALANCE_STATUS_PER_CELL_17_TO_32 = 0x50; +static const uint16_t DALY_MODBUS_ADDR_BALANCE_STATUS_PER_CELL_33_TO_48 = 0x51; + +static const uint16_t DALY_MODBUS_ADDR_CHG_MOS_ACTIVE = 0x52; +static const uint16_t DALY_MODBUS_ADDR_DSCHG_MOS_ACTIVE = 0x53; +static const uint16_t DALY_MODBUS_ADDR_PRECHG_MOS_ACTIVE = 0x54; +static const uint16_t DALY_MODBUS_ADDR_HEATING_MOS_ACTIVE = 0x55; +static const uint16_t DALY_MODBUS_ADDR_FAN_MOS_ACTIVE = 0x56; + +static const uint16_t DALY_MODBUS_ADDR_POWER = 0x58; +static const uint16_t DALY_MODBUS_ADDR_ENERGY = 0x59; + +static const uint16_t DALY_MODBUS_ADDR_MOS_TEMP = 0x5A; +static const uint16_t DALY_MODBUS_ADDR_BOARD_TEMP = 0x5B; +static const uint16_t DALY_MODBUS_ADDR_HEATING_TEMP = 0x5C; + +static const uint16_t DALY_MODBUS_REGISTER_COUNT = 0x5D; + +} // namespace daly_hkms_bms +} // namespace esphome diff --git a/esphome/components/daly_hkms_bms/sensor.py b/esphome/components/daly_hkms_bms/sensor.py index e221958bbe..a2259a371f 100644 --- a/esphome/components/daly_hkms_bms/sensor.py +++ b/esphome/components/daly_hkms_bms/sensor.py @@ -2,33 +2,137 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import sensor from esphome.const import ( - CONF_CURRENT, - CONF_ID, CONF_VOLTAGE, + CONF_CURRENT, CONF_BATTERY_LEVEL, - DEVICE_CLASS_CURRENT, - DEVICE_CLASS_POWER, + CONF_MAX_TEMPERATURE, + CONF_MIN_TEMPERATURE, DEVICE_CLASS_VOLTAGE, + DEVICE_CLASS_CURRENT, DEVICE_CLASS_BATTERY, + DEVICE_CLASS_TEMPERATURE, STATE_CLASS_MEASUREMENT, - STATE_CLASS_TOTAL_INCREASING, - UNIT_AMPERE, - UNIT_CELSIUS, + UNIT_EMPTY, UNIT_VOLT, - UNIT_WATT, + UNIT_AMPERE, UNIT_PERCENT, + UNIT_CELSIUS, + ICON_FLASH, ICON_PERCENT, + ICON_COUNTER, + ICON_THERMOMETER, + ICON_GAUGE, ) from . import DalyHkmsBmsComponent, CONF_DALY_HKMS_BMS_ID +CONF_MAX_CELL_VOLTAGE = "max_cell_voltage" +CONF_MAX_CELL_VOLTAGE_NUMBER = "max_cell_voltage_number" +CONF_MIN_CELL_VOLTAGE = "min_cell_voltage" +CONF_MIN_CELL_VOLTAGE_NUMBER = "min_cell_voltage_number" +CONF_MAX_TEMPERATURE_PROBE_NUMBER = "max_temperature_probe_number" +CONF_MIN_TEMPERATURE_PROBE_NUMBER = "min_temperature_probe_number" +CONF_CELLS_NUMBER = "cells_number" +CONF_TEMPS_NUMBER = "temps_number" + +CONF_REMAINING_CAPACITY = "remaining_capacity" +CONF_CYCLES = "cycles" +CONF_TEMPERATURE_1 = "temperature_1" +CONF_TEMPERATURE_2 = "temperature_2" +CONF_TEMPERATURE_3 = "temperature_3" +CONF_TEMPERATURE_4 = "temperature_4" +CONF_TEMPERATURE_5 = "temperature_5" +CONF_TEMPERATURE_6 = "temperature_6" +CONF_TEMPERATURE_7 = "temperature_7" +CONF_TEMPERATURE_8 = "temperature_8" + +CONF_TEMPERATURE_MOS = "temperature_mos" +CONF_TEMPERATURE_BOARD = "temperature_board" + +CONF_CELL_1_VOLTAGE = "cell_1_voltage" +CONF_CELL_2_VOLTAGE = "cell_2_voltage" +CONF_CELL_3_VOLTAGE = "cell_3_voltage" +CONF_CELL_4_VOLTAGE = "cell_4_voltage" +CONF_CELL_5_VOLTAGE = "cell_5_voltage" +CONF_CELL_6_VOLTAGE = "cell_6_voltage" +CONF_CELL_7_VOLTAGE = "cell_7_voltage" +CONF_CELL_8_VOLTAGE = "cell_8_voltage" +CONF_CELL_9_VOLTAGE = "cell_9_voltage" +CONF_CELL_10_VOLTAGE = "cell_10_voltage" +CONF_CELL_11_VOLTAGE = "cell_11_voltage" +CONF_CELL_12_VOLTAGE = "cell_12_voltage" +CONF_CELL_13_VOLTAGE = "cell_13_voltage" +CONF_CELL_14_VOLTAGE = "cell_14_voltage" +CONF_CELL_15_VOLTAGE = "cell_15_voltage" +CONF_CELL_16_VOLTAGE = "cell_16_voltage" + ICON_CURRENT_DC = "mdi:current-dc" +ICON_BATTERY_OUTLINE = "mdi:battery-outline" +ICON_THERMOMETER_CHEVRON_UP = "mdi:thermometer-chevron-up" +ICON_THERMOMETER_CHEVRON_DOWN = "mdi:thermometer-chevron-down" +ICON_CAR_BATTERY = "mdi:car-battery" + +UNIT_AMPERE_HOUR = "Ah" TYPES = [ CONF_VOLTAGE, CONF_CURRENT, CONF_BATTERY_LEVEL, + CONF_MAX_CELL_VOLTAGE, + CONF_MAX_CELL_VOLTAGE_NUMBER, + CONF_MIN_CELL_VOLTAGE, + CONF_MIN_CELL_VOLTAGE_NUMBER, + CONF_MAX_TEMPERATURE, + CONF_MAX_TEMPERATURE_PROBE_NUMBER, + CONF_MIN_TEMPERATURE, + CONF_MIN_TEMPERATURE_PROBE_NUMBER, + CONF_CELLS_NUMBER, + CONF_TEMPS_NUMBER, + CONF_REMAINING_CAPACITY, + CONF_CYCLES, + CONF_TEMPERATURE_1, + CONF_TEMPERATURE_2, + CONF_TEMPERATURE_3, + CONF_TEMPERATURE_4, + CONF_TEMPERATURE_5, + CONF_TEMPERATURE_6, + CONF_TEMPERATURE_7, + CONF_TEMPERATURE_8, + CONF_TEMPERATURE_MOS, + CONF_TEMPERATURE_BOARD, + CONF_CELL_1_VOLTAGE, + CONF_CELL_2_VOLTAGE, + CONF_CELL_3_VOLTAGE, + CONF_CELL_4_VOLTAGE, + CONF_CELL_5_VOLTAGE, + CONF_CELL_6_VOLTAGE, + CONF_CELL_7_VOLTAGE, + CONF_CELL_8_VOLTAGE, + CONF_CELL_9_VOLTAGE, + CONF_CELL_10_VOLTAGE, + CONF_CELL_11_VOLTAGE, + CONF_CELL_12_VOLTAGE, + CONF_CELL_13_VOLTAGE, + CONF_CELL_14_VOLTAGE, + CONF_CELL_15_VOLTAGE, + CONF_CELL_16_VOLTAGE, ] +TEMPERATURE_SENSOR_SCHEMA = sensor.sensor_schema( + unit_of_measurement=UNIT_CELSIUS, + icon=ICON_THERMOMETER, + accuracy_decimals=0, + device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, +) + +CELL_VOLTAGE_SCHEMA = sensor.sensor_schema( + unit_of_measurement=UNIT_VOLT, + device_class=DEVICE_CLASS_VOLTAGE, + state_class=STATE_CLASS_MEASUREMENT, + icon=ICON_FLASH, + accuracy_decimals=3, +) + CONFIG_SCHEMA = ( cv.Schema( { @@ -54,6 +158,105 @@ CONFIG_SCHEMA = ( device_class=DEVICE_CLASS_BATTERY, state_class=STATE_CLASS_MEASUREMENT, ), + cv.Optional(CONF_MAX_CELL_VOLTAGE): sensor.sensor_schema( + unit_of_measurement=UNIT_VOLT, + icon=ICON_FLASH, + accuracy_decimals=3, + device_class=DEVICE_CLASS_VOLTAGE, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_MAX_CELL_VOLTAGE_NUMBER): sensor.sensor_schema( + unit_of_measurement=UNIT_EMPTY, + icon=ICON_COUNTER, + accuracy_decimals=0, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_MIN_CELL_VOLTAGE): sensor.sensor_schema( + unit_of_measurement=UNIT_VOLT, + icon=ICON_FLASH, + accuracy_decimals=3, + device_class=DEVICE_CLASS_VOLTAGE, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_MIN_CELL_VOLTAGE_NUMBER): sensor.sensor_schema( + unit_of_measurement=UNIT_EMPTY, + icon=ICON_COUNTER, + accuracy_decimals=0, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_MAX_TEMPERATURE): sensor.sensor_schema( + unit_of_measurement=UNIT_CELSIUS, + icon=ICON_THERMOMETER_CHEVRON_UP, + accuracy_decimals=0, + device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_MAX_TEMPERATURE_PROBE_NUMBER): sensor.sensor_schema( + unit_of_measurement=UNIT_EMPTY, + icon=ICON_COUNTER, + accuracy_decimals=0, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_MIN_TEMPERATURE): sensor.sensor_schema( + unit_of_measurement=UNIT_CELSIUS, + icon=ICON_THERMOMETER_CHEVRON_DOWN, + accuracy_decimals=0, + device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_MIN_TEMPERATURE_PROBE_NUMBER): sensor.sensor_schema( + unit_of_measurement=UNIT_EMPTY, + icon=ICON_COUNTER, + accuracy_decimals=0, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_REMAINING_CAPACITY): sensor.sensor_schema( + unit_of_measurement=UNIT_AMPERE_HOUR, + icon=ICON_GAUGE, + accuracy_decimals=1, + device_class=DEVICE_CLASS_VOLTAGE, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_CYCLES): sensor.sensor_schema( + unit_of_measurement=UNIT_EMPTY, + icon=ICON_COUNTER, + accuracy_decimals=0, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_CELLS_NUMBER): sensor.sensor_schema( + icon=ICON_COUNTER, + accuracy_decimals=0, + ), + cv.Optional(CONF_TEMPS_NUMBER): sensor.sensor_schema( + icon=ICON_COUNTER, + accuracy_decimals=0, + ), + cv.Optional(CONF_TEMPERATURE_1): TEMPERATURE_SENSOR_SCHEMA, + cv.Optional(CONF_TEMPERATURE_2): TEMPERATURE_SENSOR_SCHEMA, + cv.Optional(CONF_TEMPERATURE_3): TEMPERATURE_SENSOR_SCHEMA, + cv.Optional(CONF_TEMPERATURE_4): TEMPERATURE_SENSOR_SCHEMA, + cv.Optional(CONF_TEMPERATURE_5): TEMPERATURE_SENSOR_SCHEMA, + cv.Optional(CONF_TEMPERATURE_6): TEMPERATURE_SENSOR_SCHEMA, + cv.Optional(CONF_TEMPERATURE_7): TEMPERATURE_SENSOR_SCHEMA, + cv.Optional(CONF_TEMPERATURE_8): TEMPERATURE_SENSOR_SCHEMA, + cv.Optional(CONF_TEMPERATURE_MOS): TEMPERATURE_SENSOR_SCHEMA, + cv.Optional(CONF_TEMPERATURE_BOARD): TEMPERATURE_SENSOR_SCHEMA, + cv.Optional(CONF_CELL_1_VOLTAGE): CELL_VOLTAGE_SCHEMA, + cv.Optional(CONF_CELL_2_VOLTAGE): CELL_VOLTAGE_SCHEMA, + cv.Optional(CONF_CELL_3_VOLTAGE): CELL_VOLTAGE_SCHEMA, + cv.Optional(CONF_CELL_4_VOLTAGE): CELL_VOLTAGE_SCHEMA, + cv.Optional(CONF_CELL_5_VOLTAGE): CELL_VOLTAGE_SCHEMA, + cv.Optional(CONF_CELL_6_VOLTAGE): CELL_VOLTAGE_SCHEMA, + cv.Optional(CONF_CELL_7_VOLTAGE): CELL_VOLTAGE_SCHEMA, + cv.Optional(CONF_CELL_8_VOLTAGE): CELL_VOLTAGE_SCHEMA, + cv.Optional(CONF_CELL_9_VOLTAGE): CELL_VOLTAGE_SCHEMA, + cv.Optional(CONF_CELL_10_VOLTAGE): CELL_VOLTAGE_SCHEMA, + cv.Optional(CONF_CELL_11_VOLTAGE): CELL_VOLTAGE_SCHEMA, + cv.Optional(CONF_CELL_12_VOLTAGE): CELL_VOLTAGE_SCHEMA, + cv.Optional(CONF_CELL_13_VOLTAGE): CELL_VOLTAGE_SCHEMA, + cv.Optional(CONF_CELL_14_VOLTAGE): CELL_VOLTAGE_SCHEMA, + cv.Optional(CONF_CELL_15_VOLTAGE): CELL_VOLTAGE_SCHEMA, + cv.Optional(CONF_CELL_16_VOLTAGE): CELL_VOLTAGE_SCHEMA } ) .extend(cv.COMPONENT_SCHEMA) diff --git a/esphome/components/daly_hkms_bms/text_sensor.py b/esphome/components/daly_hkms_bms/text_sensor.py new file mode 100644 index 0000000000..00ed56bb5b --- /dev/null +++ b/esphome/components/daly_hkms_bms/text_sensor.py @@ -0,0 +1,34 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import text_sensor +from esphome.const import CONF_STATUS +from . import DalyHkmsBmsComponent, CONF_DALY_HKMS_BMS_ID + +ICON_CAR_BATTERY = "mdi:car-battery" + +TYPES = [ + CONF_STATUS, +] + +CONFIG_SCHEMA = cv.All( + cv.Schema( + { + cv.GenerateID(CONF_DALY_HKMS_BMS_ID): cv.use_id(DalyHkmsBmsComponent), + cv.Optional(CONF_STATUS): text_sensor.text_sensor_schema( + icon=ICON_CAR_BATTERY + ), + } + ).extend(cv.COMPONENT_SCHEMA) +) + + +async def setup_conf(config, key, hub): + if sensor_config := config.get(key): + sens = await text_sensor.new_text_sensor(sensor_config) + cg.add(getattr(hub, f"set_{key}_text_sensor")(sens)) + + +async def to_code(config): + hub = await cg.get_variable(config[CONF_DALY_HKMS_BMS_ID]) + for key in TYPES: + await setup_conf(config, key, hub)