mirror of
https://github.com/esphome/esphome.git
synced 2024-12-22 16:37:52 +01:00
Add support for Daly Smart BMS (#2156)
* Add support for Daly Smart BMS
* Fix clang-format and python lint
* Fix const declaration
* Add code owner
* Fix malloc with std::vector
* Fix with suggestions
* Revert "Fix with suggestions"
This reverts commit bc618f20cf
.
* Fix last commit
* Fix Python Lint
* Fix typo
* Use std::vector instead pointer and fix loop
* Fix typo
* Add test configuration to test3.yaml
* Fix test3.yaml
* Fix uart in test3.yaml
This commit is contained in:
parent
0929a0f8aa
commit
ed593544d8
@ -39,6 +39,7 @@ esphome/components/coolix/* @glmnet
|
|||||||
esphome/components/cover/* @esphome/core
|
esphome/components/cover/* @esphome/core
|
||||||
esphome/components/cs5460a/* @balrog-kun
|
esphome/components/cs5460a/* @balrog-kun
|
||||||
esphome/components/ct_clamp/* @jesserockz
|
esphome/components/ct_clamp/* @jesserockz
|
||||||
|
esphome/components/daly_bms/* @s1lvi0
|
||||||
esphome/components/debug/* @OttoWinter
|
esphome/components/debug/* @OttoWinter
|
||||||
esphome/components/dfplayer/* @glmnet
|
esphome/components/dfplayer/* @glmnet
|
||||||
esphome/components/dht/* @OttoWinter
|
esphome/components/dht/* @OttoWinter
|
||||||
|
27
esphome/components/daly_bms/__init__.py
Normal file
27
esphome/components/daly_bms/__init__.py
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import esphome.codegen as cg
|
||||||
|
import esphome.config_validation as cv
|
||||||
|
from esphome.components import uart
|
||||||
|
from esphome.const import CONF_ID
|
||||||
|
|
||||||
|
CODEOWNERS = ["@s1lvi0"]
|
||||||
|
DEPENDENCIES = ["uart"]
|
||||||
|
AUTO_LOAD = ["sensor", "text_sensor", "binary_sensor"]
|
||||||
|
|
||||||
|
CONF_BMS_DALY_ID = "bms_daly_id"
|
||||||
|
|
||||||
|
daly_bms = cg.esphome_ns.namespace("daly_bms")
|
||||||
|
DalyBmsComponent = daly_bms.class_(
|
||||||
|
"DalyBmsComponent", cg.PollingComponent, uart.UARTDevice
|
||||||
|
)
|
||||||
|
|
||||||
|
CONFIG_SCHEMA = (
|
||||||
|
cv.Schema({cv.GenerateID(): cv.declare_id(DalyBmsComponent)})
|
||||||
|
.extend(uart.UART_DEVICE_SCHEMA)
|
||||||
|
.extend(cv.polling_component_schema("30s"))
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def to_code(config):
|
||||||
|
var = cg.new_Pvariable(config[CONF_ID])
|
||||||
|
await cg.register_component(var, config)
|
||||||
|
await uart.register_uart_device(var, config)
|
49
esphome/components/daly_bms/binary_sensor.py
Normal file
49
esphome/components/daly_bms/binary_sensor.py
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
import esphome.codegen as cg
|
||||||
|
import esphome.config_validation as cv
|
||||||
|
from esphome.components import binary_sensor
|
||||||
|
from esphome.const import CONF_ID
|
||||||
|
from . import DalyBmsComponent, CONF_BMS_DALY_ID
|
||||||
|
|
||||||
|
CONF_CHARGING_MOS_ENABLED = "charging_mos_enabled"
|
||||||
|
CONF_DISCHARGING_MOS_ENABLED = "discharging_mos_enabled"
|
||||||
|
|
||||||
|
TYPES = [
|
||||||
|
CONF_CHARGING_MOS_ENABLED,
|
||||||
|
CONF_DISCHARGING_MOS_ENABLED,
|
||||||
|
]
|
||||||
|
|
||||||
|
CONFIG_SCHEMA = cv.All(
|
||||||
|
cv.Schema(
|
||||||
|
{
|
||||||
|
cv.GenerateID(CONF_BMS_DALY_ID): cv.use_id(DalyBmsComponent),
|
||||||
|
cv.Optional(
|
||||||
|
CONF_CHARGING_MOS_ENABLED
|
||||||
|
): binary_sensor.BINARY_SENSOR_SCHEMA.extend(
|
||||||
|
{
|
||||||
|
cv.GenerateID(): cv.declare_id(binary_sensor.BinarySensor),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
cv.Optional(
|
||||||
|
CONF_DISCHARGING_MOS_ENABLED
|
||||||
|
): binary_sensor.BINARY_SENSOR_SCHEMA.extend(
|
||||||
|
{
|
||||||
|
cv.GenerateID(): cv.declare_id(binary_sensor.BinarySensor),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
}
|
||||||
|
).extend(cv.COMPONENT_SCHEMA)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def setup_conf(config, key, hub):
|
||||||
|
if key in config:
|
||||||
|
conf = config[key]
|
||||||
|
sens = cg.new_Pvariable(conf[CONF_ID])
|
||||||
|
await binary_sensor.register_binary_sensor(sens, conf)
|
||||||
|
cg.add(getattr(hub, f"set_{key}_binary_sensor")(sens))
|
||||||
|
|
||||||
|
|
||||||
|
async def to_code(config):
|
||||||
|
hub = await cg.get_variable(config[CONF_BMS_DALY_ID])
|
||||||
|
for key in TYPES:
|
||||||
|
await setup_conf(config, key, hub)
|
181
esphome/components/daly_bms/daly_bms.cpp
Normal file
181
esphome/components/daly_bms/daly_bms.cpp
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
#include "daly_bms.h"
|
||||||
|
#include "esphome/core/log.h"
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace daly_bms {
|
||||||
|
|
||||||
|
static const char *const TAG = "daly_bms";
|
||||||
|
|
||||||
|
static const uint8_t DALY_FRAME_SIZE = 13;
|
||||||
|
static const uint8_t DALY_TEMPERATURE_OFFSET = 40;
|
||||||
|
static const uint16_t DALY_CURRENT_OFFSET = 30000;
|
||||||
|
|
||||||
|
static const uint8_t DALY_REQUEST_BATTERY_LEVEL = 0x90;
|
||||||
|
static const uint8_t DALY_REQUEST_MIN_MAX_VOLTAGE = 0x91;
|
||||||
|
static const uint8_t DALY_REQUEST_MIN_MAX_TEMPERATURE = 0x92;
|
||||||
|
static const uint8_t DALY_REQUEST_MOS = 0x93;
|
||||||
|
static const uint8_t DALY_REQUEST_STATUS = 0x94;
|
||||||
|
static const uint8_t DALY_REQUEST_TEMPERATURE = 0x96;
|
||||||
|
|
||||||
|
void DalyBmsComponent::setup() {}
|
||||||
|
|
||||||
|
void DalyBmsComponent::dump_config() {
|
||||||
|
ESP_LOGCONFIG(TAG, "Daly BMS:");
|
||||||
|
this->check_uart_settings(9600);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DalyBmsComponent::update() {
|
||||||
|
this->request_data(DALY_REQUEST_BATTERY_LEVEL);
|
||||||
|
this->request_data(DALY_REQUEST_MIN_MAX_VOLTAGE);
|
||||||
|
this->request_data(DALY_REQUEST_MIN_MAX_TEMPERATURE);
|
||||||
|
this->request_data(DALY_REQUEST_MOS);
|
||||||
|
this->request_data(DALY_REQUEST_STATUS);
|
||||||
|
this->request_data(DALY_REQUEST_TEMPERATURE);
|
||||||
|
|
||||||
|
std::vector<uint8_t> get_battery_level_data;
|
||||||
|
int available_data = this->available();
|
||||||
|
if (available_data >= DALY_FRAME_SIZE) {
|
||||||
|
get_battery_level_data.resize(available_data);
|
||||||
|
this->read_array(get_battery_level_data.data(), available_data);
|
||||||
|
this->decode_data(get_battery_level_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float DalyBmsComponent::get_setup_priority() const { return setup_priority::DATA; }
|
||||||
|
|
||||||
|
void DalyBmsComponent::request_data(uint8_t data_id) {
|
||||||
|
uint8_t request_message[DALY_FRAME_SIZE];
|
||||||
|
|
||||||
|
request_message[0] = 0xA5; // Start Flag
|
||||||
|
request_message[1] = 0x80; // Communication Module Address
|
||||||
|
request_message[2] = data_id; // Data ID
|
||||||
|
request_message[3] = 0x08; // Data Length (Fixed)
|
||||||
|
request_message[4] = 0x00; // Empty Data
|
||||||
|
request_message[5] = 0x00; // |
|
||||||
|
request_message[6] = 0x00; // |
|
||||||
|
request_message[7] = 0x00; // |
|
||||||
|
request_message[8] = 0x00; // |
|
||||||
|
request_message[9] = 0x00; // |
|
||||||
|
request_message[10] = 0x00; // |
|
||||||
|
request_message[11] = 0x00; // Empty Data
|
||||||
|
request_message[12] = (uint8_t)(request_message[0] + request_message[1] + request_message[2] +
|
||||||
|
request_message[3]); // Checksum (Lower byte of the other bytes sum)
|
||||||
|
|
||||||
|
this->write_array(request_message, sizeof(request_message));
|
||||||
|
this->flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DalyBmsComponent::decode_data(std::vector<uint8_t> data) {
|
||||||
|
auto it = data.begin();
|
||||||
|
|
||||||
|
while ((it = std::find(it, data.end(), 0xA5)) != data.end()) {
|
||||||
|
if (data.end() - it >= DALY_FRAME_SIZE && it[1] == 0x01) {
|
||||||
|
uint8_t checksum;
|
||||||
|
int sum = 0;
|
||||||
|
for (int i = 0; i < 12; i++) {
|
||||||
|
sum += it[i];
|
||||||
|
}
|
||||||
|
checksum = sum;
|
||||||
|
|
||||||
|
if (checksum == it[12]) {
|
||||||
|
switch (it[2]) {
|
||||||
|
case DALY_REQUEST_BATTERY_LEVEL:
|
||||||
|
if (this->voltage_sensor_) {
|
||||||
|
this->voltage_sensor_->publish_state((float) encode_uint16(it[4], it[5]) / 10);
|
||||||
|
}
|
||||||
|
if (this->current_sensor_) {
|
||||||
|
this->current_sensor_->publish_state(((float) (encode_uint16(it[8], it[9]) - DALY_CURRENT_OFFSET) / 10));
|
||||||
|
}
|
||||||
|
if (this->battery_level_sensor_) {
|
||||||
|
this->battery_level_sensor_->publish_state((float) encode_uint16(it[10], it[11]) / 10);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DALY_REQUEST_MIN_MAX_VOLTAGE:
|
||||||
|
if (this->max_cell_voltage_) {
|
||||||
|
this->max_cell_voltage_->publish_state((float) encode_uint16(it[4], it[5]) / 1000);
|
||||||
|
}
|
||||||
|
if (this->max_cell_voltage_number_) {
|
||||||
|
this->max_cell_voltage_number_->publish_state(it[6]);
|
||||||
|
}
|
||||||
|
if (this->min_cell_voltage_) {
|
||||||
|
this->min_cell_voltage_->publish_state((float) encode_uint16(it[7], it[8]) / 1000);
|
||||||
|
}
|
||||||
|
if (this->min_cell_voltage_number_) {
|
||||||
|
this->min_cell_voltage_number_->publish_state(it[9]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DALY_REQUEST_MIN_MAX_TEMPERATURE:
|
||||||
|
if (this->max_temperature_) {
|
||||||
|
this->max_temperature_->publish_state(it[4] - DALY_TEMPERATURE_OFFSET);
|
||||||
|
}
|
||||||
|
if (this->max_temperature_probe_number_) {
|
||||||
|
this->max_temperature_probe_number_->publish_state(it[5]);
|
||||||
|
}
|
||||||
|
if (this->min_temperature_) {
|
||||||
|
this->min_temperature_->publish_state(it[6] - DALY_TEMPERATURE_OFFSET);
|
||||||
|
}
|
||||||
|
if (this->min_temperature_probe_number_) {
|
||||||
|
this->min_temperature_probe_number_->publish_state(it[7]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DALY_REQUEST_MOS:
|
||||||
|
if (this->status_text_sensor_ != nullptr) {
|
||||||
|
switch (it[4]) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this->charging_mos_enabled_) {
|
||||||
|
this->charging_mos_enabled_->publish_state(it[5]);
|
||||||
|
}
|
||||||
|
if (this->discharging_mos_enabled_) {
|
||||||
|
this->discharging_mos_enabled_->publish_state(it[6]);
|
||||||
|
}
|
||||||
|
if (this->remaining_capacity_) {
|
||||||
|
this->remaining_capacity_->publish_state((float) encode_uint32(it[8], it[9], it[10], it[11]) / 1000);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DALY_REQUEST_STATUS:
|
||||||
|
if (this->cells_number_) {
|
||||||
|
this->cells_number_->publish_state(it[4]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DALY_REQUEST_TEMPERATURE:
|
||||||
|
if (it[4] == 1) {
|
||||||
|
if (this->temperature_1_sensor_) {
|
||||||
|
this->temperature_1_sensor_->publish_state(it[5] - DALY_TEMPERATURE_OFFSET);
|
||||||
|
}
|
||||||
|
if (this->temperature_2_sensor_) {
|
||||||
|
this->temperature_2_sensor_->publish_state(it[6] - DALY_TEMPERATURE_OFFSET);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::advance(it, DALY_FRAME_SIZE);
|
||||||
|
} else {
|
||||||
|
std::advance(it, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace daly_bms
|
||||||
|
} // namespace esphome
|
83
esphome/components/daly_bms/daly_bms.h
Normal file
83
esphome/components/daly_bms/daly_bms.h
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "esphome/core/component.h"
|
||||||
|
#include "esphome/components/sensor/sensor.h"
|
||||||
|
#include "esphome/components/text_sensor/text_sensor.h"
|
||||||
|
#include "esphome/components/binary_sensor/binary_sensor.h"
|
||||||
|
#include "esphome/components/uart/uart.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace daly_bms {
|
||||||
|
|
||||||
|
class DalyBmsComponent : public PollingComponent, public uart::UARTDevice {
|
||||||
|
public:
|
||||||
|
DalyBmsComponent() = default;
|
||||||
|
|
||||||
|
// SENSORS
|
||||||
|
void set_voltage_sensor(sensor::Sensor *voltage_sensor) { voltage_sensor_ = voltage_sensor; }
|
||||||
|
void set_current_sensor(sensor::Sensor *current_sensor) { current_sensor_ = current_sensor; }
|
||||||
|
void set_battery_level_sensor(sensor::Sensor *battery_level_sensor) { battery_level_sensor_ = battery_level_sensor; }
|
||||||
|
void set_max_cell_voltage_sensor(sensor::Sensor *max_cell_voltage) { max_cell_voltage_ = max_cell_voltage; }
|
||||||
|
void set_max_cell_voltage_number_sensor(sensor::Sensor *max_cell_voltage_number) {
|
||||||
|
max_cell_voltage_number_ = max_cell_voltage_number;
|
||||||
|
}
|
||||||
|
void set_min_cell_voltage_sensor(sensor::Sensor *min_cell_voltage) { min_cell_voltage_ = min_cell_voltage; }
|
||||||
|
void set_min_cell_voltage_number_sensor(sensor::Sensor *min_cell_voltage_number) {
|
||||||
|
min_cell_voltage_number_ = min_cell_voltage_number;
|
||||||
|
}
|
||||||
|
void set_max_temperature_sensor(sensor::Sensor *max_temperature) { max_temperature_ = max_temperature; }
|
||||||
|
void set_max_temperature_probe_number_sensor(sensor::Sensor *max_temperature_probe_number) {
|
||||||
|
max_temperature_probe_number_ = max_temperature_probe_number;
|
||||||
|
}
|
||||||
|
void set_min_temperature_sensor(sensor::Sensor *min_temperature) { min_temperature_ = min_temperature; }
|
||||||
|
void set_min_temperature_probe_number_sensor(sensor::Sensor *min_temperature_probe_number) {
|
||||||
|
min_temperature_probe_number_ = min_temperature_probe_number;
|
||||||
|
}
|
||||||
|
void set_remaining_capacity_sensor(sensor::Sensor *remaining_capacity) { remaining_capacity_ = remaining_capacity; }
|
||||||
|
void set_cells_number_sensor(sensor::Sensor *cells_number) { cells_number_ = cells_number; }
|
||||||
|
void set_temperature_1_sensor(sensor::Sensor *temperature_1_sensor) { temperature_1_sensor_ = temperature_1_sensor; }
|
||||||
|
void set_temperature_2_sensor(sensor::Sensor *temperature_2_sensor) { temperature_2_sensor_ = temperature_2_sensor; }
|
||||||
|
// TEXT_SENSORS
|
||||||
|
void set_status_text_sensor(text_sensor::TextSensor *status_text_sensor) { status_text_sensor_ = status_text_sensor; }
|
||||||
|
// BINARY_SENSORS
|
||||||
|
void set_charging_mos_enabled_binary_sensor(binary_sensor::BinarySensor *charging_mos_enabled) {
|
||||||
|
charging_mos_enabled_ = charging_mos_enabled;
|
||||||
|
}
|
||||||
|
void set_discharging_mos_enabled_binary_sensor(binary_sensor::BinarySensor *discharging_mos_enabled) {
|
||||||
|
discharging_mos_enabled_ = discharging_mos_enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup() override;
|
||||||
|
void dump_config() override;
|
||||||
|
void update() override;
|
||||||
|
|
||||||
|
float get_setup_priority() const override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void request_data(uint8_t data_id);
|
||||||
|
void decode_data(std::vector<uint8_t> data);
|
||||||
|
|
||||||
|
sensor::Sensor *voltage_sensor_{nullptr};
|
||||||
|
sensor::Sensor *current_sensor_{nullptr};
|
||||||
|
sensor::Sensor *battery_level_sensor_{nullptr};
|
||||||
|
sensor::Sensor *max_cell_voltage_{nullptr};
|
||||||
|
sensor::Sensor *max_cell_voltage_number_{nullptr};
|
||||||
|
sensor::Sensor *min_cell_voltage_{nullptr};
|
||||||
|
sensor::Sensor *min_cell_voltage_number_{nullptr};
|
||||||
|
sensor::Sensor *max_temperature_{nullptr};
|
||||||
|
sensor::Sensor *max_temperature_probe_number_{nullptr};
|
||||||
|
sensor::Sensor *min_temperature_{nullptr};
|
||||||
|
sensor::Sensor *min_temperature_probe_number_{nullptr};
|
||||||
|
sensor::Sensor *remaining_capacity_{nullptr};
|
||||||
|
sensor::Sensor *cells_number_{nullptr};
|
||||||
|
sensor::Sensor *temperature_1_sensor_{nullptr};
|
||||||
|
sensor::Sensor *temperature_2_sensor_{nullptr};
|
||||||
|
|
||||||
|
text_sensor::TextSensor *status_text_sensor_{nullptr};
|
||||||
|
|
||||||
|
binary_sensor::BinarySensor *charging_mos_enabled_{nullptr};
|
||||||
|
binary_sensor::BinarySensor *discharging_mos_enabled_{nullptr};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace daly_bms
|
||||||
|
} // namespace esphome
|
192
esphome/components/daly_bms/sensor.py
Normal file
192
esphome/components/daly_bms/sensor.py
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
import esphome.codegen as cg
|
||||||
|
import esphome.config_validation as cv
|
||||||
|
from esphome.components import sensor
|
||||||
|
from esphome.const import (
|
||||||
|
CONF_VOLTAGE,
|
||||||
|
CONF_CURRENT,
|
||||||
|
CONF_BATTERY_LEVEL,
|
||||||
|
CONF_MAX_TEMPERATURE,
|
||||||
|
CONF_MIN_TEMPERATURE,
|
||||||
|
DEVICE_CLASS_VOLTAGE,
|
||||||
|
DEVICE_CLASS_CURRENT,
|
||||||
|
DEVICE_CLASS_BATTERY,
|
||||||
|
DEVICE_CLASS_TEMPERATURE,
|
||||||
|
DEVICE_CLASS_EMPTY,
|
||||||
|
STATE_CLASS_MEASUREMENT,
|
||||||
|
STATE_CLASS_NONE,
|
||||||
|
UNIT_VOLT,
|
||||||
|
UNIT_AMPERE,
|
||||||
|
UNIT_PERCENT,
|
||||||
|
UNIT_CELSIUS,
|
||||||
|
UNIT_EMPTY,
|
||||||
|
ICON_FLASH,
|
||||||
|
ICON_PERCENT,
|
||||||
|
ICON_COUNTER,
|
||||||
|
ICON_THERMOMETER,
|
||||||
|
ICON_GAUGE,
|
||||||
|
)
|
||||||
|
from . import DalyBmsComponent, CONF_BMS_DALY_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_REMAINING_CAPACITY = "remaining_capacity"
|
||||||
|
CONF_TEMPERATURE_1 = "temperature_1"
|
||||||
|
CONF_TEMPERATURE_2 = "temperature_2"
|
||||||
|
|
||||||
|
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_REMAINING_CAPACITY,
|
||||||
|
CONF_TEMPERATURE_1,
|
||||||
|
CONF_TEMPERATURE_2,
|
||||||
|
]
|
||||||
|
|
||||||
|
CONFIG_SCHEMA = cv.All(
|
||||||
|
cv.Schema(
|
||||||
|
{
|
||||||
|
cv.GenerateID(CONF_BMS_DALY_ID): cv.use_id(DalyBmsComponent),
|
||||||
|
cv.Optional(CONF_VOLTAGE): sensor.sensor_schema(
|
||||||
|
UNIT_VOLT,
|
||||||
|
ICON_FLASH,
|
||||||
|
1,
|
||||||
|
DEVICE_CLASS_VOLTAGE,
|
||||||
|
STATE_CLASS_MEASUREMENT,
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_CURRENT): sensor.sensor_schema(
|
||||||
|
UNIT_AMPERE,
|
||||||
|
ICON_CURRENT_DC,
|
||||||
|
1,
|
||||||
|
DEVICE_CLASS_CURRENT,
|
||||||
|
STATE_CLASS_MEASUREMENT,
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_BATTERY_LEVEL): sensor.sensor_schema(
|
||||||
|
UNIT_PERCENT,
|
||||||
|
ICON_PERCENT,
|
||||||
|
1,
|
||||||
|
DEVICE_CLASS_BATTERY,
|
||||||
|
STATE_CLASS_MEASUREMENT,
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_MAX_CELL_VOLTAGE): sensor.sensor_schema(
|
||||||
|
UNIT_VOLT,
|
||||||
|
ICON_FLASH,
|
||||||
|
2,
|
||||||
|
DEVICE_CLASS_VOLTAGE,
|
||||||
|
STATE_CLASS_MEASUREMENT,
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_MAX_CELL_VOLTAGE_NUMBER): sensor.sensor_schema(
|
||||||
|
UNIT_EMPTY,
|
||||||
|
ICON_COUNTER,
|
||||||
|
0,
|
||||||
|
DEVICE_CLASS_EMPTY,
|
||||||
|
STATE_CLASS_NONE,
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_MIN_CELL_VOLTAGE): sensor.sensor_schema(
|
||||||
|
UNIT_VOLT,
|
||||||
|
ICON_FLASH,
|
||||||
|
2,
|
||||||
|
DEVICE_CLASS_VOLTAGE,
|
||||||
|
STATE_CLASS_MEASUREMENT,
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_MIN_CELL_VOLTAGE_NUMBER): sensor.sensor_schema(
|
||||||
|
UNIT_EMPTY,
|
||||||
|
ICON_COUNTER,
|
||||||
|
0,
|
||||||
|
DEVICE_CLASS_EMPTY,
|
||||||
|
STATE_CLASS_NONE,
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_MAX_TEMPERATURE): sensor.sensor_schema(
|
||||||
|
UNIT_CELSIUS,
|
||||||
|
ICON_THERMOMETER_CHEVRON_UP,
|
||||||
|
0,
|
||||||
|
DEVICE_CLASS_TEMPERATURE,
|
||||||
|
STATE_CLASS_MEASUREMENT,
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_MAX_TEMPERATURE_PROBE_NUMBER): sensor.sensor_schema(
|
||||||
|
UNIT_EMPTY,
|
||||||
|
ICON_COUNTER,
|
||||||
|
0,
|
||||||
|
DEVICE_CLASS_EMPTY,
|
||||||
|
STATE_CLASS_NONE,
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_MIN_TEMPERATURE): sensor.sensor_schema(
|
||||||
|
UNIT_CELSIUS,
|
||||||
|
ICON_THERMOMETER_CHEVRON_DOWN,
|
||||||
|
0,
|
||||||
|
DEVICE_CLASS_TEMPERATURE,
|
||||||
|
STATE_CLASS_MEASUREMENT,
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_MIN_TEMPERATURE_PROBE_NUMBER): sensor.sensor_schema(
|
||||||
|
UNIT_EMPTY,
|
||||||
|
ICON_COUNTER,
|
||||||
|
0,
|
||||||
|
DEVICE_CLASS_EMPTY,
|
||||||
|
STATE_CLASS_NONE,
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_REMAINING_CAPACITY): sensor.sensor_schema(
|
||||||
|
UNIT_AMPERE_HOUR,
|
||||||
|
ICON_GAUGE,
|
||||||
|
2,
|
||||||
|
DEVICE_CLASS_VOLTAGE,
|
||||||
|
STATE_CLASS_MEASUREMENT,
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_CELLS_NUMBER): sensor.sensor_schema(
|
||||||
|
UNIT_EMPTY,
|
||||||
|
ICON_COUNTER,
|
||||||
|
0,
|
||||||
|
DEVICE_CLASS_EMPTY,
|
||||||
|
STATE_CLASS_NONE,
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_TEMPERATURE_1): sensor.sensor_schema(
|
||||||
|
UNIT_CELSIUS,
|
||||||
|
ICON_THERMOMETER,
|
||||||
|
0,
|
||||||
|
DEVICE_CLASS_TEMPERATURE,
|
||||||
|
STATE_CLASS_MEASUREMENT,
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_TEMPERATURE_2): sensor.sensor_schema(
|
||||||
|
UNIT_CELSIUS,
|
||||||
|
ICON_THERMOMETER,
|
||||||
|
0,
|
||||||
|
DEVICE_CLASS_TEMPERATURE,
|
||||||
|
STATE_CLASS_MEASUREMENT,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
).extend(cv.COMPONENT_SCHEMA)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def setup_conf(config, key, hub):
|
||||||
|
if key in config:
|
||||||
|
conf = config[key]
|
||||||
|
sens = await sensor.new_sensor(conf)
|
||||||
|
cg.add(getattr(hub, f"set_{key}_sensor")(sens))
|
||||||
|
|
||||||
|
|
||||||
|
async def to_code(config):
|
||||||
|
hub = await cg.get_variable(config[CONF_BMS_DALY_ID])
|
||||||
|
for key in TYPES:
|
||||||
|
await setup_conf(config, key, hub)
|
39
esphome/components/daly_bms/text_sensor.py
Normal file
39
esphome/components/daly_bms/text_sensor.py
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import esphome.codegen as cg
|
||||||
|
import esphome.config_validation as cv
|
||||||
|
from esphome.components import text_sensor
|
||||||
|
from esphome.const import CONF_ICON, CONF_ID, CONF_STATUS
|
||||||
|
from . import DalyBmsComponent, CONF_BMS_DALY_ID
|
||||||
|
|
||||||
|
ICON_CAR_BATTERY = "mdi:car-battery"
|
||||||
|
|
||||||
|
TYPES = [
|
||||||
|
CONF_STATUS,
|
||||||
|
]
|
||||||
|
|
||||||
|
CONFIG_SCHEMA = cv.All(
|
||||||
|
cv.Schema(
|
||||||
|
{
|
||||||
|
cv.GenerateID(CONF_BMS_DALY_ID): cv.use_id(DalyBmsComponent),
|
||||||
|
cv.Optional(CONF_STATUS): text_sensor.TEXT_SENSOR_SCHEMA.extend(
|
||||||
|
{
|
||||||
|
cv.GenerateID(): cv.declare_id(text_sensor.TextSensor),
|
||||||
|
cv.Optional(CONF_ICON, default=ICON_CAR_BATTERY): cv.icon,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
}
|
||||||
|
).extend(cv.COMPONENT_SCHEMA)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def setup_conf(config, key, hub):
|
||||||
|
if key in config:
|
||||||
|
conf = config[key]
|
||||||
|
sens = cg.new_Pvariable(conf[CONF_ID])
|
||||||
|
await text_sensor.register_text_sensor(sens, conf)
|
||||||
|
cg.add(getattr(hub, f"set_{key}_text_sensor")(sens))
|
||||||
|
|
||||||
|
|
||||||
|
async def to_code(config):
|
||||||
|
hub = await cg.get_variable(config[CONF_BMS_DALY_ID])
|
||||||
|
for key in TYPES:
|
||||||
|
await setup_conf(config, key, hub)
|
@ -273,6 +273,37 @@ adalight:
|
|||||||
|
|
||||||
|
|
||||||
sensor:
|
sensor:
|
||||||
|
- platform: daly_bms
|
||||||
|
voltage:
|
||||||
|
name: "Battery Voltage"
|
||||||
|
current:
|
||||||
|
name: "Battery Current"
|
||||||
|
battery_level:
|
||||||
|
name: "Battery Level"
|
||||||
|
max_cell_voltage:
|
||||||
|
name: "Max Cell Voltage"
|
||||||
|
max_cell_voltage_number:
|
||||||
|
name: "Max Cell Voltage Number"
|
||||||
|
min_cell_voltage:
|
||||||
|
name: "Min Cell Voltage"
|
||||||
|
min_cell_voltage_number:
|
||||||
|
name: "Min Cell Voltage Number"
|
||||||
|
max_temperature:
|
||||||
|
name: "Max Temperature"
|
||||||
|
max_temperature_probe_number:
|
||||||
|
name: "Max Temperature Probe Number"
|
||||||
|
min_temperature:
|
||||||
|
name: "Min Temperature"
|
||||||
|
min_temperature_probe_number:
|
||||||
|
name: "Min Temperature Probe Number"
|
||||||
|
remaining_capacity:
|
||||||
|
name: "Remaining Capacity"
|
||||||
|
cells_number:
|
||||||
|
name: "Cells Number"
|
||||||
|
temperature_1:
|
||||||
|
name: "Temperature 1"
|
||||||
|
temperature_2:
|
||||||
|
name: "Temperature 2"
|
||||||
- platform: apds9960
|
- platform: apds9960
|
||||||
type: proximity
|
type: proximity
|
||||||
name: APDS9960 Proximity
|
name: APDS9960 Proximity
|
||||||
@ -621,6 +652,11 @@ mpr121:
|
|||||||
address: 0x5A
|
address: 0x5A
|
||||||
|
|
||||||
binary_sensor:
|
binary_sensor:
|
||||||
|
- platform: daly_bms
|
||||||
|
charging_mos_enabled:
|
||||||
|
name: "Charging MOS"
|
||||||
|
discharging_mos_enabled:
|
||||||
|
name: "Discharging MOS"
|
||||||
- platform: apds9960
|
- platform: apds9960
|
||||||
direction: up
|
direction: up
|
||||||
name: APDS9960 Up
|
name: APDS9960 Up
|
||||||
@ -701,6 +737,9 @@ status_led:
|
|||||||
pin: GPIO2
|
pin: GPIO2
|
||||||
|
|
||||||
text_sensor:
|
text_sensor:
|
||||||
|
- platform: daly_bms
|
||||||
|
status:
|
||||||
|
name: "BMS Status"
|
||||||
- platform: version
|
- platform: version
|
||||||
name: 'ESPHome Version'
|
name: 'ESPHome Version'
|
||||||
icon: mdi:icon
|
icon: mdi:icon
|
||||||
@ -1219,3 +1258,8 @@ fingerprint_grow:
|
|||||||
dsmr:
|
dsmr:
|
||||||
decryption_key: 00112233445566778899aabbccddeeff
|
decryption_key: 00112233445566778899aabbccddeeff
|
||||||
uart_id: uart6
|
uart_id: uart6
|
||||||
|
|
||||||
|
daly_bms:
|
||||||
|
update_interval: 20s
|
||||||
|
uart_id: uart1
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user