Home Assistant Git Exporter

This commit is contained in:
root
2024-05-31 13:07:35 +02:00
parent 64a0536537
commit 60abdd866c
275 changed files with 71113 additions and 1 deletions
@@ -0,0 +1,70 @@
from abc import ABC, abstractmethod
from enum import StrEnum
from homeassistant.components.number import NumberEntity
from homeassistant.components.select import SelectEntity
from homeassistant.components.sensor import SensorEntity
from homeassistant.components.switch import SwitchEntity
from homeassistant.components.button import ButtonEntity
from homeassistant.const import Platform
from ..mqtt.ecoflow_mqtt import EcoflowMQTTClient
class MigrationAction(StrEnum):
REMOVE = "remove"
class EntityMigration:
def __init__(self, key: str, domain: Platform, action: MigrationAction, **kwargs):
self.key = key
self.domain = domain
self.action = action
self.args = kwargs
class BaseDevice(ABC):
def charging_power_step(self) -> int:
return 100
@abstractmethod
def sensors(self, client: EcoflowMQTTClient) -> list[SensorEntity]:
pass
@abstractmethod
def numbers(self, client: EcoflowMQTTClient) -> list[NumberEntity]:
pass
@abstractmethod
def switches(self, client: EcoflowMQTTClient) -> list[SwitchEntity]:
pass
@abstractmethod
def selects(self, client: EcoflowMQTTClient) -> list[SelectEntity]:
pass
def buttons(self, client: EcoflowMQTTClient) -> list[ButtonEntity]:
return []
def migrate(self, version) -> list[EntityMigration]:
return []
class DiagnosticDevice(BaseDevice):
def sensors(self, client: EcoflowMQTTClient) -> list[SensorEntity]:
return []
def numbers(self, client: EcoflowMQTTClient) -> list[NumberEntity]:
return []
def switches(self, client: EcoflowMQTTClient) -> list[SwitchEntity]:
return []
def buttons(self, client: EcoflowMQTTClient) -> list[ButtonEntity]:
return []
def selects(self, client: EcoflowMQTTClient) -> list[SelectEntity]:
return []
@@ -0,0 +1,255 @@
DC_MODE_OPTIONS = {
"Auto": 0,
"Solar Recharging": 1,
"Car Recharging": 2,
}
DC_ICONS = {
"Auto": None,
"MPPT": "mdi:solar-power",
"DC": "mdi:current-dc",
}
SCREEN_TIMEOUT_OPTIONS = {
"Never": 0,
"10 sec": 10,
"30 sec": 30,
"1 min": 60,
"5 min": 300,
"30 min": 1800,
}
UNIT_TIMEOUT_OPTIONS = {
"Never": 0,
"30 min": 30,
"1 hr": 60,
"2 hr": 120,
"4 hr": 240,
"6 hr": 360,
"12 hr": 720,
"24 hr": 1440
}
UNIT_TIMEOUT_OPTIONS_LIMITED = {
"Never": 0,
"30 min": 30,
"1 hr": 60,
"2 hr": 120,
"6 hr": 360,
"12 hr": 720
}
AC_TIMEOUT_OPTIONS = {
"Never": 0,
"30 min": 30,
"1 hr": 60,
"2 hr": 120,
"4 hr": 240,
"6 hr": 360,
"12 hr": 720,
"24 hr": 1440,
}
AC_TIMEOUT_OPTIONS_LIMITED = {
"Never": 0,
"2 hr": 120,
"4 hr": 240,
"6 hr": 360,
"12 hr": 720,
"24 hr": 1440,
}
DC_TIMEOUT_OPTIONS = {
"Never": 0,
"30 min": 30,
"1 hr": 60,
"2 hr": 120,
"4 hr": 240,
"6 hr": 360,
"12 hr": 720,
"24 hr": 1440,
}
DC_TIMEOUT_OPTIONS_LIMITED = {
"Never": 0,
"2 hr": 120,
"4 hr": 240,
"6 hr": 360,
"12 hr": 720,
"24 hr": 1440,
}
DC_CHARGE_CURRENT_OPTIONS = {
"4A": 4000,
"6A": 6000,
"8A": 8000
}
MAIN_MODE_OPTIONS = {
"Cool": 0,
"Heat": 1,
"Fan": 2
}
FAN_MODE_OPTIONS = {
"Low": 0,
"Medium": 1,
"High": 2
}
REMOTE_MODE_OPTIONS = {
"Startup": 1,
"Standby": 2,
"Shutdown": 3
}
POWER_SUB_MODE_OPTIONS = {
"Max": 0,
"Sleep": 1,
"Eco": 2,
"Manual": 3
}
COMBINED_BATTERY_LEVEL = "Battery Level"
COMBINED_BATTERY_LEVEL_F32 = "Battery Level (Precise)"
BATTERY_CHARGING_STATE = "Battery Charging State"
ATTR_DESIGN_CAPACITY = "Design Capacity (mAh)"
ATTR_FULL_CAPACITY = "Full Capacity (mAh)"
ATTR_REMAIN_CAPACITY = "Remain Capacity (mAh)"
MAIN_DESIGN_CAPACITY = "Main Design Capacity"
MAIN_FULL_CAPACITY = "Main Full Capacity"
MAIN_REMAIN_CAPACITY = "Main Remain Capacity"
SLAVE_DESIGN_CAPACITY = "Slave Design Capacity"
SLAVE_FULL_CAPACITY = "Slave Full Capacity"
SLAVE_REMAIN_CAPACITY = "Slave Remain Capacity"
SLAVE_N_DESIGN_CAPACITY = "Slave %i Design Capacity"
SLAVE_N_FULL_CAPACITY = "Slave %i Full Capacity"
SLAVE_N_REMAIN_CAPACITY = "Slave %i Remain Capacity"
MAIN_BATTERY_LEVEL = "Main Battery Level"
MAIN_BATTERY_LEVEL_F32 = "Main Battery Level (Precise)"
MAIN_BATTERY_CURRENT = "Main Battery Current"
TOTAL_IN_POWER = "Total In Power"
SOLAR_IN_POWER = "Solar In Power"
SOLAR_1_IN_POWER = "Solar (1) In Power"
SOLAR_2_IN_POWER = "Solar (2) In Power"
AC_IN_POWER = "AC In Power"
AC_IN_VOLT = "AC In Volts"
AC_OUT_VOLT = "AC Out Volts"
TYPE_C_IN_POWER = "Type-C In Power"
SOLAR_IN_CURRENT = "Solar In Current"
SOLAR_IN_VOLTAGE = "Solar In Voltage"
SOLAR_IN_ENERGY = "Solar In Energy"
CHARGE_AC_ENERGY = "Battery Charge Energy from AC"
CHARGE_DC_ENERGY = "Battery Charge Energy from DC"
DISCHARGE_AC_ENERGY = "Battery Discharge Energy to AC"
DISCHARGE_DC_ENERGY = "Battery Discharge Energy to DC"
TOTAL_OUT_POWER = "Total Out Power"
AC_OUT_POWER = "AC Out Power"
DC_OUT_POWER = "DC Out Power"
DC_OUT_VOLTAGE = "DC Out Voltage"
DC_CAR_OUT_POWER = "DC Car Out Power"
DC_ANDERSON_OUT_POWER = "DC Anderson Out Power"
TYPEC_OUT_POWER = "Type-C Out Power"
TYPEC_1_OUT_POWER = "Type-C (1) Out Power"
TYPEC_2_OUT_POWER = "Type-C (2) Out Power"
USB_OUT_POWER = "USB Out Power"
USB_1_OUT_POWER = "USB (1) Out Power"
USB_2_OUT_POWER = "USB (2) Out Power"
USB_3_OUT_POWER = "USB (3) Out Power"
USB_QC_1_OUT_POWER = "USB QC (1) Out Power"
USB_QC_2_OUT_POWER = "USB QC (2) Out Power"
REMAINING_TIME = "Remaining Time"
CHARGE_REMAINING_TIME = "Charge Remaining Time"
DISCHARGE_REMAINING_TIME = "Discharge Remaining Time"
CYCLES = "Cycles"
SOH = "State of Health"
SLAVE_BATTERY_LEVEL = "Slave Battery Level"
SLAVE_N_BATTERY_LEVEL = "Slave %i Battery Level"
SLAVE_N_BATTERY_LEVEL_F32 = "Slave %i Battery Level (Precise)"
SLAVE_BATTERY_TEMP = "Slave Battery Temperature"
SLAVE_N_BATTERY_TEMP = "Slave %i Battery Temperature"
SLAVE_MIN_CELL_TEMP = "Slave Min Cell Temperature"
SLAVE_MAX_CELL_TEMP = "Slave Max Cell Temperature"
SLAVE_N_MIN_CELL_TEMP = "Slave %i Min Cell Temperature"
SLAVE_N_MAX_CELL_TEMP = "Slave %i Max Cell Temperature"
SLAVE_CYCLES = "Slave Cycles"
SLAVE_N_CYCLES = "Slave %i Cycles"
SLAVE_SOH = "Slave State of Health"
SLAVE_N_SOH = "Slave %i State of Health"
SLAVE_IN_POWER = "Slave In Power"
SLAVE_N_IN_POWER = "Slave %i In Power"
SLAVE_OUT_POWER = "Slave Out Power"
SLAVE_N_OUT_POWER = "Slave %i Out Power"
SLAVE_BATTERY_VOLT = "Slave Battery Volts"
SLAVE_MIN_CELL_VOLT = "Slave Min Cell Volts"
SLAVE_MAX_CELL_VOLT = "Slave Max Cell Volts"
SLAVE_N_BATTERY_VOLT = "Slave %i Battery Volts"
SLAVE_N_MIN_CELL_VOLT = "Slave %i Min Cell Volts"
SLAVE_N_MAX_CELL_VOLT = "Slave %i Max Cell Volts"
SLAVE_N_BATTERY_CURRENT = "Slave %i Battery Current"
MAX_CHARGE_LEVEL = "Max Charge Level"
MIN_DISCHARGE_LEVEL = "Min Discharge Level"
BACKUP_RESERVE_LEVEL = "Backup Reserve Level"
AC_CHARGING_POWER = "AC Charging Power"
SCREEN_TIMEOUT = "Screen Timeout"
UNIT_TIMEOUT = "Unit Timeout"
AC_TIMEOUT = "AC Timeout"
DC_TIMEOUT = "DC (12V) Timeout"
DC_CHARGE_CURRENT = "DC (12V) Charge Current"
GEN_AUTO_START_LEVEL = "Generator Auto Start Level"
GEN_AUTO_STOP_LEVEL = "Generator Auto Stop Level"
BEEPER = "Beeper"
USB_ENABLED = "USB Enabled"
AC_ENABLED = "AC Enabled"
DC_ENABLED = "DC (12V) Enabled"
XBOOST_ENABLED = "X-Boost Enabled"
AC_ALWAYS_ENABLED = "AC Always On"
PV_PRIO = "Prio Solar Charging"
BP_ENABLED = "Backup Reserve Enabled"
AUTO_FAN_SPEED = "Auto Fan Speed"
AC_SLOW_CHARGE = "AC Slow Charging"
DC_MODE = "DC Mode"
BATTERY_TEMP = "Battery Temperature"
MIN_CELL_TEMP = "Min Cell Temperature"
MAX_CELL_TEMP = "Max Cell Temperature"
INV_IN_TEMP = "Inverter Inside Temperature"
INV_OUT_TEMP = "Inverter Outside Temperature"
DC_CAR_OUT_TEMP = "DC Temperature"
USB_C_TEMP = "USB C Temperature"
ATTR_MIN_CELL_TEMP = MIN_CELL_TEMP
ATTR_MAX_CELL_TEMP = MAX_CELL_TEMP
BATTERY_VOLT = "Battery Volts"
MIN_CELL_VOLT = "Min Cell Volts"
MAX_CELL_VOLT = "Max Cell Volts"
ATTR_MIN_CELL_VOLT = MIN_CELL_VOLT
ATTR_MAX_CELL_VOLT = MAX_CELL_VOLT
BATTERY_AMP = "Battery Current"
SLAVE_BATTERY_AMP = "Slave Battery Current"
FAN_MODE = "Wind speed"
MAIN_MODE = "Main mode"
REMOTE_MODE = "Remote startup/shutdown"
POWER_SUB_MODE = "Sub-mode"
@@ -0,0 +1,200 @@
from homeassistant.const import Platform
from . import const, BaseDevice, EntityMigration, MigrationAction
from .. import EcoflowMQTTClient
from ..entities import BaseSensorEntity, BaseNumberEntity, BaseSwitchEntity, BaseSelectEntity
from ..number import ChargingPowerEntity, MinBatteryLevelEntity, MaxBatteryLevelEntity, \
MaxGenStopLevelEntity, MinGenStartLevelEntity, BatteryBackupLevel
from ..select import DictSelectEntity, TimeoutDictSelectEntity
from ..sensor import LevelSensorEntity, RemainSensorEntity, TempSensorEntity, CyclesSensorEntity, \
InWattsSensorEntity, OutWattsSensorEntity, QuotasStatusSensorEntity, MilliVoltSensorEntity, InMilliVoltSensorEntity, \
OutMilliVoltSensorEntity, CapacitySensorEntity
from ..switch import BeeperEntity, EnabledEntity
class Delta2(BaseDevice):
def sensors(self, client: EcoflowMQTTClient) -> list[BaseSensorEntity]:
return [
LevelSensorEntity(client, "bms_bmsStatus.soc", const.MAIN_BATTERY_LEVEL)
.attr("bms_bmsStatus.designCap", const.ATTR_DESIGN_CAPACITY, 0)
.attr("bms_bmsStatus.fullCap", const.ATTR_FULL_CAPACITY, 0)
.attr("bms_bmsStatus.remainCap", const.ATTR_REMAIN_CAPACITY, 0),
CapacitySensorEntity(client, "bms_bmsStatus.designCap", const.MAIN_DESIGN_CAPACITY, False),
CapacitySensorEntity(client, "bms_bmsStatus.fullCap", const.MAIN_FULL_CAPACITY, False),
CapacitySensorEntity(client, "bms_bmsStatus.remainCap", const.MAIN_REMAIN_CAPACITY, False),
LevelSensorEntity(client, "bms_bmsStatus.soh", const.SOH),
LevelSensorEntity(client, "bms_emsStatus.lcdShowSoc", const.COMBINED_BATTERY_LEVEL),
InWattsSensorEntity(client, "pd.wattsInSum", const.TOTAL_IN_POWER),
OutWattsSensorEntity(client, "pd.wattsOutSum", const.TOTAL_OUT_POWER),
InWattsSensorEntity(client, "inv.inputWatts", const.AC_IN_POWER),
OutWattsSensorEntity(client, "inv.outputWatts", const.AC_OUT_POWER),
InMilliVoltSensorEntity(client, "inv.acInVol", const.AC_IN_VOLT),
OutMilliVoltSensorEntity(client, "inv.invOutVol", const.AC_OUT_VOLT),
InWattsSensorEntity(client, "mppt.inWatts", const.SOLAR_IN_POWER),
# OutWattsSensorEntity(client, "pd.carWatts", const.DC_OUT_POWER),
# the same value as pd.carWatts
OutWattsSensorEntity(client, "mppt.outWatts", const.DC_OUT_POWER),
OutWattsSensorEntity(client, "pd.typec1Watts", const.TYPEC_1_OUT_POWER),
OutWattsSensorEntity(client, "pd.typec2Watts", const.TYPEC_2_OUT_POWER),
OutWattsSensorEntity(client, "pd.usb1Watts", const.USB_1_OUT_POWER),
OutWattsSensorEntity(client, "pd.usb2Watts", const.USB_2_OUT_POWER),
OutWattsSensorEntity(client, "pd.qcUsb1Watts", const.USB_QC_1_OUT_POWER),
OutWattsSensorEntity(client, "pd.qcUsb2Watts", const.USB_QC_2_OUT_POWER),
RemainSensorEntity(client, "bms_emsStatus.chgRemainTime", const.CHARGE_REMAINING_TIME),
RemainSensorEntity(client, "bms_emsStatus.dsgRemainTime", const.DISCHARGE_REMAINING_TIME),
TempSensorEntity(client, "inv.outTemp", "Inv Out Temperature"),
CyclesSensorEntity(client, "bms_bmsStatus.cycles", const.CYCLES),
TempSensorEntity(client, "bms_bmsStatus.temp", const.BATTERY_TEMP)
.attr("bms_bmsStatus.minCellTemp", const.ATTR_MIN_CELL_TEMP, 0)
.attr("bms_bmsStatus.maxCellTemp", const.ATTR_MAX_CELL_TEMP, 0),
TempSensorEntity(client, "bms_bmsStatus.minCellTemp", const.MIN_CELL_TEMP, False),
TempSensorEntity(client, "bms_bmsStatus.maxCellTemp", const.MAX_CELL_TEMP, False),
MilliVoltSensorEntity(client, "bms_bmsStatus.vol", const.BATTERY_VOLT, False)
.attr("bms_bmsStatus.minCellVol", const.ATTR_MIN_CELL_VOLT, 0)
.attr("bms_bmsStatus.maxCellVol", const.ATTR_MAX_CELL_VOLT, 0),
MilliVoltSensorEntity(client, "bms_bmsStatus.minCellVol", const.MIN_CELL_VOLT, False),
MilliVoltSensorEntity(client, "bms_bmsStatus.maxCellVol", const.MAX_CELL_VOLT, False),
# Optional Slave Battery
LevelSensorEntity(client, "bms_slave.soc", const.SLAVE_BATTERY_LEVEL, False, True)
.attr("bms_slave.designCap", const.ATTR_DESIGN_CAPACITY, 0)
.attr("bms_slave.fullCap", const.ATTR_FULL_CAPACITY, 0)
.attr("bms_slave.remainCap", const.ATTR_REMAIN_CAPACITY, 0),
CapacitySensorEntity(client, "bms_slave.designCap", const.SLAVE_DESIGN_CAPACITY, False),
CapacitySensorEntity(client, "bms_slave.fullCap", const.SLAVE_FULL_CAPACITY, False),
CapacitySensorEntity(client, "bms_slave.remainCap", const.SLAVE_REMAIN_CAPACITY, False),
LevelSensorEntity(client, "bms_slave.soh", const.SLAVE_SOH),
TempSensorEntity(client, "bms_slave.temp", const.SLAVE_BATTERY_TEMP, False, True)
.attr("bms_slave.minCellTemp", const.ATTR_MIN_CELL_TEMP, 0)
.attr("bms_slave.maxCellTemp", const.ATTR_MAX_CELL_TEMP, 0),
TempSensorEntity(client, "bms_slave.minCellTemp", const.SLAVE_MIN_CELL_TEMP, False),
TempSensorEntity(client, "bms_slave.maxCellTemp", const.SLAVE_MAX_CELL_TEMP, False),
MilliVoltSensorEntity(client, "bms_slave.vol", const.SLAVE_BATTERY_VOLT, False)
.attr("bms_slave.minCellVol", const.ATTR_MIN_CELL_VOLT, 0)
.attr("bms_slave.maxCellVol", const.ATTR_MAX_CELL_VOLT, 0),
MilliVoltSensorEntity(client, "bms_slave.minCellVol", const.SLAVE_MIN_CELL_VOLT, False),
MilliVoltSensorEntity(client, "bms_slave.maxCellVol", const.SLAVE_MAX_CELL_VOLT, False),
CyclesSensorEntity(client, "bms_slave.cycles", const.SLAVE_CYCLES, False, True),
InWattsSensorEntity(client, "bms_slave.inputWatts", const.SLAVE_IN_POWER, False, True),
OutWattsSensorEntity(client, "bms_slave.outputWatts", const.SLAVE_OUT_POWER, False, True),
QuotasStatusSensorEntity(client),
]
def numbers(self, client: EcoflowMQTTClient) -> list[BaseNumberEntity]:
return [
MaxBatteryLevelEntity(client, "bms_emsStatus.maxChargeSoc", const.MAX_CHARGE_LEVEL, 50, 100,
lambda value: {"moduleType": 2, "operateType": "upsConfig",
"params": {"maxChgSoc": int(value)}}),
MinBatteryLevelEntity(client, "bms_emsStatus.minDsgSoc", const.MIN_DISCHARGE_LEVEL, 0, 30,
lambda value: {"moduleType": 2, "operateType": "dsgCfg",
"params": {"minDsgSoc": int(value)}}),
BatteryBackupLevel(client, "pd.bpPowerSoc", const.BACKUP_RESERVE_LEVEL, 5, 100,
"bms_emsStatus.minDsgSoc", "bms_emsStatus.maxChargeSoc",
lambda value: {"moduleType": 1, "operateType": "watthConfig",
"params": {"isConfig": 1, "bpPowerSoc": int(value), "minDsgSoc": 0,
"minChgSoc": 0}}),
MinGenStartLevelEntity(client, "bms_emsStatus.minOpenOilEb", const.GEN_AUTO_START_LEVEL, 0, 30,
lambda value: {"moduleType": 2, "operateType": "openOilSoc",
"params": {"openOilSoc": value}}),
MaxGenStopLevelEntity(client, "bms_emsStatus.maxCloseOilEb", const.GEN_AUTO_STOP_LEVEL, 50, 100,
lambda value: {"moduleType": 2, "operateType": "closeOilSoc",
"params": {"closeOilSoc": value}}),
ChargingPowerEntity(client, "mppt.cfgChgWatts", const.AC_CHARGING_POWER, 200, 1200,
lambda value: {"moduleType": 5, "operateType": "acChgCfg",
"params": {"chgWatts": int(value), "chgPauseFlag": 255}})
]
def switches(self, client: EcoflowMQTTClient) -> list[BaseSwitchEntity]:
return [
BeeperEntity(client, "mppt.beepState", const.BEEPER,
lambda value: {"moduleType": 5, "operateType": "quietMode", "params": {"enabled": value}}),
EnabledEntity(client, "pd.dcOutState", const.USB_ENABLED,
lambda value: {"moduleType": 1, "operateType": "dcOutCfg", "params": {"enabled": value}}),
EnabledEntity(client, "pd.acAutoOutConfig", const.AC_ALWAYS_ENABLED,
lambda value, params: {"moduleType": 1, "operateType": "acAutoOutConfig",
"params": {"acAutoOutConfig": value,
"minAcOutSoc": int(params.get("bms_emsStatus.minDsgSoc", 0)) + 5}}),
EnabledEntity(client, "pd.pvChgPrioSet", const.PV_PRIO,
lambda value: {"moduleType": 1, "operateType": "pvChangePrio",
"params": {"pvChangeSet": value}}),
EnabledEntity(client, "mppt.cfgAcEnabled", const.AC_ENABLED,
lambda value: {"moduleType": 5, "operateType": "acOutCfg",
"params": {"enabled": value, "out_voltage": -1, "out_freq": 255,
"xboost": 255}}),
EnabledEntity(client, "mppt.cfgAcXboost", const.XBOOST_ENABLED,
lambda value: {"moduleType": 5, "operateType": "acOutCfg",
"params": {"enabled": 255, "out_voltage": -1, "out_freq": 255,
"xboost": value}}),
EnabledEntity(client, "pd.carState", const.DC_ENABLED,
lambda value: {"moduleType": 5, "operateType": "mpptCar", "params": {"enabled": value}}),
EnabledEntity(client, "pd.bpPowerSoc", const.BP_ENABLED,
lambda value: {"moduleType": 1,
"operateType": "watthConfig",
"params": {"bpPowerSoc": value,
"minChgSoc": 0,
"isConfig": value,
"minDsgSoc": 0}}),
]
def selects(self, client: EcoflowMQTTClient) -> list[BaseSelectEntity]:
return [
DictSelectEntity(client, "mppt.dcChgCurrent", const.DC_CHARGE_CURRENT, const.DC_CHARGE_CURRENT_OPTIONS,
lambda value: {"moduleType": 5, "operateType": "dcChgCfg",
"params": {"dcChgCfg": value}}),
TimeoutDictSelectEntity(client, "pd.lcdOffSec", const.SCREEN_TIMEOUT, const.SCREEN_TIMEOUT_OPTIONS,
lambda value: {"moduleType": 1, "operateType": "lcdCfg",
"params": {"brighLevel": 255, "delayOff": value}}),
TimeoutDictSelectEntity(client, "pd.standbyMin", const.UNIT_TIMEOUT, const.UNIT_TIMEOUT_OPTIONS,
lambda value: {"moduleType": 1, "operateType": "standbyTime",
"params": {"standbyMin": value}}),
TimeoutDictSelectEntity(client, "mppt.acStandbyMins", const.AC_TIMEOUT, const.AC_TIMEOUT_OPTIONS,
lambda value: {"moduleType": 5, "operateType": "standbyTime",
"params": {"standbyMins": value}}),
TimeoutDictSelectEntity(client, "mppt.carStandbyMin", const.DC_TIMEOUT, const.DC_TIMEOUT_OPTIONS,
lambda value: {"moduleType": 5, "operateType": "carStandby",
"params": {"standbyMins": value}})
]
def migrate(self, version) -> list[EntityMigration]:
if version == 2:
return [
EntityMigration("pd.soc", Platform.SENSOR, MigrationAction.REMOVE)
]
return []
@@ -0,0 +1,229 @@
from homeassistant.const import Platform
from . import const, BaseDevice, EntityMigration, MigrationAction
from .. import EcoflowMQTTClient
from ..entities import BaseSensorEntity, BaseNumberEntity, BaseSwitchEntity, BaseSelectEntity
from ..number import ChargingPowerEntity, MinBatteryLevelEntity, MaxBatteryLevelEntity, \
MaxGenStopLevelEntity, MinGenStartLevelEntity, BatteryBackupLevel
from ..select import TimeoutDictSelectEntity
from ..sensor import LevelSensorEntity, RemainSensorEntity, TempSensorEntity, CyclesSensorEntity, \
InWattsSensorEntity, OutWattsSensorEntity, StatusSensorEntity, MilliVoltSensorEntity, \
InMilliVoltSensorEntity, OutMilliVoltSensorEntity, CapacitySensorEntity
from ..switch import BeeperEntity, EnabledEntity
class Delta2Max(BaseDevice):
def sensors(self, client: EcoflowMQTTClient) -> list[BaseSensorEntity]:
return [
LevelSensorEntity(client, "bms_bmsStatus.soc", const.MAIN_BATTERY_LEVEL)
.attr("bms_bmsStatus.designCap", const.ATTR_DESIGN_CAPACITY, 0)
.attr("bms_bmsStatus.fullCap", const.ATTR_FULL_CAPACITY, 0)
.attr("bms_bmsStatus.remainCap", const.ATTR_REMAIN_CAPACITY, 0),
CapacitySensorEntity(client, "bms_bmsStatus.designCap", const.MAIN_DESIGN_CAPACITY, False),
CapacitySensorEntity(client, "bms_bmsStatus.fullCap", const.MAIN_FULL_CAPACITY, False),
CapacitySensorEntity(client, "bms_bmsStatus.remainCap", const.MAIN_REMAIN_CAPACITY, False),
LevelSensorEntity(client, "bms_bmsStatus.soh", const.SOH),
LevelSensorEntity(client, "bms_emsStatus.lcdShowSoc", const.COMBINED_BATTERY_LEVEL),
InWattsSensorEntity(client, "pd.wattsInSum", const.TOTAL_IN_POWER),
OutWattsSensorEntity(client, "pd.wattsOutSum", const.TOTAL_OUT_POWER),
InWattsSensorEntity(client, "inv.inputWatts", const.AC_IN_POWER),
OutWattsSensorEntity(client, "inv.outputWatts", const.AC_OUT_POWER),
InMilliVoltSensorEntity(client, "inv.acInVol", const.AC_IN_VOLT),
OutMilliVoltSensorEntity(client, "inv.invOutVol", const.AC_OUT_VOLT),
InWattsSensorEntity(client, "mppt.inWatts", const.SOLAR_1_IN_POWER),
InWattsSensorEntity(client, "mppt.pv2InWatts", const.SOLAR_2_IN_POWER),
# OutWattsSensorEntity(client, "pd.carWatts", const.DC_OUT_POWER),
# the same value as pd.carWatts
OutWattsSensorEntity(client, "mppt.outWatts", const.DC_OUT_POWER),
OutWattsSensorEntity(client, "pd.typec1Watts", const.TYPEC_1_OUT_POWER),
OutWattsSensorEntity(client, "pd.typec2Watts", const.TYPEC_2_OUT_POWER),
OutWattsSensorEntity(client, "pd.usb1Watts", const.USB_1_OUT_POWER),
OutWattsSensorEntity(client, "pd.usb2Watts", const.USB_2_OUT_POWER),
OutWattsSensorEntity(client, "pd.qcUsb1Watts", const.USB_QC_1_OUT_POWER),
OutWattsSensorEntity(client, "pd.qcUsb2Watts", const.USB_QC_2_OUT_POWER),
RemainSensorEntity(client, "bms_emsStatus.chgRemainTime", const.CHARGE_REMAINING_TIME),
RemainSensorEntity(client, "bms_emsStatus.dsgRemainTime", const.DISCHARGE_REMAINING_TIME),
TempSensorEntity(client, "inv.outTemp", "Inv Out Temperature"),
CyclesSensorEntity(client, "bms_bmsStatus.cycles", const.CYCLES),
TempSensorEntity(client, "bms_bmsStatus.temp", const.BATTERY_TEMP)
.attr("bms_bmsStatus.minCellTemp", const.ATTR_MIN_CELL_TEMP, 0)
.attr("bms_bmsStatus.maxCellTemp", const.ATTR_MAX_CELL_TEMP, 0),
TempSensorEntity(client, "bms_bmsStatus.minCellTemp", const.MIN_CELL_TEMP, False),
TempSensorEntity(client, "bms_bmsStatus.maxCellTemp", const.MAX_CELL_TEMP, False),
MilliVoltSensorEntity(client, "bms_bmsStatus.vol", const.BATTERY_VOLT, False)
.attr("bms_bmsStatus.minCellVol", const.ATTR_MIN_CELL_VOLT, 0)
.attr("bms_bmsStatus.maxCellVol", const.ATTR_MAX_CELL_VOLT, 0),
MilliVoltSensorEntity(client, "bms_bmsStatus.minCellVol", const.MIN_CELL_VOLT, False),
MilliVoltSensorEntity(client, "bms_bmsStatus.maxCellVol", const.MAX_CELL_VOLT, False),
# Optional Slave 1 Battery
LevelSensorEntity(client, "bms_slave_bmsSlaveStatus_1.soc", const.SLAVE_N_BATTERY_LEVEL % 1, False, True)
.attr("bms_slave_bmsSlaveStatus_1.designCap", const.ATTR_DESIGN_CAPACITY, 0)
.attr("bms_slave_bmsSlaveStatus_1.fullCap", const.ATTR_FULL_CAPACITY, 0)
.attr("bms_slave_bmsSlaveStatus_1.remainCap", const.ATTR_REMAIN_CAPACITY, 0),
CapacitySensorEntity(client, "bms_slave_bmsSlaveStatus_1.designCap", const.SLAVE_N_DESIGN_CAPACITY % 1, False),
CapacitySensorEntity(client, "bms_slave_bmsSlaveStatus_1.fullCap", const.SLAVE_N_FULL_CAPACITY % 1, False),
CapacitySensorEntity(client, "bms_slave_bmsSlaveStatus_1.remainCap", const.SLAVE_N_REMAIN_CAPACITY % 1, False),
TempSensorEntity(client, "bms_slave_bmsSlaveStatus_1.temp", const.SLAVE_N_BATTERY_TEMP % 1, False, True)
.attr("bms_slave_bmsSlaveStatus_1.minCellTemp", const.ATTR_MIN_CELL_TEMP, 0)
.attr("bms_slave_bmsSlaveStatus_1.maxCellTemp", const.ATTR_MAX_CELL_TEMP, 0),
TempSensorEntity(client, "bms_slave_bmsSlaveStatus_1.minCellTemp", const.SLAVE_N_MIN_CELL_TEMP % 1, False),
TempSensorEntity(client, "bms_slave_bmsSlaveStatus_1.maxCellTemp", const.SLAVE_N_MAX_CELL_TEMP % 1, False),
MilliVoltSensorEntity(client, "bms_slave_bmsSlaveStatus_1.vol", const.SLAVE_N_BATTERY_VOLT % 1, False)
.attr("bms_slave_bmsSlaveStatus_1.minCellVol", const.ATTR_MIN_CELL_VOLT, 0)
.attr("bms_slave_bmsSlaveStatus_1.maxCellVol", const.ATTR_MAX_CELL_VOLT, 0),
MilliVoltSensorEntity(client, "bms_slave_bmsSlaveStatus_1.minCellVol", const.SLAVE_N_MIN_CELL_VOLT % 1, False),
MilliVoltSensorEntity(client, "bms_slave_bmsSlaveStatus_1.maxCellVol", const.SLAVE_N_MAX_CELL_VOLT % 1, False),
CyclesSensorEntity(client, "bms_slave_bmsSlaveStatus_1.cycles", const.SLAVE_N_CYCLES % 1, False, True),
LevelSensorEntity(client, "bms_slave_bmsSlaveStatus_1.soh", const.SLAVE_N_SOH % 1, False,True),
InWattsSensorEntity(client, "bms_slave_bmsSlaveStatus_1.inputWatts", const.SLAVE_N_IN_POWER % 1, False, True),
OutWattsSensorEntity(client, "bms_slave_bmsSlaveStatus_1.outputWatts", const.SLAVE_N_OUT_POWER % 1, False, True),
# Optional Slave 2 Battery
LevelSensorEntity(client, "bms_slave_bmsSlaveStatus_2.soc", const.SLAVE_N_BATTERY_LEVEL % 2, False, True)
.attr("bms_slave_bmsSlaveStatus_2.designCap", const.ATTR_DESIGN_CAPACITY, 0)
.attr("bms_slave_bmsSlaveStatus_2.fullCap", const.ATTR_FULL_CAPACITY, 0)
.attr("bms_slave_bmsSlaveStatus_2.remainCap", const.ATTR_REMAIN_CAPACITY, 0),
CapacitySensorEntity(client, "bms_slave_bmsSlaveStatus_2.designCap", const.SLAVE_N_DESIGN_CAPACITY % 2, False),
CapacitySensorEntity(client, "bms_slave_bmsSlaveStatus_2.fullCap", const.SLAVE_N_FULL_CAPACITY % 2, False),
CapacitySensorEntity(client, "bms_slave_bmsSlaveStatus_2.remainCap", const.SLAVE_N_REMAIN_CAPACITY % 2, False),
TempSensorEntity(client, "bms_slave_bmsSlaveStatus_2.temp", const.SLAVE_N_BATTERY_TEMP % 2, False, True)
.attr("bms_slave_bmsSlaveStatus_2.minCellTemp", const.ATTR_MIN_CELL_TEMP, 0)
.attr("bms_slave_bmsSlaveStatus_2.maxCellTemp", const.ATTR_MAX_CELL_TEMP, 0),
TempSensorEntity(client, "bms_slave_bmsSlaveStatus_2.minCellTemp", const.SLAVE_N_MIN_CELL_TEMP % 2, False),
TempSensorEntity(client, "bms_slave_bmsSlaveStatus_2.maxCellTemp", const.SLAVE_N_MAX_CELL_TEMP % 2, False),
MilliVoltSensorEntity(client, "bms_slave_bmsSlaveStatus_2.vol", const.SLAVE_N_BATTERY_VOLT % 2, False)
.attr("bms_slave_bmsSlaveStatus_2.minCellVol", const.ATTR_MIN_CELL_VOLT, 0)
.attr("bms_slave_bmsSlaveStatus_2.maxCellVol", const.ATTR_MAX_CELL_VOLT, 0),
MilliVoltSensorEntity(client, "bms_slave_bmsSlaveStatus_2.minCellVol", const.SLAVE_N_MIN_CELL_VOLT % 2, False),
MilliVoltSensorEntity(client, "bms_slave_bmsSlaveStatus_2.maxCellVol", const.SLAVE_N_MAX_CELL_VOLT % 2, False),
CyclesSensorEntity(client, "bms_slave_bmsSlaveStatus_2.cycles", const.SLAVE_N_CYCLES % 2, False, True),
LevelSensorEntity(client, "bms_slave_bmsSlaveStatus_2.soh", const.SLAVE_N_SOH % 2, False, True),
InWattsSensorEntity(client, "bms_slave_bmsSlaveStatus_2.inputWatts", const.SLAVE_N_IN_POWER % 2, False, True),
OutWattsSensorEntity(client, "bms_slave_bmsSlaveStatus_2.outputWatts", const.SLAVE_N_OUT_POWER % 2, False, True),
StatusSensorEntity(client),
]
def numbers(self, client: EcoflowMQTTClient) -> list[BaseNumberEntity]:
return [
MaxBatteryLevelEntity(client, "bms_emsStatus.maxChargeSoc", const.MAX_CHARGE_LEVEL, 50, 100,
lambda value: {"moduleType": 2, "operateType": "upsConfig",
"moduleSn": client.device_sn,
"params": {"maxChgSoc": int(value)}}),
MinBatteryLevelEntity(client, "bms_emsStatus.minDsgSoc", const.MIN_DISCHARGE_LEVEL, 0, 30,
lambda value: {"moduleType": 2, "operateType": "dsgCfg",
"moduleSn": client.device_sn,
"params": {"minDsgSoc": int(value)}}),
BatteryBackupLevel(client, "pd.bpPowerSoc", const.BACKUP_RESERVE_LEVEL, 5, 100,
"bms_emsStatus.minDsgSoc", "bms_emsStatus.maxChargeSoc",
lambda value: {"moduleType": 1, "operateType": "watthConfig",
"params": {"isConfig": 1, "bpPowerSoc": int(value), "minDsgSoc": 0,
"minChgSoc": 0}}),
MinGenStartLevelEntity(client, "bms_emsStatus.minOpenOilEbSoc", const.GEN_AUTO_START_LEVEL, 0, 30,
lambda value: {"moduleType": 2, "operateType": "openOilSoc",
"moduleSn": client.device_sn,
"params": {"openOilSoc": value}}),
MaxGenStopLevelEntity(client, "bms_emsStatus.maxCloseOilEbSoc", const.GEN_AUTO_STOP_LEVEL, 50, 100,
lambda value: {"moduleType": 2, "operateType": "closeOilSoc",
"moduleSn": client.device_sn,
"params": {"closeOilSoc": value}}),
ChargingPowerEntity(client, "inv.SlowChgWatts", const.AC_CHARGING_POWER, 200, 2400,
lambda value: {"moduleType": 3, "operateType": "acChgCfg",
"moduleSn": client.device_sn,
"params": {"slowChgWatts": int(value), "fastChgWatts": 255,
"chgPauseFlag": 0}})
]
def switches(self, client: EcoflowMQTTClient) -> list[BaseSwitchEntity]:
return [
BeeperEntity(client, "pd.beepMode", const.BEEPER,
lambda value: {"moduleType": 1, "operateType": "quietCfg",
"moduleSn": client.device_sn,
"params": {"enabled": value}}),
EnabledEntity(client, "pd.dcOutState", const.USB_ENABLED,
lambda value: {"moduleType": 1, "operateType": "dcOutCfg",
"moduleSn": client.device_sn,
"params": {"enabled": value}}),
EnabledEntity(client, "pd.newAcAutoOnCfg", const.AC_ALWAYS_ENABLED,
lambda value: {"moduleType": 1, "operateType": "newAcAutoOnCfg",
"moduleSn": client.device_sn,
"params": {"enabled": value, "minAcSoc": 5}}),
EnabledEntity(client, "inv.cfgAcEnabled", const.AC_ENABLED,
lambda value: {"moduleType": 3, "operateType": "acOutCfg",
"moduleSn": client.device_sn,
"params": {"enabled": value, "out_voltage": -1,
"out_freq": 255, "xboost": 255}}),
EnabledEntity(client, "inv.cfgAcXboost", const.XBOOST_ENABLED,
lambda value: {"moduleType": 3, "operateType": "acOutCfg",
"moduleSn": client.device_sn,
"params": {"xboost": value}}),
EnabledEntity(client, "pd.carState", const.DC_ENABLED,
lambda value: {"moduleType": 5, "operateType": "mpptCar",
"params": {"enabled": value}}),
EnabledEntity(client, "pd.bpPowerSoc", const.BP_ENABLED,
lambda value: {"moduleType": 1,
"operateType": "watthConfig",
"params": {"bpPowerSoc": value,
"minChgSoc": 0,
"isConfig": value,
"minDsgSoc": 0}}),
]
def selects(self, client: EcoflowMQTTClient) -> list[BaseSelectEntity]:
return [
TimeoutDictSelectEntity(client, "pd.lcdOffSec", const.SCREEN_TIMEOUT, const.SCREEN_TIMEOUT_OPTIONS,
lambda value: {"moduleType": 1, "operateType": "lcdCfg",
"moduleSn": client.device_sn,
"params": {"brighLevel": 255, "delayOff": value}}),
TimeoutDictSelectEntity(client, "inv.standbyMin", const.UNIT_TIMEOUT, const.UNIT_TIMEOUT_OPTIONS,
lambda value: {"moduleType": 1, "operateType": "standbyTime",
"moduleSn": client.device_sn,
"params": {"standbyMin": value}}),
TimeoutDictSelectEntity(client, "mppt.carStandbyMin", const.AC_TIMEOUT, const.AC_TIMEOUT_OPTIONS,
lambda value: {"moduleType": 5, "operateType": "standbyTime",
"moduleSn": client.device_sn,
"params": {"standbyMins": value}}),
]
def migrate(self, version) -> list[EntityMigration]:
if version == 2:
return [
EntityMigration("pd.soc", Platform.SENSOR, MigrationAction.REMOVE),
EntityMigration("bms_emsStatus.f32LcdShowSoc", Platform.SENSOR, MigrationAction.REMOVE)
]
return []
@@ -0,0 +1,160 @@
from homeassistant.const import Platform
from . import const, BaseDevice, EntityMigration, MigrationAction
from .. import EcoflowMQTTClient
from ..entities import BaseSensorEntity, BaseNumberEntity, BaseSwitchEntity, BaseSelectEntity
from ..number import ChargingPowerEntity, MinBatteryLevelEntity, MaxBatteryLevelEntity, \
MaxGenStopLevelEntity, MinGenStartLevelEntity
from ..sensor import LevelSensorEntity, RemainSensorEntity, TempSensorEntity, CyclesSensorEntity, \
InWattsSensorEntity, OutWattsSensorEntity, StatusSensorEntity, MilliVoltSensorEntity, \
InMilliVoltSensorEntity, OutMilliVoltSensorEntity, CapacitySensorEntity, InWattsSolarSensorEntity, \
OutWattsDcSensorEntity
from ..switch import BeeperEntity, EnabledEntity
class DeltaMax(BaseDevice):
def sensors(self, client: EcoflowMQTTClient) -> list[BaseSensorEntity]:
return [
LevelSensorEntity(client, "bmsMaster.soc", const.MAIN_BATTERY_LEVEL)
.attr("bmsMaster.designCap", const.ATTR_DESIGN_CAPACITY, 0)
.attr("bmsMaster.fullCap", const.ATTR_FULL_CAPACITY, 0)
.attr("bmsMaster.remainCap", const.ATTR_REMAIN_CAPACITY, 0),
CapacitySensorEntity(client, "bmsMaster.designCap", const.MAIN_DESIGN_CAPACITY, False),
CapacitySensorEntity(client, "bmsMaster.fullCap", const.MAIN_FULL_CAPACITY, False),
CapacitySensorEntity(client, "bmsMaster.remainCap", const.MAIN_REMAIN_CAPACITY, False),
LevelSensorEntity(client, "ems.lcdShowSoc", const.COMBINED_BATTERY_LEVEL),
InWattsSensorEntity(client, "pd.wattsInSum", const.TOTAL_IN_POWER),
OutWattsSensorEntity(client, "pd.wattsOutSum", const.TOTAL_OUT_POWER),
InWattsSensorEntity(client, "inv.inputWatts", const.AC_IN_POWER),
OutWattsSensorEntity(client, "inv.outputWatts", const.AC_OUT_POWER),
InMilliVoltSensorEntity(client, "inv.acInVol", const.AC_IN_VOLT),
OutMilliVoltSensorEntity(client, "inv.invOutVol", const.AC_OUT_VOLT),
InWattsSolarSensorEntity(client, "mppt.inWatts", const.SOLAR_IN_POWER),
OutWattsDcSensorEntity(client, "mppt.outWatts", const.DC_OUT_POWER),
OutWattsSensorEntity(client, "pd.typec1Watts", const.TYPEC_1_OUT_POWER),
OutWattsSensorEntity(client, "pd.typec2Watts", const.TYPEC_2_OUT_POWER),
OutWattsSensorEntity(client, "pd.usb1Watts", const.USB_1_OUT_POWER),
OutWattsSensorEntity(client, "pd.usb2Watts", const.USB_2_OUT_POWER),
OutWattsSensorEntity(client, "pd.qcUsb1Watts", const.USB_QC_1_OUT_POWER),
OutWattsSensorEntity(client, "pd.qcUsb2Watts", const.USB_QC_2_OUT_POWER),
RemainSensorEntity(client, "ems.chgRemainTime", const.CHARGE_REMAINING_TIME),
RemainSensorEntity(client, "ems.dsgRemainTime", const.DISCHARGE_REMAINING_TIME),
TempSensorEntity(client, "inv.outTemp", "Inv Out Temperature"),
CyclesSensorEntity(client, "bmsMaster.cycles", const.CYCLES),
TempSensorEntity(client, "bmsMaster.temp", const.BATTERY_TEMP)
.attr("bmsMaster.minCellTemp", const.ATTR_MIN_CELL_TEMP, 0)
.attr("bmsMaster.maxCellTemp", const.ATTR_MAX_CELL_TEMP, 0),
TempSensorEntity(client, "bmsMaster.minCellTemp", const.MIN_CELL_TEMP, False),
TempSensorEntity(client, "bmsMaster.maxCellTemp", const.MAX_CELL_TEMP, False),
MilliVoltSensorEntity(client, "bmsMaster.vol", const.BATTERY_VOLT, False)
.attr("bmsMaster.minCellVol", const.ATTR_MIN_CELL_VOLT, 0)
.attr("bmsMaster.maxCellVol", const.ATTR_MAX_CELL_VOLT, 0),
MilliVoltSensorEntity(client, "bmsMaster.minCellVol", const.MIN_CELL_VOLT, False),
MilliVoltSensorEntity(client, "bmsMaster.maxCellVol", const.MAX_CELL_VOLT, False),
# Optional Slave Battery
#LevelSensorEntity(client, "bms_slave.soc", const.SLAVE_BATTERY_LEVEL, False, True),
#TempSensorEntity(client, "bms_slave.temp", const.SLAVE_BATTERY_TEMP, False, True),
#TempSensorEntity(client, "bms_slave.minCellTemp", const.SLAVE_MIN_CELL_TEMP, False),
#TempSensorEntity(client, "bms_slave.maxCellTemp", const.SLAVE_MAX_CELL_TEMP, False),
#VoltSensorEntity(client, "bms_slave.vol", const.SLAVE_BATTERY_VOLT, False),
#VoltSensorEntity(client, "bms_slave.minCellVol", const.SLAVE_MIN_CELL_VOLT, False),
#VoltSensorEntity(client, "bms_slave.maxCellVol", const.SLAVE_MAX_CELL_VOLT, False),
#CyclesSensorEntity(client, "bms_slave.cycles", const.SLAVE_CYCLES, False, True),
#InWattsSensorEntity(client, "bms_slave.inputWatts", const.SLAVE_IN_POWER, False, True),
#OutWattsSensorEntity(client, "bms_slave.outputWatts", const.SLAVE_OUT_POWER, False, True)
StatusSensorEntity(client),
]
def numbers(self, client: EcoflowMQTTClient) -> list[BaseNumberEntity]:
return [
MaxBatteryLevelEntity(client, "ems.maxChargeSoc", const.MAX_CHARGE_LEVEL, 50, 100,
lambda value: {"moduleType": 2, "operateType": "TCP",
"params": {"id": 49, "maxChgSoc": value}}),
MinBatteryLevelEntity(client, "ems.minDsgSoc", const.MIN_DISCHARGE_LEVEL, 0, 30,
lambda value: {"moduleType": 2, "operateType": "TCP",
"params": {"id": 51, "minDsgSoc": value}}),
MinGenStartLevelEntity(client, "ems.minOpenOilEbSoc", const.GEN_AUTO_START_LEVEL, 0, 30,
lambda value: {"moduleType": 2, "operateType": "TCP",
"params": {"id": 52, "openOilSoc": value}}),
MaxGenStopLevelEntity(client, "ems.maxCloseOilEbSoc", const.GEN_AUTO_STOP_LEVEL, 50, 100,
lambda value: {"moduleType": 2, "operateType": "TCP",
"params": {"id": 53, "closeOilSoc": value}}),
ChargingPowerEntity(client, "inv.cfgFastChgWatt", const.AC_CHARGING_POWER, 200, 2000,
lambda value: {"moduleType": 0, "operateType": "TCP",
"params": {"slowChgPower": value, "id": 69}}),
]
def switches(self, client: EcoflowMQTTClient) -> list[BaseSwitchEntity]:
return [
BeeperEntity(client, "pd.beepState", const.BEEPER,
lambda value: {"moduleType": 5, "operateType": "TCP", "params": {"id": 38, "enabled": value}}),
EnabledEntity(client, "pd.dcOutState", const.USB_ENABLED,
lambda value: {"moduleType": 0, "operateType": "TCP", "params": {"enabled": value, "id": 34 }}),
EnabledEntity(client, "pd.acAutoOnCfg", const.AC_ALWAYS_ENABLED,
lambda value: {"moduleType": 1, "operateType": "acAutoOn", "params": {"cfg": value}}),
EnabledEntity(client, "pd.pvChgPrioSet", const.PV_PRIO,
lambda value: {"moduleType": 1, "operateType": "pvChangePrio", "params": {"pvChangeSet": value}}),
EnabledEntity(client, "inv.cfgAcEnabled", const.AC_ENABLED,
lambda value: {"moduleType": 0, "operateType": "TCP", "params": {"enabled": value, "id": 66 }}),
EnabledEntity(client, "inv.cfgAcXboost", const.XBOOST_ENABLED,
lambda value: {"moduleType": 5, "operateType": "TCP", "params": {"id": 66, "xboost": value}}),
EnabledEntity(client, "mppt.carState", const.DC_ENABLED,
lambda value: {"moduleType": 0, "operateType": "TCP", "params": {"enabled": value, "id": 81 }}),
]
def selects(self, client: EcoflowMQTTClient) -> list[BaseSelectEntity]:
return [
#DictSelectEntity(client, "mppt.cfgDcChgCurrent", const.DC_CHARGE_CURRENT, const.DC_CHARGE_CURRENT_OPTIONS,
# lambda value: {"moduleType": 5, "operateType": "dcChgCfg",
# "params": {"dcChgCfg": value}}),
#TimeoutDictSelectEntity(client, "pd.lcdOffSec", const.SCREEN_TIMEOUT, const.SCREEN_TIMEOUT_OPTIONS,
# lambda value: {"moduleType": 1, "operateType": "lcdCfg",
# "params": {"brighLevel": 255, "delayOff": value}}),
#TimeoutDictSelectEntity(client, "inv.cfgStandbyMin", const.UNIT_TIMEOUT, const.UNIT_TIMEOUT_OPTIONS,
# lambda value: {"moduleType": 1, "operateType": "standbyTime",
# "params": {"standbyMin": value}}),
#TimeoutDictSelectEntity(client, "mppt.acStandbyMins", const.AC_TIMEOUT, const.AC_TIMEOUT_OPTIONS,
# lambda value: {"moduleType": 5, "operateType": "standbyTime",
# "params": {"standbyMins": value}}),
#TimeoutDictSelectEntity(client, "mppt.carStandbyMin", const.DC_TIMEOUT, const.DC_TIMEOUT_OPTIONS,
# lambda value: {"moduleType": 5, "operateType": "carStandby",
# "params": {"standbyMins": value}})
]
def migrate(self, version) -> list[EntityMigration]:
if version == 2:
return [
EntityMigration("pd.soc", Platform.SENSOR, MigrationAction.REMOVE),
]
return []
@@ -0,0 +1,147 @@
from homeassistant.const import Platform
from . import const, BaseDevice, EntityMigration, MigrationAction
from ..entities import BaseSensorEntity, BaseNumberEntity, BaseSwitchEntity, BaseSelectEntity
from ..mqtt.ecoflow_mqtt import EcoflowMQTTClient
from ..number import ChargingPowerEntity, MaxBatteryLevelEntity, MinBatteryLevelEntity
from ..select import DictSelectEntity, TimeoutDictSelectEntity
from ..sensor import LevelSensorEntity, WattsSensorEntity, RemainSensorEntity, TempSensorEntity, \
CyclesSensorEntity, InWattsSensorEntity, OutWattsSensorEntity, OutWattsDcSensorEntity, InWattsSolarSensorEntity, \
StatusSensorEntity, InEnergySensorEntity, OutEnergySensorEntity, MilliVoltSensorEntity, InMilliVoltSensorEntity, \
OutMilliVoltSensorEntity, CapacitySensorEntity
from ..switch import BeeperEntity, EnabledEntity
class DeltaMini(BaseDevice):
def sensors(self, client: EcoflowMQTTClient) -> list[BaseSensorEntity]:
return [
LevelSensorEntity(client, "bmsMaster.soc", const.MAIN_BATTERY_LEVEL)
.attr("bmsMaster.designCap", const.ATTR_DESIGN_CAPACITY, 0)
.attr("bmsMaster.fullCap", const.ATTR_FULL_CAPACITY, 0)
.attr("bmsMaster.remainCap", const.ATTR_REMAIN_CAPACITY, 0),
CapacitySensorEntity(client, "bmsMaster.designCap", const.MAIN_DESIGN_CAPACITY, False),
CapacitySensorEntity(client, "bmsMaster.fullCap", const.MAIN_FULL_CAPACITY, False),
CapacitySensorEntity(client, "bmsMaster.remainCap", const.MAIN_REMAIN_CAPACITY, False),
LevelSensorEntity(client, "bmsMaster.soh", const.SOH),
LevelSensorEntity(client, "ems.lcdShowSoc", const.COMBINED_BATTERY_LEVEL),
WattsSensorEntity(client, "pd.wattsInSum", const.TOTAL_IN_POWER),
WattsSensorEntity(client, "pd.wattsOutSum", const.TOTAL_OUT_POWER),
InWattsSensorEntity(client, "inv.inputWatts", const.AC_IN_POWER),
OutWattsSensorEntity(client, "inv.outputWatts", const.AC_OUT_POWER),
InMilliVoltSensorEntity(client, "inv.acInVol", const.AC_IN_VOLT),
OutMilliVoltSensorEntity(client, "inv.invOutVol", const.AC_OUT_VOLT),
InWattsSolarSensorEntity(client, "mppt.inWatts", const.SOLAR_IN_POWER),
OutWattsDcSensorEntity(client, "mppt.outWatts", const.DC_OUT_POWER),
OutWattsDcSensorEntity(client, "mppt.carOutWatts", const.DC_CAR_OUT_POWER),
OutWattsSensorEntity(client, "mppt.dcdc12vWatts", const.DC_ANDERSON_OUT_POWER),
OutWattsSensorEntity(client, "pd.typec1Watts", const.TYPEC_1_OUT_POWER),
OutWattsSensorEntity(client, "pd.typec2Watts", const.TYPEC_2_OUT_POWER),
OutWattsSensorEntity(client, "pd.usb1Watts", const.USB_1_OUT_POWER),
OutWattsSensorEntity(client, "pd.usb2Watts", const.USB_2_OUT_POWER),
OutWattsSensorEntity(client, "pd.qcUsb1Watts", const.USB_QC_1_OUT_POWER),
OutWattsSensorEntity(client, "pd.qcUsb2Watts", const.USB_QC_2_OUT_POWER),
RemainSensorEntity(client, "ems.chgRemainTime", const.CHARGE_REMAINING_TIME),
RemainSensorEntity(client, "ems.dsgRemainTime", const.DISCHARGE_REMAINING_TIME),
CyclesSensorEntity(client, "bmsMaster.cycles", const.CYCLES),
TempSensorEntity(client, "bmsMaster.temp", const.BATTERY_TEMP, False)
.attr("bmsMaster.minCellTemp", const.ATTR_MIN_CELL_TEMP, 0)
.attr("bmsMaster.maxCellTemp", const.ATTR_MAX_CELL_TEMP, 0),
MilliVoltSensorEntity(client, "bmsMaster.vol", const.BATTERY_VOLT, False)
.attr("bmsMaster.minCellVol", const.ATTR_MIN_CELL_VOLT, 0)
.attr("bmsMaster.maxCellVol", const.ATTR_MAX_CELL_VOLT, 0),
# https://github.com/tolwi/hassio-ecoflow-cloud/discussions/87
InEnergySensorEntity(client, "pd.chgSunPower", const.SOLAR_IN_ENERGY),
InEnergySensorEntity(client, "pd.chgPowerAc", const.CHARGE_AC_ENERGY),
InEnergySensorEntity(client, "pd.chgPowerDc", const.CHARGE_DC_ENERGY),
OutEnergySensorEntity(client, "pd.dsgPowerAc", const.DISCHARGE_AC_ENERGY),
OutEnergySensorEntity(client, "pd.dsgPowerDc", const.DISCHARGE_DC_ENERGY),
StatusSensorEntity(client),
]
def numbers(self, client: EcoflowMQTTClient) -> list[BaseNumberEntity]:
return [
MaxBatteryLevelEntity(client, "ems.maxChargeSoc", const.MAX_CHARGE_LEVEL, 50, 100,
lambda value: {"moduleType": 0, "operateType": "TCP",
"params": {"id": 49, "maxChgSoc": value}}),
MinBatteryLevelEntity(client, "ems.minDsgSoc", const.MIN_DISCHARGE_LEVEL, 0, 30,
lambda value: {"moduleType": 0, "operateType": "TCP",
"params": {"id": 51, "minDsgSoc": value}}),
# MaxBatteryLevelEntity(client, "pd.bpPowerSoc", const.BACKUP_RESERVE_LEVEL, 5, 100,
# lambda value: {"moduleType": 0, "operateType": "TCP",
# "params": {"isConfig": 1, "bpPowerSoc": int(value), "minDsgSoc": 0, "maxChgSoc": 0, "id": 94}}),
# MinGenStartLevelEntity(client, "ems.minOpenOilEbSoc", const.GEN_AUTO_START_LEVEL, 0, 30,
# lambda value: {"moduleType": 0, "operateType": "TCP",
# "params": {"openOilSoc": value, "id": 52}}),
#
# MaxGenStopLevelEntity(client, "ems.maxCloseOilEbSoc", const.GEN_AUTO_STOP_LEVEL, 50, 100,
# lambda value: {"moduleType": 0, "operateType": "TCP",
# "params": {"closeOilSoc": value, "id": 53}}),
ChargingPowerEntity(client, "inv.cfgSlowChgWatts", const.AC_CHARGING_POWER, 200, 900,
lambda value: {"moduleType": 0, "operateType": "TCP",
"params": {"slowChgPower": value, "id": 69}}),
]
def switches(self, client: EcoflowMQTTClient) -> list[BaseSwitchEntity]:
return [
BeeperEntity(client, "mppt.beepState", const.BEEPER,
lambda value: {"moduleType": 0, "operateType": "TCP", "params": {"id": 38, "enabled": value}}),
EnabledEntity(client, "mppt.carState", const.DC_ENABLED,
lambda value: {"moduleType": 0, "operateType": "TCP",
"params": {"id": 81, "enabled": value}}),
EnabledEntity(client, "inv.cfgAcEnabled", const.AC_ENABLED,
lambda value: {"moduleType": 0, "operateType": "TCP",
"params": {"id": 66, "enabled": value}}),
EnabledEntity(client, "inv.cfgAcXboost", const.XBOOST_ENABLED,
lambda value: {"moduleType": 0, "operateType": "TCP", "params": {"id": 66, "xboost": value}}),
# EnabledEntity(client, "inv.acPassByAutoEn", const.AC_ALWAYS_ENABLED,
# lambda value: {"moduleType": 0, "operateType": "TCP", "params": {"id": 84, "enabled": value}}),
# EnabledEntity(client, "pd.bpPowerSoc", const.BP_ENABLED,
# lambda value: {"moduleType": 0, "operateType": "TCP", "params": {"isConfig": value}}),
]
def selects(self, client: EcoflowMQTTClient) -> list[BaseSelectEntity]:
return [
DictSelectEntity(client, "mppt.cfgDcChgCurrent", const.DC_CHARGE_CURRENT, const.DC_CHARGE_CURRENT_OPTIONS,
lambda value: {"moduleType": 0, "operateType": "TCP",
"params": {"currMa": value, "id": 71}}),
TimeoutDictSelectEntity(client, "pd.lcdOffSec", const.SCREEN_TIMEOUT, const.SCREEN_TIMEOUT_OPTIONS,
lambda value: {"moduleType": 0, "operateType": "TCP",
"params": {"lcdTime": value, "id": 39}}),
TimeoutDictSelectEntity(client, "pd.standByMode", const.UNIT_TIMEOUT, const.UNIT_TIMEOUT_OPTIONS_LIMITED,
lambda value: {"moduleType": 0, "operateType": "TCP",
"params": {"standByMode": value, "id": 33}}),
TimeoutDictSelectEntity(client, "inv.cfgStandbyMin", const.AC_TIMEOUT, const.AC_TIMEOUT_OPTIONS,
lambda value: {"moduleType": 0, "operateType": "TCP",
"params": {"standByMins": value, "id": 153}}),
]
def migrate(self, version) -> list[EntityMigration]:
if version == 2:
return [
EntityMigration("pd.soc", Platform.SENSOR, MigrationAction.REMOVE),
]
return []
@@ -0,0 +1,212 @@
from homeassistant.const import Platform
from . import const, BaseDevice, EntityMigration, MigrationAction
from ..entities import BaseSensorEntity, BaseNumberEntity, BaseSwitchEntity, BaseSelectEntity
from ..mqtt.ecoflow_mqtt import EcoflowMQTTClient
from ..number import ChargingPowerEntity, MaxBatteryLevelEntity, MinBatteryLevelEntity, MinGenStartLevelEntity, \
MaxGenStopLevelEntity
from ..select import DictSelectEntity, TimeoutDictSelectEntity
from ..sensor import LevelSensorEntity, WattsSensorEntity, RemainSensorEntity, TempSensorEntity, \
CyclesSensorEntity, InWattsSensorEntity, OutWattsSensorEntity, OutWattsDcSensorEntity, VoltSensorEntity, \
InWattsSolarSensorEntity, InVoltSolarSensorEntity, InAmpSolarSensorEntity, OutVoltDcSensorEntity, \
StatusSensorEntity, InEnergySensorEntity, OutEnergySensorEntity, MilliVoltSensorEntity, InMilliVoltSensorEntity, \
OutMilliVoltSensorEntity, AmpSensorEntity, CapacitySensorEntity
from ..switch import BeeperEntity, EnabledEntity
class DeltaPro(BaseDevice):
def sensors(self, client: EcoflowMQTTClient) -> list[BaseSensorEntity]:
return [
LevelSensorEntity(client, "bmsMaster.soc", const.MAIN_BATTERY_LEVEL)
.attr("bmsMaster.designCap", const.ATTR_DESIGN_CAPACITY, 0)
.attr("bmsMaster.fullCap", const.ATTR_FULL_CAPACITY, 0)
.attr("bmsMaster.remainCap", const.ATTR_REMAIN_CAPACITY, 0),
LevelSensorEntity(client, "bmsMaster.f32ShowSoc", const.MAIN_BATTERY_LEVEL_F32, False)
.attr("bmsMaster.designCap", const.ATTR_DESIGN_CAPACITY, 0)
.attr("bmsMaster.fullCap", const.ATTR_FULL_CAPACITY, 0)
.attr("bmsMaster.remainCap", const.ATTR_REMAIN_CAPACITY, 0),
CapacitySensorEntity(client, "bmsMaster.designCap", const.MAIN_DESIGN_CAPACITY, False),
CapacitySensorEntity(client, "bmsMaster.fullCap", const.MAIN_FULL_CAPACITY, False),
CapacitySensorEntity(client, "bmsMaster.remainCap", const.MAIN_REMAIN_CAPACITY, False),
LevelSensorEntity(client, "bmsMaster.soh", const.SOH),
LevelSensorEntity(client, "ems.lcdShowSoc", const.COMBINED_BATTERY_LEVEL),
LevelSensorEntity(client, "ems.f32LcdShowSoc", const.COMBINED_BATTERY_LEVEL_F32, False),
WattsSensorEntity(client, "pd.wattsInSum", const.TOTAL_IN_POWER),
WattsSensorEntity(client, "pd.wattsOutSum", const.TOTAL_OUT_POWER),
AmpSensorEntity(client, "bmsMaster.amp", const.MAIN_BATTERY_CURRENT),
InWattsSensorEntity(client, "inv.inputWatts", const.AC_IN_POWER),
OutWattsSensorEntity(client, "inv.outputWatts", const.AC_OUT_POWER),
InMilliVoltSensorEntity(client, "inv.acInVol", const.AC_IN_VOLT),
OutMilliVoltSensorEntity(client, "inv.invOutVol", const.AC_OUT_VOLT),
InWattsSolarSensorEntity(client, "mppt.inWatts", const.SOLAR_IN_POWER),
InVoltSolarSensorEntity(client, "mppt.inVol", const.SOLAR_IN_VOLTAGE),
InAmpSolarSensorEntity(client, "mppt.inAmp", const.SOLAR_IN_CURRENT),
OutWattsDcSensorEntity(client, "mppt.outWatts", const.DC_OUT_POWER),
OutVoltDcSensorEntity(client, "mppt.outVol", const.DC_OUT_VOLTAGE),
OutWattsSensorEntity(client, "mppt.carOutWatts", const.DC_CAR_OUT_POWER),
OutWattsSensorEntity(client, "mppt.dcdc12vWatts", const.DC_ANDERSON_OUT_POWER),
OutWattsSensorEntity(client, "pd.typec1Watts", const.TYPEC_1_OUT_POWER),
OutWattsSensorEntity(client, "pd.typec2Watts", const.TYPEC_2_OUT_POWER),
OutWattsSensorEntity(client, "pd.usb1Watts", const.USB_1_OUT_POWER),
OutWattsSensorEntity(client, "pd.usb2Watts", const.USB_2_OUT_POWER),
OutWattsSensorEntity(client, "pd.qcUsb1Watts", const.USB_QC_1_OUT_POWER),
OutWattsSensorEntity(client, "pd.qcUsb2Watts", const.USB_QC_2_OUT_POWER),
RemainSensorEntity(client, "ems.chgRemainTime", const.CHARGE_REMAINING_TIME),
RemainSensorEntity(client, "ems.dsgRemainTime", const.DISCHARGE_REMAINING_TIME),
CyclesSensorEntity(client, "bmsMaster.cycles", const.CYCLES),
TempSensorEntity(client, "bmsMaster.temp", const.BATTERY_TEMP)
.attr("bmsMaster.minCellTemp", const.ATTR_MIN_CELL_TEMP, 0)
.attr("bmsMaster.maxCellTemp", const.ATTR_MAX_CELL_TEMP, 0),
TempSensorEntity(client, "bmsMaster.minCellTemp", const.MIN_CELL_TEMP, False),
TempSensorEntity(client, "bmsMaster.maxCellTemp", const.MAX_CELL_TEMP, False),
MilliVoltSensorEntity(client, "bmsMaster.vol", const.BATTERY_VOLT, False)
.attr("bmsMaster.minCellVol", const.ATTR_MIN_CELL_VOLT, 0)
.attr("bmsMaster.maxCellVol", const.ATTR_MAX_CELL_VOLT, 0),
MilliVoltSensorEntity(client, "bmsMaster.minCellVol", const.MIN_CELL_VOLT, False),
MilliVoltSensorEntity(client, "bmsMaster.maxCellVol", const.MAX_CELL_VOLT, False),
# https://github.com/tolwi/hassio-ecoflow-cloud/discussions/87
InEnergySensorEntity(client, "pd.chgSunPower", const.SOLAR_IN_ENERGY),
InEnergySensorEntity(client, "pd.chgPowerAc", const.CHARGE_AC_ENERGY),
InEnergySensorEntity(client, "pd.chgPowerDc", const.CHARGE_DC_ENERGY),
OutEnergySensorEntity(client, "pd.dsgPowerAc", const.DISCHARGE_AC_ENERGY),
OutEnergySensorEntity(client, "pd.dsgPowerDc", const.DISCHARGE_DC_ENERGY),
# Optional Slave Batteries
LevelSensorEntity(client, "bmsSlave1.soc", const.SLAVE_N_BATTERY_LEVEL % 1, False, True)
.attr("bmsSlave1.designCap", const.ATTR_DESIGN_CAPACITY, 0)
.attr("bmsSlave1.fullCap", const.ATTR_FULL_CAPACITY, 0)
.attr("bmsSlave1.remainCap", const.ATTR_REMAIN_CAPACITY, 0),
LevelSensorEntity(client, "bmsSlave1.f32ShowSoc", const.SLAVE_N_BATTERY_LEVEL_F32 % 1, False, False)
.attr("bmsSlave1.designCap", const.ATTR_DESIGN_CAPACITY, 0)
.attr("bmsSlave1.fullCap", const.ATTR_FULL_CAPACITY, 0)
.attr("bmsSlave1.remainCap", const.ATTR_REMAIN_CAPACITY, 0),
CapacitySensorEntity(client, "bmsSlave1.designCap", const.SLAVE_N_DESIGN_CAPACITY % 1, False),
CapacitySensorEntity(client, "bmsSlave1.fullCap", const.SLAVE_N_FULL_CAPACITY % 1, False),
CapacitySensorEntity(client, "bmsSlave1.remainCap", const.SLAVE_N_REMAIN_CAPACITY % 1, False),
LevelSensorEntity(client, "bmsSlave1.soh", const.SLAVE_N_SOH % 1),
TempSensorEntity(client, "bmsSlave1.temp", const.SLAVE_N_BATTERY_TEMP % 1, False, True)
.attr("bmsSlave1.minCellTemp", const.ATTR_MIN_CELL_TEMP, 0)
.attr("bmsSlave1.maxCellTemp", const.ATTR_MAX_CELL_TEMP, 0),
WattsSensorEntity(client, "bmsSlave1.inputWatts", const.SLAVE_N_IN_POWER % 1, False, True),
WattsSensorEntity(client, "bmsSlave1.outputWatts", const.SLAVE_N_OUT_POWER % 1, False, True),
LevelSensorEntity(client, "bmsSlave2.soc", const.SLAVE_N_BATTERY_LEVEL % 2, False, True)
.attr("bmsSlave2.designCap", const.ATTR_DESIGN_CAPACITY, 0)
.attr("bmsSlave2.fullCap", const.ATTR_FULL_CAPACITY, 0)
.attr("bmsSlave2.remainCap", const.ATTR_REMAIN_CAPACITY, 0),
LevelSensorEntity(client, "bmsSlave2.f32ShowSoc", const.SLAVE_N_BATTERY_LEVEL_F32 % 2, False, False)
.attr("bmsSlave2.designCap", const.ATTR_DESIGN_CAPACITY, 0)
.attr("bmsSlave2.fullCap", const.ATTR_FULL_CAPACITY, 0)
.attr("bmsSlave2.remainCap", const.ATTR_REMAIN_CAPACITY, 0),
CapacitySensorEntity(client, "bmsSlave2.designCap", const.SLAVE_N_DESIGN_CAPACITY % 2, False),
CapacitySensorEntity(client, "bmsSlave2.fullCap", const.SLAVE_N_FULL_CAPACITY % 2, False),
CapacitySensorEntity(client, "bmsSlave2.remainCap", const.SLAVE_N_REMAIN_CAPACITY % 2, False),
LevelSensorEntity(client, "bmsSlave2.soh", const.SLAVE_N_SOH % 2),
MilliVoltSensorEntity(client, "bmsSlave1.vol", const.SLAVE_N_BATTERY_VOLT % 1, False),
MilliVoltSensorEntity(client, "bmsSlave1.minCellVol", const.SLAVE_N_MIN_CELL_VOLT % 1, False),
MilliVoltSensorEntity(client, "bmsSlave1.maxCellVol", const.SLAVE_N_MAX_CELL_VOLT % 1, False),
AmpSensorEntity(client, "bmsSlave1.amp", const.SLAVE_N_BATTERY_CURRENT % 1, False),
MilliVoltSensorEntity(client, "bmsSlave2.vol", const.SLAVE_N_BATTERY_VOLT % 2, False),
MilliVoltSensorEntity(client, "bmsSlave2.minCellVol", const.SLAVE_N_MIN_CELL_VOLT % 2, False),
MilliVoltSensorEntity(client, "bmsSlave2.maxCellVol", const.SLAVE_N_MAX_CELL_VOLT % 2, False),
AmpSensorEntity(client, "bmsSlave2.amp", const.SLAVE_N_BATTERY_CURRENT % 2, False),
TempSensorEntity(client, "bmsSlave2.temp", const.SLAVE_N_BATTERY_TEMP % 2, False, True)
.attr("bmsSlave2.minCellTemp", const.ATTR_MIN_CELL_TEMP, 0)
.attr("bmsSlave2.maxCellTemp", const.ATTR_MAX_CELL_TEMP, 0),
WattsSensorEntity(client, "bmsSlave2.inputWatts", const.SLAVE_N_IN_POWER % 2, False, True),
WattsSensorEntity(client, "bmsSlave2.outputWatts", const.SLAVE_N_OUT_POWER % 2, False, True),
CyclesSensorEntity(client, "bmsSlave1.cycles", const.SLAVE_N_CYCLES % 1, False),
CyclesSensorEntity(client, "bmsSlave2.cycles", const.SLAVE_N_CYCLES % 2, False),
StatusSensorEntity(client),
]
def numbers(self, client: EcoflowMQTTClient) -> list[BaseNumberEntity]:
return [
MaxBatteryLevelEntity(client, "ems.maxChargeSoc", const.MAX_CHARGE_LEVEL, 50, 100,
lambda value: {"moduleType": 0, "operateType": "TCP",
"params": {"id": 49, "maxChgSoc": value}}),
MinBatteryLevelEntity(client, "ems.minDsgSoc", const.MIN_DISCHARGE_LEVEL, 0, 30,
lambda value: {"moduleType": 0, "operateType": "TCP",
"params": {"id": 51, "minDsgSoc": value}}),
MaxBatteryLevelEntity(client, "pd.bpPowerSoc", const.BACKUP_RESERVE_LEVEL, 5, 100,
lambda value: {"moduleType": 0, "operateType": "TCP",
"params": {"isConfig": 1, "bpPowerSoc": int(value), "minDsgSoc": 0,
"maxChgSoc": 0, "id": 94}}),
MinGenStartLevelEntity(client, "ems.minOpenOilEbSoc", const.GEN_AUTO_START_LEVEL, 0, 30,
lambda value: {"moduleType": 0, "operateType": "TCP",
"params": {"openOilSoc": value, "id": 52}}),
MaxGenStopLevelEntity(client, "ems.maxCloseOilEbSoc", const.GEN_AUTO_STOP_LEVEL, 50, 100,
lambda value: {"moduleType": 0, "operateType": "TCP",
"params": {"closeOilSoc": value, "id": 53}}),
ChargingPowerEntity(client, "inv.cfgSlowChgWatts", const.AC_CHARGING_POWER, 200, 2900,
lambda value: {"moduleType": 0, "operateType": "TCP",
"params": {"slowChgPower": value, "id": 69}}),
]
def switches(self, client: EcoflowMQTTClient) -> list[BaseSwitchEntity]:
return [
BeeperEntity(client, "pd.beepState", const.BEEPER,
lambda value: {"moduleType": 0, "operateType": "TCP", "params": {"id": 38, "enabled": value}}),
EnabledEntity(client, "mppt.carState", const.DC_ENABLED,
lambda value: {"moduleType": 0, "operateType": "TCP",
"params": {"id": 81, "enabled": value}}),
EnabledEntity(client, "inv.cfgAcEnabled", const.AC_ENABLED,
lambda value: {"moduleType": 0, "operateType": "TCP",
"params": {"id": 66, "enabled": value}}),
EnabledEntity(client, "inv.cfgAcXboost", const.XBOOST_ENABLED,
lambda value: {"moduleType": 0, "operateType": "TCP", "params": {"id": 66, "xboost": value}}),
EnabledEntity(client, "pd.acautooutConfig", const.AC_ALWAYS_ENABLED,
lambda value: {"moduleType": 0, "operateType": "TCP",
"params": {"id": 95, "acautooutConfig": value}}),
EnabledEntity(client, "pd.bppowerSoc", const.BP_ENABLED,
lambda value, params: {"moduleType": 0, "operateType": "TCP",
"params": {"id": 94, "isConfig": value,
"bpPowerSoc": int(params.get("pd.bppowerSoc", 0)),
"minDsgSoc": 0,
"maxChgSoc": 0}}),
]
def selects(self, client: EcoflowMQTTClient) -> list[BaseSelectEntity]:
return [
DictSelectEntity(client, "mppt.cfgDcChgCurrent", const.DC_CHARGE_CURRENT, const.DC_CHARGE_CURRENT_OPTIONS,
lambda value: {"moduleType": 0, "operateType": "TCP",
"params": {"currMa": value, "id": 71}}),
TimeoutDictSelectEntity(client, "pd.lcdOffSec", const.SCREEN_TIMEOUT, const.SCREEN_TIMEOUT_OPTIONS,
lambda value: {"moduleType": 0, "operateType": "TCP",
"params": {"lcdTime": value, "id": 39}}),
TimeoutDictSelectEntity(client, "pd.standByMode", const.UNIT_TIMEOUT, const.UNIT_TIMEOUT_OPTIONS_LIMITED,
lambda value: {"moduleType": 0, "operateType": "TCP",
"params": {"standByMode": value, "id": 33}}),
TimeoutDictSelectEntity(client, "inv.cfgStandbyMin", const.AC_TIMEOUT, const.AC_TIMEOUT_OPTIONS,
lambda value: {"moduleType": 0, "operateType": "TCP",
"params": {"standByMins": value, "id": 153}}),
]
def migrate(self, version) -> list[EntityMigration]:
if version == 2:
return [
EntityMigration("pd.soc", Platform.SENSOR, MigrationAction.REMOVE),
]
return []
@@ -0,0 +1,129 @@
from . import const, BaseDevice
from ..button import EnabledButtonEntity
from ..entities import BaseSensorEntity, BaseNumberEntity, BaseSwitchEntity, BaseSelectEntity, BaseButtonEntity
from ..mqtt.ecoflow_mqtt import EcoflowMQTTClient
from ..number import SetTempEntity
from ..sensor import LevelSensorEntity, RemainSensorEntity, SecondsRemainSensorEntity, TempSensorEntity, \
CyclesSensorEntity, InWattsSensorEntity, OutWattsSensorEntity, VoltSensorEntity, QuotasStatusSensorEntity, \
MilliVoltSensorEntity, ChargingStateSensorEntity, \
FanSensorEntity, MiscBinarySensorEntity, DecicelsiusSensorEntity, MiscSensorEntity, CapacitySensorEntity
from ..switch import EnabledEntity, InvertedBeeperEntity
class Glacier(BaseDevice):
def charging_power_step(self) -> int:
return 50
def sensors(self, client: EcoflowMQTTClient) -> list[BaseSensorEntity]:
return [
# Power and Battery Entities
LevelSensorEntity(client, "bms_bmsStatus.soc", const.MAIN_BATTERY_LEVEL)
.attr("bms_bmsStatus.designCap", const.ATTR_DESIGN_CAPACITY, 0)
.attr("bms_bmsStatus.fullCap", const.ATTR_FULL_CAPACITY, 0)
.attr("bms_bmsStatus.remainCap", const.ATTR_REMAIN_CAPACITY, 0),
CapacitySensorEntity(client, "bms_bmsStatus.designCap", const.MAIN_DESIGN_CAPACITY, False),
CapacitySensorEntity(client, "bms_bmsStatus.fullCap", const.MAIN_FULL_CAPACITY, False),
CapacitySensorEntity(client, "bms_bmsStatus.remainCap", const.MAIN_REMAIN_CAPACITY, False),
LevelSensorEntity(client, "bms_emsStatus.f32LcdSoc", const.COMBINED_BATTERY_LEVEL),
ChargingStateSensorEntity(client, "bms_emsStatus.chgState", const.BATTERY_CHARGING_STATE),
InWattsSensorEntity(client, "bms_bmsStatus.inWatts", const.TOTAL_IN_POWER),
OutWattsSensorEntity(client, "bms_bmsStatus.outWatts", const.TOTAL_OUT_POWER),
OutWattsSensorEntity(client, "pd.motorWat", "Motor Power"),
RemainSensorEntity(client, "bms_emsStatus.chgRemain", const.CHARGE_REMAINING_TIME),
RemainSensorEntity(client, "bms_emsStatus.dsgRemain", const.DISCHARGE_REMAINING_TIME),
CyclesSensorEntity(client, "bms_bmsStatus.cycles", const.CYCLES),
TempSensorEntity(client, "bms_bmsStatus.tmp", const.BATTERY_TEMP)
.attr("bms_bmsStatus.minCellTemp", const.ATTR_MIN_CELL_TEMP, 0)
.attr("bms_bmsStatus.maxCellTemp", const.ATTR_MAX_CELL_TEMP, 0),
TempSensorEntity(client, "bms_bmsStatus.minCellTmp", const.MIN_CELL_TEMP, False),
TempSensorEntity(client, "bms_bmsStatus.maxCellTmp", const.MAX_CELL_TEMP, False),
VoltSensorEntity(client, "bms_bmsStatus.vol", const.BATTERY_VOLT, False)
.attr("bms_bmsStatus.minCellVol", const.ATTR_MIN_CELL_VOLT, 0)
.attr("bms_bmsStatus.maxCellVol", const.ATTR_MAX_CELL_VOLT, 0),
MilliVoltSensorEntity(client, "bms_bmsStatus.minCellVol", const.MIN_CELL_VOLT, False),
MilliVoltSensorEntity(client, "bms_bmsStatus.maxCellVol", const.MAX_CELL_VOLT, False),
MiscBinarySensorEntity(client,"pd.batFlag", "Battery Present"),
MiscSensorEntity(client, "pd.xt60InState", "XT60 State"),
#Fridge Entities
FanSensorEntity(client, "bms_emsStatus.fanLvl", "Fan Level"),
DecicelsiusSensorEntity(client, "pd.ambientTmp", "Ambient Temperature"),
DecicelsiusSensorEntity(client, "pd.exhaustTmp", "Exhaust Temperature"),
DecicelsiusSensorEntity(client, "pd.tempWater", "Water Temperature"),
DecicelsiusSensorEntity(client, "pd.tmpL", "Left Temperature"),
DecicelsiusSensorEntity(client, "pd.tmpR", "Right Temperature"),
MiscBinarySensorEntity(client,"pd.flagTwoZone","Dual Zone Mode"),
SecondsRemainSensorEntity(client, "pd.iceTm", "Ice Time Remain"),
LevelSensorEntity(client, "pd.icePercent", "Ice Percentage"),
MiscSensorEntity(client, "pd.iceMkMode", "Ice Make Mode"),
MiscBinarySensorEntity(client,"pd.iceAlert","Ice Alert"),
MiscBinarySensorEntity(client,"pd.waterLine","Ice Water Level OK"),
QuotasStatusSensorEntity(client)
]
def numbers(self, client: EcoflowMQTTClient) -> list[BaseNumberEntity]:
return [
SetTempEntity(client,"pd.tmpLSet", "Left Set Temperature",-25, 10,
lambda value, params: {"moduleType": 1, "operateType": "temp",
"params": {"tmpM": int(params.get("pd.tmpMSet", 0)),
"tmpL": int(value),
"tmpR": int(params.get("pd.tmpRSet", 0))}}),
SetTempEntity(client,"pd.tmpMSet", "Combined Set Temperature",-25, 10,
lambda value, params: {"moduleType": 1, "operateType": "temp",
"params": {"tmpM": int(value),
"tmpL": int(params.get("pd.tmpLSet", 0)),
"tmpR": int(params.get("pd.tmpRSet", 0))}}),
SetTempEntity(client,"pd.tmpRSet", "Right Set Temperature",-25, 10,
lambda value, params: {"moduleType": 1, "operateType": "temp",
"params": {"tmpM": int(params.get("pd.tmpMSet", 0)),
"tmpL": int(params.get("pd.tmpLSet", 0)),
"tmpR": int(value)}}),
]
def switches(self, client: EcoflowMQTTClient) -> list[BaseSwitchEntity]:
return [
InvertedBeeperEntity(client, "pd.beepEn", const.BEEPER,
lambda value: {"moduleType": 1, "operateType": "beepEn", "params": {"flag": value}}),
EnabledEntity(client, "pd.coolMode", "Eco Mode",
lambda value: {"moduleType": 1, "operateType": "ecoMode", "params": {"mode": value}}),
#power parameter is inverted for some reason
EnabledEntity(client, "pd.pwrState", "Power",
lambda value: {"moduleType": 1, "operateType": "powerOff", "params": {"enable": value}}),
]
def buttons(self, client: EcoflowMQTTClient) -> list[BaseButtonEntity]:
return [
EnabledButtonEntity(client, "smlice", "Make Small Ice", lambda value: {"moduleType": 1, "operateType": "iceMake", "params": {"enable": 1, "iceShape": 0}}),
EnabledButtonEntity(client, "lrgice", "Make Large Ice", lambda value: {"moduleType": 1, "operateType": "iceMake", "params": {"enable": 1, "iceShape": 1}}),
EnabledButtonEntity(client, "deice", "Detach Ice", lambda value: {"moduleType": 1, "operateType": "deIce", "params": {"enable": 1}})
]
def selects(self, client: EcoflowMQTTClient) -> list[BaseSelectEntity]:
return [
]
@@ -0,0 +1,104 @@
from . import BaseDevice
from .. import EcoflowMQTTClient
from ..entities import (
BaseSensorEntity, BaseNumberEntity, BaseSelectEntity, BaseSwitchEntity
)
from ..sensor import (
AmpSensorEntity, CentivoltSensorEntity, DeciampSensorEntity,
DecicelsiusSensorEntity, DecihertzSensorEntity, DeciwattsSensorEntity,
DecivoltSensorEntity, InWattsSolarSensorEntity, LevelSensorEntity,
MiscSensorEntity, RemainSensorEntity, StatusSensorEntity,
)
# from ..number import MinBatteryLevelEntity, MaxBatteryLevelEntity
# from ..select import DictSelectEntity
class PowerStream(BaseDevice):
def sensors(self, client: EcoflowMQTTClient) -> list[BaseSensorEntity]:
return [
InWattsSolarSensorEntity(client, "pv1_input_watts", "Solar 1 Watts"),
DecivoltSensorEntity(client, "pv1_input_volt", "Solar 1 Input Potential"),
CentivoltSensorEntity(client, "pv1_op_volt", "Solar 1 Op Potential"),
DeciampSensorEntity(client, "pv1_input_cur", "Solar 1 Currrent"),
DecicelsiusSensorEntity(client, "pv1_temp", "Solar 1 Temperature"),
MiscSensorEntity(client, "pv1_relay_status", "Solar 1 Relay Status"),
MiscSensorEntity(client, "pv1_error_code", "Solar 1 Error Code", False),
MiscSensorEntity(client, "pv1_warning_code", "Solar 1 Warning Code", False),
MiscSensorEntity(client, "pv1_status", "Solar 1 Status", False),
InWattsSolarSensorEntity(client, "pv2_input_watts", "Solar 2 Watts"),
DecivoltSensorEntity(client, "pv2_input_volt", "Solar 2 Input Potential"),
CentivoltSensorEntity(client, "pv2_op_volt", "Solar 2 Op Potential"),
DeciampSensorEntity(client, "pv2_input_cur", "Solar 2 Current"),
DecicelsiusSensorEntity(client, "pv2_temp", "Solar 2 Temperature"),
MiscSensorEntity(client, "pv2_relay_status", "Solar 2 Relay Status"),
MiscSensorEntity(client, "pv2_error_code", "Solar 2 Error Code", False),
MiscSensorEntity(client, "pv2_warning_code", "Solar 2 Warning Code", False),
MiscSensorEntity(client, "pv2_status", "Solar 2 Status", False),
MiscSensorEntity(client, "bp_type", "Battery Type", False),
LevelSensorEntity(client, "bat_soc", "Battery Charge"),
DeciwattsSensorEntity(client, "bat_input_watts", "Battery Input Watts"),
DecivoltSensorEntity(client, "bat_input_volt", "Battery Input Potential"),
DecivoltSensorEntity(client, "bat_op_volt", "Battery Op Potential"),
AmpSensorEntity(client, "bat_input_cur", "Battery Input Current"),
DecicelsiusSensorEntity(client, "bat_temp", "Battery Temperature"),
RemainSensorEntity(client, "battery_charge_remain", "Charge Time"),
RemainSensorEntity(client, "battery_discharge_remain", "Discharge Time"),
MiscSensorEntity(client, "bat_error_code", "Battery Error Code", False),
MiscSensorEntity(client, "bat_warning_code", "Battery Warning Code", False),
MiscSensorEntity(client, "bat_status", "Battery Status", False),
DecivoltSensorEntity(client, "llc_input_volt", "LLC Input Potential", False),
DecivoltSensorEntity(client, "llc_op_volt", "LLC Op Potential", False),
MiscSensorEntity(client, "llc_error_code", "LLC Error Code", False),
MiscSensorEntity(client, "llc_warning_code", "LLC Warning Code", False),
MiscSensorEntity(client, "llc_status", "LLC Status", False),
MiscSensorEntity(client, "inv_on_off", "Inverter On/Off Status"),
DeciwattsSensorEntity(client, "inv_output_watts", "Inverter Output Watts"),
DecivoltSensorEntity(client, "inv_input_volt", "Inverter Output Potential", False),
DecivoltSensorEntity(client, "inv_op_volt", "Inverter Op Potential"),
AmpSensorEntity(client, "inv_output_cur", "Inverter Output Current"),
AmpSensorEntity(client, "inv_dc_cur", "Inverter DC Current"),
DecihertzSensorEntity(client, "inv_freq", "Inverter Frequency"),
DecicelsiusSensorEntity(client, "inv_temp", "Inverter Temperature"),
MiscSensorEntity(client, "inv_relay_status", "Inverter Relay Status"),
MiscSensorEntity(client, "inv_error_code", "Inverter Error Code", False),
MiscSensorEntity(client, "inv_warning_code", "Inverter Warning Code", False),
MiscSensorEntity(client, "inv_status", "Inverter Status", False),
DeciwattsSensorEntity(client, "permanent_watts", "Other Loads"),
DeciwattsSensorEntity(client, "dynamic_watts", "Smart Plug Loads"),
DeciwattsSensorEntity(client, "rated_power", "Rated Power"),
MiscSensorEntity(client, "lower_limit", "Lower Battery Limit", False),
MiscSensorEntity(client, "upper_limit", "Upper Battery Limit", False),
MiscSensorEntity(client, "wireless_error_code", "Wireless Error Code", False),
MiscSensorEntity(client, "wireless_warning_code", "Wireless Warning Code", False),
MiscSensorEntity(client, "inv_brightness", "LED Brightness", False),
MiscSensorEntity(client, "heartbeat_frequency", "Heartbeat Frequency", False),
StatusSensorEntity(client)
]
def numbers(self, client: EcoflowMQTTClient) -> list[BaseNumberEntity]:
return [
# These will likely be some form of serialised data rather than JSON will look into it later
# MinBatteryLevelEntity(client, "lowerLimit", "Min Disharge Level", 50, 100,
# lambda value: {"moduleType": 0, "operateType": "TCP",
# "params": {"id": 00, "lowerLimit": value}}),
# MaxBatteryLevelEntity(client, "upperLimit", "Max Charge Level", 0, 30,
# lambda value: {"moduleType": 0, "operateType": "TCP",
# "params": {"id": 00, "upperLimit": value}}),
]
def switches(self, client: EcoflowMQTTClient) -> list[BaseSwitchEntity]:
return []
def selects(self, client: EcoflowMQTTClient) -> list[BaseSelectEntity]:
return [
# DictSelectEntity(client, "supplyPriority", "Power supply mode", {"Prioritize power supply", "Prioritize power storage"},
# lambda value: {"moduleType": 00, "operateType": "supplyPriority",
# "params": {"supplyPriority": value}}),
]
@@ -0,0 +1,32 @@
from custom_components.ecoflow_cloud.config_flow import EcoflowModel
from custom_components.ecoflow_cloud.devices import BaseDevice, DiagnosticDevice
from custom_components.ecoflow_cloud.devices.delta2 import Delta2
from custom_components.ecoflow_cloud.devices.delta_mini import DeltaMini
from custom_components.ecoflow_cloud.devices.delta_pro import DeltaPro
from custom_components.ecoflow_cloud.devices.river2 import River2
from custom_components.ecoflow_cloud.devices.river2_max import River2Max
from custom_components.ecoflow_cloud.devices.river2_pro import River2Pro
from custom_components.ecoflow_cloud.devices.river_max import RiverMax
from custom_components.ecoflow_cloud.devices.river_pro import RiverPro
from custom_components.ecoflow_cloud.devices.delta_max import DeltaMax
from custom_components.ecoflow_cloud.devices.delta2_max import Delta2Max
from custom_components.ecoflow_cloud.devices.powerstream import PowerStream
from custom_components.ecoflow_cloud.devices.glacier import Glacier
from custom_components.ecoflow_cloud.devices.wave2 import Wave2
devices: dict[str, BaseDevice] = {
EcoflowModel.DELTA_2.name: Delta2(),
EcoflowModel.RIVER_2.name: River2(),
EcoflowModel.RIVER_2_MAX.name: River2Max(),
EcoflowModel.RIVER_2_PRO.name: River2Pro(),
EcoflowModel.DELTA_PRO.name: DeltaPro(),
EcoflowModel.RIVER_MAX.name: RiverMax(),
EcoflowModel.RIVER_PRO.name: RiverPro(),
EcoflowModel.DELTA_MINI.name: DeltaMini(),
EcoflowModel.DELTA_MAX.name: DeltaMax(),
EcoflowModel.DELTA_2_MAX.name: Delta2Max(),
EcoflowModel.POWERSTREAM.name: PowerStream(),
EcoflowModel.GLACIER.name: Glacier(),
EcoflowModel.WAVE_2.name: Wave2(),
EcoflowModel.DIAGNOSTIC.name: DiagnosticDevice()
}
@@ -0,0 +1,135 @@
from homeassistant.const import Platform
from . import const, BaseDevice, EntityMigration, MigrationAction
from ..entities import BaseSensorEntity, BaseNumberEntity, BaseSwitchEntity, BaseSelectEntity
from ..mqtt.ecoflow_mqtt import EcoflowMQTTClient
from ..number import ChargingPowerEntity, MaxBatteryLevelEntity, MinBatteryLevelEntity
from ..select import DictSelectEntity, TimeoutDictSelectEntity
from ..sensor import LevelSensorEntity, RemainSensorEntity, TempSensorEntity, \
CyclesSensorEntity, InWattsSensorEntity, OutWattsSensorEntity, VoltSensorEntity, StatusSensorEntity, \
MilliVoltSensorEntity, InMilliVoltSensorEntity, OutMilliVoltSensorEntity, ChargingStateSensorEntity, \
CapacitySensorEntity
from ..switch import EnabledEntity
class River2(BaseDevice):
def charging_power_step(self) -> int:
return 50
def sensors(self, client: EcoflowMQTTClient) -> list[BaseSensorEntity]:
return [
LevelSensorEntity(client, "bms_bmsStatus.soc", const.MAIN_BATTERY_LEVEL)
.attr("bms_bmsStatus.designCap", const.ATTR_DESIGN_CAPACITY, 0)
.attr("bms_bmsStatus.fullCap", const.ATTR_FULL_CAPACITY, 0)
.attr("bms_bmsStatus.remainCap", const.ATTR_REMAIN_CAPACITY, 0),
CapacitySensorEntity(client, "bms_bmsStatus.designCap", const.MAIN_DESIGN_CAPACITY, False),
CapacitySensorEntity(client, "bms_bmsStatus.fullCap", const.MAIN_FULL_CAPACITY, False),
CapacitySensorEntity(client, "bms_bmsStatus.remainCap", const.MAIN_REMAIN_CAPACITY, False),
LevelSensorEntity(client, "bms_bmsStatus.soh", const.SOH),
LevelSensorEntity(client, "bms_emsStatus.lcdShowSoc", const.COMBINED_BATTERY_LEVEL),
ChargingStateSensorEntity(client, "bms_emsStatus.chgState", const.BATTERY_CHARGING_STATE),
InWattsSensorEntity(client, "pd.wattsInSum", const.TOTAL_IN_POWER),
OutWattsSensorEntity(client, "pd.wattsOutSum", const.TOTAL_OUT_POWER),
InWattsSensorEntity(client, "inv.inputWatts", const.AC_IN_POWER),
OutWattsSensorEntity(client, "inv.outputWatts", const.AC_OUT_POWER),
InMilliVoltSensorEntity(client, "inv.acInVol", const.AC_IN_VOLT),
OutMilliVoltSensorEntity(client, "inv.invOutVol", const.AC_OUT_VOLT),
InWattsSensorEntity(client, "pd.typecChaWatts", const.TYPE_C_IN_POWER),
InWattsSensorEntity(client, "mppt.inWatts", const.SOLAR_IN_POWER),
OutWattsSensorEntity(client, "pd.carWatts", const.DC_OUT_POWER),
OutWattsSensorEntity(client, "pd.typec1Watts", const.TYPEC_1_OUT_POWER),
# both USB-A Ports (the small RIVER 2 has only two) are being summarized under "pd.usb1Watts" - https://github.com/tolwi/hassio-ecoflow-cloud/issues/12#issuecomment-1432837393
OutWattsSensorEntity(client, "pd.usb1Watts", const.USB_OUT_POWER),
RemainSensorEntity(client, "bms_emsStatus.chgRemainTime", const.CHARGE_REMAINING_TIME),
RemainSensorEntity(client, "bms_emsStatus.dsgRemainTime", const.DISCHARGE_REMAINING_TIME),
TempSensorEntity(client, "inv.outTemp", "Inv Out Temperature"),
CyclesSensorEntity(client, "bms_bmsStatus.cycles", const.CYCLES),
TempSensorEntity(client, "bms_bmsStatus.temp", const.BATTERY_TEMP)
.attr("bms_bmsStatus.minCellTemp", const.ATTR_MIN_CELL_TEMP, 0)
.attr("bms_bmsStatus.maxCellTemp", const.ATTR_MAX_CELL_TEMP, 0),
TempSensorEntity(client, "bms_bmsStatus.minCellTemp", const.MIN_CELL_TEMP, False),
TempSensorEntity(client, "bms_bmsStatus.maxCellTemp", const.MAX_CELL_TEMP, False),
VoltSensorEntity(client, "bms_bmsStatus.vol", const.BATTERY_VOLT, False)
.attr("bms_bmsStatus.minCellVol", const.ATTR_MIN_CELL_VOLT, 0)
.attr("bms_bmsStatus.maxCellVol", const.ATTR_MAX_CELL_VOLT, 0),
MilliVoltSensorEntity(client, "bms_bmsStatus.minCellVol", const.MIN_CELL_VOLT, False),
MilliVoltSensorEntity(client, "bms_bmsStatus.maxCellVol", const.MAX_CELL_VOLT, False),
# FanSensorEntity(client, "bms_emsStatus.fanLevel", "Fan Level"),
StatusSensorEntity(client),
]
def numbers(self, client: EcoflowMQTTClient) -> list[BaseNumberEntity]:
return [
MaxBatteryLevelEntity(client, "bms_emsStatus.maxChargeSoc", const.MAX_CHARGE_LEVEL, 50, 100,
lambda value: {"moduleType": 2, "operateType": "upsConfig",
"params": {"maxChgSoc": int(value)}}),
MinBatteryLevelEntity(client, "bms_emsStatus.minDsgSoc", const.MIN_DISCHARGE_LEVEL, 0, 30,
lambda value: {"moduleType": 2, "operateType": "dsgCfg",
"params": {"minDsgSoc": int(value)}}),
ChargingPowerEntity(client, "mppt.cfgChgWatts", const.AC_CHARGING_POWER, 100, 360,
lambda value: {"moduleType": 5, "operateType": "acChgCfg",
"params": {"chgWatts": int(value), "chgPauseFlag": 255}}),
]
def switches(self, client: EcoflowMQTTClient) -> list[BaseSwitchEntity]:
return [
EnabledEntity(client, "mppt.cfgAcEnabled", const.AC_ENABLED,
lambda value: {"moduleType": 5, "operateType": "acOutCfg",
"params": {"enabled": value, "out_voltage": -1, "out_freq": 255,
"xboost": 255}}),
EnabledEntity(client, "mppt.cfgAcXboost", const.XBOOST_ENABLED,
lambda value: {"moduleType": 5, "operateType": "acOutCfg",
"params": {"enabled": 255, "out_voltage": -1, "out_freq": 255,
"xboost": value}}),
EnabledEntity(client, "pd.carState", const.DC_ENABLED,
lambda value: {"moduleType": 5, "operateType": "mpptCar", "params": {"enabled": value}})
]
def selects(self, client: EcoflowMQTTClient) -> list[BaseSelectEntity]:
return [
DictSelectEntity(client, "mppt.dcChgCurrent", const.DC_CHARGE_CURRENT, const.DC_CHARGE_CURRENT_OPTIONS,
lambda value: {"moduleType": 5, "operateType": "dcChgCfg",
"params": {"dcChgCfg": value}}),
DictSelectEntity(client, "mppt.cfgChgType", const.DC_MODE, const.DC_MODE_OPTIONS,
lambda value: {"moduleType": 5, "operateType": "chaType",
"params": {"chaType": value}}),
TimeoutDictSelectEntity(client, "mppt.scrStandbyMin", const.SCREEN_TIMEOUT, const.SCREEN_TIMEOUT_OPTIONS,
lambda value: {"moduleType": 5, "operateType": "lcdCfg",
"params": {"brighLevel": 255, "delayOff": value}}),
TimeoutDictSelectEntity(client, "mppt.powStandbyMin", const.UNIT_TIMEOUT, const.UNIT_TIMEOUT_OPTIONS,
lambda value: {"moduleType": 5, "operateType": "standby",
"params": {"standbyMins": value}}),
TimeoutDictSelectEntity(client, "mppt.acStandbyMins", const.AC_TIMEOUT, const.AC_TIMEOUT_OPTIONS,
lambda value: {"moduleType": 5, "operateType": "acStandby",
"params": {"standbyMins": value}})
]
def migrate(self, version) -> list[EntityMigration]:
if version == 2:
return [
EntityMigration("pd.soc", Platform.SENSOR, MigrationAction.REMOVE),
]
return []
@@ -0,0 +1,163 @@
from homeassistant.const import Platform
from . import const, BaseDevice, EntityMigration, MigrationAction
from .const import ATTR_DESIGN_CAPACITY, ATTR_FULL_CAPACITY, ATTR_REMAIN_CAPACITY, BATTERY_CHARGING_STATE, \
MAIN_DESIGN_CAPACITY, MAIN_FULL_CAPACITY, MAIN_REMAIN_CAPACITY
from ..entities import BaseSensorEntity, BaseNumberEntity, BaseSwitchEntity, BaseSelectEntity
from ..mqtt.ecoflow_mqtt import EcoflowMQTTClient
from ..number import ChargingPowerEntity, MaxBatteryLevelEntity, MinBatteryLevelEntity, BatteryBackupLevel
from ..select import DictSelectEntity, TimeoutDictSelectEntity
from ..sensor import LevelSensorEntity, RemainSensorEntity, TempSensorEntity, \
CyclesSensorEntity, InWattsSensorEntity, OutWattsSensorEntity, VoltSensorEntity, InAmpSensorEntity, \
InVoltSensorEntity, QuotasStatusSensorEntity, MilliVoltSensorEntity, InMilliVoltSensorEntity, \
OutMilliVoltSensorEntity, ChargingStateSensorEntity, CapacitySensorEntity
from ..switch import EnabledEntity
class River2Max(BaseDevice):
def charging_power_step(self) -> int:
return 50
def sensors(self, client: EcoflowMQTTClient) -> list[BaseSensorEntity]:
return [
LevelSensorEntity(client, "bms_bmsStatus.soc", const.MAIN_BATTERY_LEVEL)
.attr("bms_bmsStatus.designCap", ATTR_DESIGN_CAPACITY, 0)
.attr("bms_bmsStatus.fullCap", ATTR_FULL_CAPACITY, 0)
.attr("bms_bmsStatus.remainCap", ATTR_REMAIN_CAPACITY, 0),
CapacitySensorEntity(client, "bms_bmsStatus.designCap", MAIN_DESIGN_CAPACITY, False),
CapacitySensorEntity(client, "bms_bmsStatus.fullCap", MAIN_FULL_CAPACITY, False),
CapacitySensorEntity(client, "bms_bmsStatus.remainCap", MAIN_REMAIN_CAPACITY, False),
LevelSensorEntity(client, "bms_bmsStatus.soh", const.SOH),
LevelSensorEntity(client, "bms_emsStatus.lcdShowSoc", const.COMBINED_BATTERY_LEVEL),
ChargingStateSensorEntity(client, "bms_emsStatus.chgState", BATTERY_CHARGING_STATE),
InWattsSensorEntity(client, "pd.wattsInSum", const.TOTAL_IN_POWER),
OutWattsSensorEntity(client, "pd.wattsOutSum", const.TOTAL_OUT_POWER),
InAmpSensorEntity(client, "inv.dcInAmp", const.SOLAR_IN_CURRENT),
InVoltSensorEntity(client, "inv.dcInVol", const.SOLAR_IN_VOLTAGE),
InWattsSensorEntity(client, "inv.inputWatts", const.AC_IN_POWER),
OutWattsSensorEntity(client, "inv.outputWatts", const.AC_OUT_POWER),
InMilliVoltSensorEntity(client, "inv.acInVol", const.AC_IN_VOLT),
OutMilliVoltSensorEntity(client, "inv.invOutVol", const.AC_OUT_VOLT),
InWattsSensorEntity(client, "pd.typecChaWatts", const.TYPE_C_IN_POWER),
InWattsSensorEntity(client, "mppt.inWatts", const.SOLAR_IN_POWER),
OutWattsSensorEntity(client, "pd.carWatts", const.DC_OUT_POWER),
OutWattsSensorEntity(client, "pd.typec1Watts", const.TYPEC_OUT_POWER),
OutWattsSensorEntity(client, "pd.usb1Watts", const.USB_OUT_POWER),
# OutWattsSensorEntity(client, "pd.usb2Watts", const.USB_2_OUT_POWER),
RemainSensorEntity(client, "bms_emsStatus.chgRemainTime", const.CHARGE_REMAINING_TIME),
RemainSensorEntity(client, "bms_emsStatus.dsgRemainTime", const.DISCHARGE_REMAINING_TIME),
RemainSensorEntity(client, "pd.remainTime", const.REMAINING_TIME),
TempSensorEntity(client, "inv.outTemp", "Inv Out Temperature"),
CyclesSensorEntity(client, "bms_bmsStatus.cycles", const.CYCLES),
TempSensorEntity(client, "bms_bmsStatus.temp", const.BATTERY_TEMP)
.attr("bms_bmsStatus.minCellTemp", const.ATTR_MIN_CELL_TEMP, 0)
.attr("bms_bmsStatus.maxCellTemp", const.ATTR_MAX_CELL_TEMP, 0),
TempSensorEntity(client, "bms_bmsStatus.minCellTemp", const.MIN_CELL_TEMP, False),
TempSensorEntity(client, "bms_bmsStatus.maxCellTemp", const.MAX_CELL_TEMP, False),
VoltSensorEntity(client, "bms_bmsStatus.vol", const.BATTERY_VOLT, False)
.attr("bms_bmsStatus.minCellVol", const.ATTR_MIN_CELL_VOLT, 0)
.attr("bms_bmsStatus.maxCellVol", const.ATTR_MAX_CELL_VOLT, 0),
MilliVoltSensorEntity(client, "bms_bmsStatus.minCellVol", const.MIN_CELL_VOLT, False),
MilliVoltSensorEntity(client, "bms_bmsStatus.maxCellVol", const.MAX_CELL_VOLT, False),
QuotasStatusSensorEntity(client),
# FanSensorEntity(client, "bms_emsStatus.fanLevel", "Fan Level"),
]
def numbers(self, client: EcoflowMQTTClient) -> list[BaseNumberEntity]:
return [
MaxBatteryLevelEntity(client, "bms_emsStatus.maxChargeSoc", const.MAX_CHARGE_LEVEL, 50, 100,
lambda value: {"moduleType": 2, "operateType": "upsConfig",
"params": {"maxChgSoc": int(value)}}),
MinBatteryLevelEntity(client, "bms_emsStatus.minDsgSoc", const.MIN_DISCHARGE_LEVEL, 0, 30,
lambda value: {"moduleType": 2, "operateType": "dsgCfg",
"params": {"minDsgSoc": int(value)}}),
ChargingPowerEntity(client, "mppt.cfgChgWatts", const.AC_CHARGING_POWER, 50, 660,
lambda value: {"moduleType": 5, "operateType": "acChgCfg",
"params": {"chgWatts": int(value), "chgPauseFlag": 255}}),
BatteryBackupLevel(client, "pd.bpPowerSoc", const.BACKUP_RESERVE_LEVEL, 5, 100,
"bms_emsStatus.minDsgSoc", "bms_emsStatus.maxChargeSoc",
lambda value: {"moduleType": 1, "operateType": "watthConfig",
"params": {"isConfig": 1,
"bpPowerSoc": int(value),
"minDsgSoc": 0,
"minChgSoc": 0}}),
]
def switches(self, client: EcoflowMQTTClient) -> list[BaseSwitchEntity]:
return [
EnabledEntity(client, "mppt.cfgAcEnabled", const.AC_ENABLED,
lambda value: {"moduleType": 5, "operateType": "acOutCfg",
"params": {"enabled": value, "out_voltage": -1, "out_freq": 255,
"xboost": 255}}),
EnabledEntity(client, "pd.acAutoOutConfig", const.AC_ALWAYS_ENABLED,
lambda value, params: {"moduleType": 1, "operateType": "acAutoOutConfig",
"params": {"acAutoOutConfig": value,
"minAcOutSoc": int(params.get("bms_emsStatus.minDsgSoc", 0)) + 5}}
),
EnabledEntity(client, "mppt.cfgAcXboost", const.XBOOST_ENABLED,
lambda value: {"moduleType": 5, "operateType": "acOutCfg",
"params": {"enabled": 255, "out_voltage": -1, "out_freq": 255,
"xboost": value}}),
EnabledEntity(client, "pd.carState", const.DC_ENABLED,
lambda value: {"moduleType": 5, "operateType": "mpptCar", "params": {"enabled": value}}),
EnabledEntity(client, "pd.bpPowerSoc", const.BP_ENABLED,
lambda value, params: {"moduleType": 1, "operateType": "watthConfig",
"params": {"isConfig": value,
"bpPowerSoc": value,
"minDsgSoc": 0,
"minChgSoc": 0}})
]
def selects(self, client: EcoflowMQTTClient) -> list[BaseSelectEntity]:
return [
DictSelectEntity(client, "mppt.dcChgCurrent", const.DC_CHARGE_CURRENT, const.DC_CHARGE_CURRENT_OPTIONS,
lambda value: {"moduleType": 5, "operateType": "dcChgCfg",
"params": {"dcChgCfg": value}}),
DictSelectEntity(client, "mppt.cfgChgType", const.DC_MODE, const.DC_MODE_OPTIONS,
lambda value: {"moduleType": 5, "operateType": "chaType",
"params": {"chaType": value}}),
TimeoutDictSelectEntity(client, "mppt.scrStandbyMin", const.SCREEN_TIMEOUT, const.SCREEN_TIMEOUT_OPTIONS,
lambda value: {"moduleType": 5, "operateType": "lcdCfg",
"params": {"brighLevel": 255, "delayOff": value}}),
TimeoutDictSelectEntity(client, "mppt.powStandbyMin", const.UNIT_TIMEOUT, const.UNIT_TIMEOUT_OPTIONS,
lambda value: {"moduleType": 5, "operateType": "standby",
"params": {"standbyMins": value}}),
TimeoutDictSelectEntity(client, "mppt.acStandbyMins", const.AC_TIMEOUT, const.AC_TIMEOUT_OPTIONS,
lambda value: {"moduleType": 5, "operateType": "acStandby",
"params": {"standbyMins": value}})
]
def migrate(self, version) -> list[EntityMigration]:
if version == 2:
return [
EntityMigration("pd.soc", Platform.SENSOR, MigrationAction.REMOVE),
]
return []
@@ -0,0 +1,136 @@
from homeassistant.const import Platform
from . import const, BaseDevice, EntityMigration, MigrationAction
from ..entities import BaseSensorEntity, BaseNumberEntity, BaseSwitchEntity, BaseSelectEntity
from ..mqtt.ecoflow_mqtt import EcoflowMQTTClient
from ..number import ChargingPowerEntity, MaxBatteryLevelEntity, MinBatteryLevelEntity
from ..select import DictSelectEntity, TimeoutDictSelectEntity
from ..sensor import LevelSensorEntity, RemainSensorEntity, TempSensorEntity, \
CyclesSensorEntity, InWattsSensorEntity, OutWattsSensorEntity, VoltSensorEntity, QuotasStatusSensorEntity, \
MilliVoltSensorEntity, InMilliVoltSensorEntity, OutMilliVoltSensorEntity, ChargingStateSensorEntity, \
CapacitySensorEntity
from ..switch import EnabledEntity
class River2Pro(BaseDevice):
def charging_power_step(self) -> int:
return 50
def sensors(self, client: EcoflowMQTTClient) -> list[BaseSensorEntity]:
return [
LevelSensorEntity(client, "bms_bmsStatus.soc", const.MAIN_BATTERY_LEVEL)
.attr("bms_bmsStatus.designCap", const.ATTR_DESIGN_CAPACITY, 0)
.attr("bms_bmsStatus.fullCap", const.ATTR_FULL_CAPACITY, 0)
.attr("bms_bmsStatus.remainCap", const.ATTR_REMAIN_CAPACITY, 0),
CapacitySensorEntity(client, "bms_bmsStatus.designCap", const.MAIN_DESIGN_CAPACITY, False),
CapacitySensorEntity(client, "bms_bmsStatus.fullCap", const.MAIN_FULL_CAPACITY, False),
CapacitySensorEntity(client, "bms_bmsStatus.remainCap", const.MAIN_REMAIN_CAPACITY, False),
LevelSensorEntity(client, "bms_bmsStatus.soh", const.SOH),
LevelSensorEntity(client, "bms_emsStatus.lcdShowSoc", const.COMBINED_BATTERY_LEVEL),
ChargingStateSensorEntity(client, "bms_emsStatus.chgState", const.BATTERY_CHARGING_STATE),
InWattsSensorEntity(client, "pd.wattsInSum", const.TOTAL_IN_POWER),
OutWattsSensorEntity(client, "pd.wattsOutSum", const.TOTAL_OUT_POWER),
InWattsSensorEntity(client, "inv.inputWatts", const.AC_IN_POWER),
OutWattsSensorEntity(client, "inv.outputWatts", const.AC_OUT_POWER),
InMilliVoltSensorEntity(client, "inv.acInVol", const.AC_IN_VOLT),
OutMilliVoltSensorEntity(client, "inv.invOutVol", const.AC_OUT_VOLT),
InWattsSensorEntity(client, "pd.typecChaWatts", const.TYPE_C_IN_POWER),
InWattsSensorEntity(client, "mppt.inWatts", const.SOLAR_IN_POWER),
OutWattsSensorEntity(client, "pd.carWatts", const.DC_OUT_POWER),
OutWattsSensorEntity(client, "pd.typec1Watts", const.TYPEC_OUT_POWER),
OutWattsSensorEntity(client, "pd.usb1Watts", const.USB_OUT_POWER),
# OutWattsSensorEntity(client, "pd.usb2Watts", const.USB_2_OUT_POWER),
RemainSensorEntity(client, "bms_emsStatus.chgRemainTime", const.CHARGE_REMAINING_TIME),
RemainSensorEntity(client, "bms_emsStatus.dsgRemainTime", const.DISCHARGE_REMAINING_TIME),
RemainSensorEntity(client, "pd.remainTime", const.REMAINING_TIME),
TempSensorEntity(client, "inv.outTemp", "Inv Out Temperature"),
CyclesSensorEntity(client, "bms_bmsStatus.cycles", const.CYCLES),
TempSensorEntity(client, "bms_bmsStatus.temp", const.BATTERY_TEMP)
.attr("bms_bmsStatus.minCellTemp", const.ATTR_MIN_CELL_TEMP, 0)
.attr("bms_bmsStatus.maxCellTemp", const.ATTR_MAX_CELL_TEMP, 0),
TempSensorEntity(client, "bms_bmsStatus.minCellTemp", const.MIN_CELL_TEMP, False),
TempSensorEntity(client, "bms_bmsStatus.maxCellTemp", const.MAX_CELL_TEMP, False),
VoltSensorEntity(client, "bms_bmsStatus.vol", const.BATTERY_VOLT, False)
.attr("bms_bmsStatus.minCellVol", const.ATTR_MIN_CELL_VOLT, 0)
.attr("bms_bmsStatus.maxCellVol", const.ATTR_MAX_CELL_VOLT, 0),
MilliVoltSensorEntity(client, "bms_bmsStatus.minCellVol", const.MIN_CELL_VOLT, False),
MilliVoltSensorEntity(client, "bms_bmsStatus.maxCellVol", const.MAX_CELL_VOLT, False),
# FanSensorEntity(client, "bms_emsStatus.fanLevel", "Fan Level"),
QuotasStatusSensorEntity(client),
]
def numbers(self, client: EcoflowMQTTClient) -> list[BaseNumberEntity]:
return [
MaxBatteryLevelEntity(client, "bms_emsStatus.maxChargeSoc", const.MAX_CHARGE_LEVEL, 50, 100,
lambda value: {"moduleType": 2, "operateType": "upsConfig",
"params": {"maxChgSoc": int(value)}}),
MinBatteryLevelEntity(client, "bms_emsStatus.minDsgSoc", const.MIN_DISCHARGE_LEVEL, 0, 30,
lambda value: {"moduleType": 2, "operateType": "dsgCfg",
"params": {"minDsgSoc": int(value)}}),
ChargingPowerEntity(client, "mppt.cfgChgWatts", const.AC_CHARGING_POWER, 100, 950,
lambda value: {"moduleType": 5, "operateType": "acChgCfg",
"params": {"chgWatts": int(value), "chgPauseFlag": 255}}),
]
def switches(self, client: EcoflowMQTTClient) -> list[BaseSwitchEntity]:
return [
EnabledEntity(client, "mppt.cfgAcEnabled", const.AC_ENABLED,
lambda value: {"moduleType": 5, "operateType": "acOutCfg",
"params": {"enabled": value, "out_voltage": -1, "out_freq": 255,
"xboost": 255}}),
EnabledEntity(client, "mppt.cfgAcXboost", const.XBOOST_ENABLED,
lambda value: {"moduleType": 5, "operateType": "acOutCfg",
"params": {"enabled": 255, "out_voltage": -1, "out_freq": 255,
"xboost": value}}),
EnabledEntity(client, "pd.carState", const.DC_ENABLED,
lambda value: {"moduleType": 5, "operateType": "mpptCar", "params": {"enabled": value}})
]
def selects(self, client: EcoflowMQTTClient) -> list[BaseSelectEntity]:
return [
DictSelectEntity(client, "mppt.dcChgCurrent", const.DC_CHARGE_CURRENT, const.DC_CHARGE_CURRENT_OPTIONS,
lambda value: {"moduleType": 5, "operateType": "dcChgCfg",
"params": {"dcChgCfg": value}}),
DictSelectEntity(client, "mppt.cfgChgType", const.DC_MODE, const.DC_MODE_OPTIONS,
lambda value: {"moduleType": 5, "operateType": "chaType",
"params": {"chaType": value}}),
TimeoutDictSelectEntity(client, "mppt.scrStandbyMin", const.SCREEN_TIMEOUT, const.SCREEN_TIMEOUT_OPTIONS,
lambda value: {"moduleType": 5, "operateType": "lcdCfg",
"params": {"brighLevel": 255, "delayOff": value}}),
TimeoutDictSelectEntity(client, "mppt.powStandbyMin", const.UNIT_TIMEOUT, const.UNIT_TIMEOUT_OPTIONS,
lambda value: {"moduleType": 5, "operateType": "standby",
"params": {"standbyMins": value}}),
TimeoutDictSelectEntity(client, "mppt.acStandbyMins", const.AC_TIMEOUT, const.AC_TIMEOUT_OPTIONS,
lambda value: {"moduleType": 5, "operateType": "acStandby",
"params": {"standbyMins": value}})
]
def migrate(self, version) -> list[EntityMigration]:
if version == 2:
return [
EntityMigration("pd.soc", Platform.SENSOR, MigrationAction.REMOVE),
]
return []
@@ -0,0 +1,117 @@
from homeassistant.const import Platform
from . import const, BaseDevice, MigrationAction, EntityMigration
from ..entities import BaseSensorEntity, BaseNumberEntity, BaseSwitchEntity, BaseSelectEntity
from ..mqtt.ecoflow_mqtt import EcoflowMQTTClient
from ..number import MaxBatteryLevelEntity
from ..select import DictSelectEntity
from ..sensor import LevelSensorEntity, WattsSensorEntity, RemainSensorEntity, TempSensorEntity, \
CyclesSensorEntity, InWattsSensorEntity, OutWattsSensorEntity, StatusSensorEntity, \
InEnergySensorEntity, OutEnergySensorEntity, MilliVoltSensorEntity, InMilliVoltSensorEntity, \
OutMilliVoltSensorEntity, CapacitySensorEntity
from ..switch import EnabledEntity, BeeperEntity
class RiverMax(BaseDevice):
def sensors(self, client: EcoflowMQTTClient) -> list[BaseSensorEntity]:
return [
LevelSensorEntity(client, "bmsMaster.soc", const.MAIN_BATTERY_LEVEL)
.attr("bmsMaster.designCap", const.ATTR_DESIGN_CAPACITY, 0)
.attr("bmsMaster.fullCap", const.ATTR_FULL_CAPACITY, 0)
.attr("bmsMaster.remainCap", const.ATTR_REMAIN_CAPACITY, 0),
CapacitySensorEntity(client, "bmsMaster.designCap", const.MAIN_DESIGN_CAPACITY, False),
CapacitySensorEntity(client, "bmsMaster.fullCap", const.MAIN_FULL_CAPACITY, False),
CapacitySensorEntity(client, "bmsMaster.remainCap", const.MAIN_REMAIN_CAPACITY, False),
WattsSensorEntity(client, "pd.wattsInSum", const.TOTAL_IN_POWER),
WattsSensorEntity(client, "pd.wattsOutSum", const.TOTAL_OUT_POWER),
InWattsSensorEntity(client, "inv.inputWatts", const.AC_IN_POWER),
OutWattsSensorEntity(client, "inv.outputWatts", const.AC_OUT_POWER),
InMilliVoltSensorEntity(client, "inv.acInVol", const.AC_IN_VOLT),
OutMilliVoltSensorEntity(client, "inv.invOutVol", const.AC_OUT_VOLT),
OutWattsSensorEntity(client, "pd.carWatts", const.DC_OUT_POWER),
OutWattsSensorEntity(client, "pd.typecWatts", const.TYPEC_OUT_POWER),
OutWattsSensorEntity(client, "pd.usb1Watts", const.USB_1_OUT_POWER),
OutWattsSensorEntity(client, "pd.usb2Watts", const.USB_2_OUT_POWER),
OutWattsSensorEntity(client, "pd.usb3Watts", const.USB_3_OUT_POWER),
RemainSensorEntity(client, "pd.remainTime", const.REMAINING_TIME),
CyclesSensorEntity(client, "bmsMaster.cycles", const.CYCLES),
TempSensorEntity(client, "bmsMaster.temp", const.BATTERY_TEMP)
.attr("bmsMaster.minCellTemp", const.ATTR_MIN_CELL_TEMP, 0)
.attr("bmsMaster.maxCellTemp", const.ATTR_MAX_CELL_TEMP, 0),
TempSensorEntity(client, "bmsMaster.minCellTemp", const.MIN_CELL_TEMP, False),
TempSensorEntity(client, "bmsMaster.maxCellTemp", const.MAX_CELL_TEMP, False),
MilliVoltSensorEntity(client, "bmsMaster.vol", const.BATTERY_VOLT, False)
.attr("bmsMaster.minCellVol", const.ATTR_MIN_CELL_VOLT, 0)
.attr("bmsMaster.maxCellVol", const.ATTR_MAX_CELL_VOLT, 0),
MilliVoltSensorEntity(client, "bmsMaster.minCellVol", const.MIN_CELL_VOLT, False),
MilliVoltSensorEntity(client, "bmsMaster.maxCellVol", const.MAX_CELL_VOLT, False),
# https://github.com/tolwi/hassio-ecoflow-cloud/discussions/87
InEnergySensorEntity(client, "pd.chgSunPower", const.SOLAR_IN_ENERGY),
InEnergySensorEntity(client, "pd.chgPowerAC", const.CHARGE_AC_ENERGY),
InEnergySensorEntity(client, "pd.chgPowerDC", const.CHARGE_DC_ENERGY),
OutEnergySensorEntity(client, "pd.dsgPowerAC", const.DISCHARGE_AC_ENERGY),
OutEnergySensorEntity(client, "pd.dsgPowerDC", const.DISCHARGE_DC_ENERGY),
LevelSensorEntity(client, "bmsSlave1.soc", const.SLAVE_BATTERY_LEVEL, False, True)
.attr("bmsSlave1.designCap", const.ATTR_DESIGN_CAPACITY, 0)
.attr("bmsSlave1.fullCap", const.ATTR_FULL_CAPACITY, 0)
.attr("bmsSlave1.remainCap", const.ATTR_REMAIN_CAPACITY, 0),
CapacitySensorEntity(client, "bmsSlave1.designCap", const.SLAVE_DESIGN_CAPACITY, False),
CapacitySensorEntity(client, "bmsSlave1.fullCap", const.SLAVE_FULL_CAPACITY, False),
CapacitySensorEntity(client, "bmsSlave1.remainCap", const.SLAVE_REMAIN_CAPACITY, False),
TempSensorEntity(client, "bmsSlave1.temp", const.SLAVE_BATTERY_TEMP, False, True)
.attr("bmsSlave1.minCellTemp", const.ATTR_MIN_CELL_TEMP, 0)
.attr("bmsSlave1.maxCellTemp", const.ATTR_MAX_CELL_TEMP, 0),
TempSensorEntity(client, "bmsSlave1.minCellTemp", const.SLAVE_MIN_CELL_TEMP, False),
TempSensorEntity(client, "bmsSlave1.maxCellTemp", const.SLAVE_MAX_CELL_TEMP, False),
MilliVoltSensorEntity(client, "bmsSlave1.vol", const.BATTERY_VOLT, False)
.attr("bmsSlave1.minCellVol", const.ATTR_MIN_CELL_VOLT, 0)
.attr("bmsSlave1.maxCellVol", const.ATTR_MAX_CELL_VOLT, 0),
MilliVoltSensorEntity(client, "bmsSlave1.minCellVol", const.MIN_CELL_VOLT, False),
MilliVoltSensorEntity(client, "bmsSlave1.maxCellVol", const.MAX_CELL_VOLT, False),
CyclesSensorEntity(client, "bmsSlave1.cycles", const.SLAVE_CYCLES, False, True),
StatusSensorEntity(client),
]
def numbers(self, client: EcoflowMQTTClient) -> list[BaseNumberEntity]:
return [
MaxBatteryLevelEntity(client, "bmsMaster.maxChargeSoc", const.MAX_CHARGE_LEVEL, 30, 100, None),
# MinBatteryLevelEntity(client, "bmsMaster.minDsgSoc", const.MIN_DISCHARGE_LEVEL, 0, 30, None),
]
def switches(self, client: EcoflowMQTTClient) -> list[BaseSwitchEntity]:
return [
BeeperEntity(client, "pd.beepState", const.BEEPER, lambda value: {"moduleType": 0, "operateType": "TCP", "params": {"id": 38, "enabled": value}}),
EnabledEntity(client, "inv.cfgAcEnabled", const.AC_ENABLED, lambda value: {"moduleType": 0, "operateType": "TCP", "params": {"id": 66, "enabled": value}}),
EnabledEntity(client, "pd.carSwitch", const.DC_ENABLED, lambda value: {"moduleType": 0, "operateType": "TCP", "params": {"id": 34, "enabled": value}}),
EnabledEntity(client, "inv.cfgAcXboost", const.XBOOST_ENABLED, lambda value: {"moduleType": 0, "operateType": "TCP", "params": {"id": 66, "xboost": value}})
]
def selects(self, client: EcoflowMQTTClient) -> list[BaseSelectEntity]:
return [
DictSelectEntity(client, "pd.standByMode", const.UNIT_TIMEOUT, const.UNIT_TIMEOUT_OPTIONS, lambda value: {"moduleType": 0, "operateType": "TCP", "params": {"id": 33, "standByMode": value}}),
DictSelectEntity(client, "inv.cfgStandbyMin", const.AC_TIMEOUT, const.AC_TIMEOUT_OPTIONS, lambda value: {"moduleType": 0, "operateType": "TCP", "params": {"id": 153, "standByMins": value}}),
]
def migrate(self, version) -> list[EntityMigration]:
if version == 2:
return [
EntityMigration("pd.soc", Platform.SENSOR, MigrationAction.REMOVE),
]
return []
@@ -0,0 +1,138 @@
from homeassistant.const import Platform
from . import const, BaseDevice, EntityMigration, MigrationAction
from ..entities import BaseSensorEntity, BaseNumberEntity, BaseSwitchEntity, BaseSelectEntity
from ..mqtt.ecoflow_mqtt import EcoflowMQTTClient
from ..number import MaxBatteryLevelEntity
from ..select import TimeoutDictSelectEntity
from ..sensor import LevelSensorEntity, WattsSensorEntity, RemainSensorEntity, TempSensorEntity, \
CyclesSensorEntity, InEnergySensorEntity, InWattsSensorEntity, OutEnergySensorEntity, OutWattsSensorEntity, VoltSensorEntity, InVoltSensorEntity, \
InAmpSensorEntity, AmpSensorEntity, StatusSensorEntity, MilliVoltSensorEntity, InMilliVoltSensorEntity, \
OutMilliVoltSensorEntity, CapacitySensorEntity
from ..switch import EnabledEntity, BeeperEntity
class RiverPro(BaseDevice):
def sensors(self, client: EcoflowMQTTClient) -> list[BaseSensorEntity]:
return [
LevelSensorEntity(client, "bmsMaster.soc", const.MAIN_BATTERY_LEVEL)
.attr("bmsMaster.designCap", const.ATTR_DESIGN_CAPACITY, 0)
.attr("bmsMaster.fullCap", const.ATTR_FULL_CAPACITY, 0)
.attr("bmsMaster.remainCap", const.ATTR_REMAIN_CAPACITY, 0),
CapacitySensorEntity(client, "bmsMaster.designCap", const.MAIN_DESIGN_CAPACITY, False),
CapacitySensorEntity(client, "bmsMaster.fullCap", const.MAIN_FULL_CAPACITY, False),
CapacitySensorEntity(client, "bmsMaster.remainCap", const.MAIN_REMAIN_CAPACITY, False),
WattsSensorEntity(client, "pd.wattsInSum", const.TOTAL_IN_POWER),
WattsSensorEntity(client, "pd.wattsOutSum", const.TOTAL_OUT_POWER),
InAmpSensorEntity(client, "inv.dcInAmp", const.SOLAR_IN_CURRENT),
InVoltSensorEntity(client, "inv.dcInVol", const.SOLAR_IN_VOLTAGE),
InWattsSensorEntity(client, "inv.inputWatts", const.AC_IN_POWER),
OutWattsSensorEntity(client, "inv.outputWatts", const.AC_OUT_POWER),
InMilliVoltSensorEntity(client, "inv.acInVol", const.AC_IN_VOLT),
OutMilliVoltSensorEntity(client, "inv.invOutVol", const.AC_OUT_VOLT),
OutWattsSensorEntity(client, "pd.carWatts", const.DC_OUT_POWER),
OutWattsSensorEntity(client, "pd.typecWatts", const.TYPEC_OUT_POWER),
# disabled by default because they aren't terribly useful
TempSensorEntity(client, "pd.carTemp", const.DC_CAR_OUT_TEMP, False),
TempSensorEntity(client, "pd.typecTemp", const.USB_C_TEMP, False),
OutWattsSensorEntity(client, "pd.usb1Watts", const.USB_1_OUT_POWER),
OutWattsSensorEntity(client, "pd.usb2Watts", const.USB_2_OUT_POWER),
OutWattsSensorEntity(client, "pd.usb3Watts", const.USB_3_OUT_POWER),
RemainSensorEntity(client, "pd.remainTime", const.REMAINING_TIME),
TempSensorEntity(client, "bmsMaster.temp", const.BATTERY_TEMP)
.attr("bmsMaster.minCellTemp", const.ATTR_MIN_CELL_TEMP, 0)
.attr("bmsMaster.maxCellTemp", const.ATTR_MAX_CELL_TEMP, 0),
TempSensorEntity(client, "bmsMaster.minCellTemp", const.MIN_CELL_TEMP, False),
TempSensorEntity(client, "bmsMaster.maxCellTemp", const.MAX_CELL_TEMP, False),
TempSensorEntity(client, "inv.inTemp", const.INV_IN_TEMP),
TempSensorEntity(client, "inv.outTemp", const.INV_OUT_TEMP),
# https://github.com/tolwi/hassio-ecoflow-cloud/discussions/87
InEnergySensorEntity(client, "pd.chgSunPower", const.SOLAR_IN_ENERGY),
InEnergySensorEntity(client, "pd.chgPowerAC", const.CHARGE_AC_ENERGY),
InEnergySensorEntity(client, "pd.chgPowerDC", const.CHARGE_DC_ENERGY),
OutEnergySensorEntity(client, "pd.dsgPowerAC", const.DISCHARGE_AC_ENERGY),
OutEnergySensorEntity(client, "pd.dsgPowerDC", const.DISCHARGE_DC_ENERGY),
AmpSensorEntity(client, "bmsMaster.amp", const.BATTERY_AMP, False),
MilliVoltSensorEntity(client, "bmsMaster.vol", const.BATTERY_VOLT, False)
.attr("bmsMaster.minCellVol", const.ATTR_MIN_CELL_VOLT, 0)
.attr("bmsMaster.maxCellVol", const.ATTR_MAX_CELL_VOLT, 0),
MilliVoltSensorEntity(client, "bmsMaster.minCellVol", const.MIN_CELL_VOLT, False),
MilliVoltSensorEntity(client, "bmsMaster.maxCellVol", const.MAX_CELL_VOLT, False),
CyclesSensorEntity(client, "bmsMaster.cycles", const.CYCLES),
# Optional Slave Batteries
LevelSensorEntity(client, "bmsSlave1.soc", const.SLAVE_BATTERY_LEVEL, False, True)
.attr("bmsSlave1.designCap", const.ATTR_DESIGN_CAPACITY, 0)
.attr("bmsSlave1.fullCap", const.ATTR_FULL_CAPACITY, 0)
.attr("bmsSlave1.remainCap", const.ATTR_REMAIN_CAPACITY, 0),
CapacitySensorEntity(client, "bmsSlave1.designCap", const.SLAVE_DESIGN_CAPACITY, False),
CapacitySensorEntity(client, "bmsSlave1.fullCap", const.SLAVE_FULL_CAPACITY, False),
CapacitySensorEntity(client, "bmsSlave1.remainCap", const.SLAVE_REMAIN_CAPACITY, False),
CyclesSensorEntity(client, "bmsSlave1.cycles", const.SLAVE_CYCLES, False, True),
TempSensorEntity(client, "bmsSlave1.temp", const.SLAVE_BATTERY_TEMP, False, True)
.attr("bmsSlave1.minCellTemp", const.ATTR_MIN_CELL_TEMP, 0)
.attr("bmsSlave1.maxCellTemp", const.ATTR_MAX_CELL_TEMP, 0),
AmpSensorEntity(client, "bmsSlave1.amp", const.SLAVE_BATTERY_AMP, False),
MilliVoltSensorEntity(client, "bmsSlave1.vol", const.SLAVE_BATTERY_VOLT, False)
.attr("bmsSlave1.minCellVol", const.ATTR_MIN_CELL_VOLT, 0)
.attr("bmsSlave1.maxCellVol", const.ATTR_MAX_CELL_VOLT, 0),
MilliVoltSensorEntity(client, "bmsSlave1.minCellVol", const.SLAVE_MIN_CELL_VOLT, False),
MilliVoltSensorEntity(client, "bmsSlave1.maxCellVol", const.SLAVE_MAX_CELL_VOLT, False),
StatusSensorEntity(client),
]
def numbers(self, client: EcoflowMQTTClient) -> list[BaseNumberEntity]:
return [
MaxBatteryLevelEntity(client, "bmsMaster.maxChargeSoc", const.MAX_CHARGE_LEVEL, 30, 100,
lambda value: {"moduleType": 0, "operateType": "TCP",
"params": {"id": 49, "maxChgSoc": value}}),
# MinBatteryLevelEntity(client, "bmsMaster.minDsgSoc", const.MIN_DISCHARGE_LEVEL, 0, 30, None),
]
def switches(self, client: EcoflowMQTTClient) -> list[BaseSwitchEntity]:
return [
BeeperEntity(client, "pd.beepState", const.BEEPER, lambda value: {"moduleType": 0, "operateType": "TCP", "params": {"id": 38, "enabled": value}}),
EnabledEntity(client, "inv.acAutoOutConfig", const.AC_ALWAYS_ENABLED,
lambda value: {"moduleType": 0, "operateType": "TCP", "params": {"id": 95, "acautooutConfig": value, "minAcoutSoc": 255}}),
EnabledEntity(client, "pd.carSwitch", const.DC_ENABLED, lambda value: {"moduleType": 0, "operateType": "TCP", "params": {"id": 34, "enabled": value}}),
EnabledEntity(client, "inv.cfgAcEnabled", const.AC_ENABLED, lambda value: {"moduleType": 0, "operateType": "TCP", "params": {"id": 66, "enabled": value}}),
EnabledEntity(client, "inv.cfgAcXboost", const.XBOOST_ENABLED, lambda value: {"moduleType": 0, "operateType": "TCP", "params": {"id": 66, "xboost": value}}),
EnabledEntity(client, "inv.cfgAcChgModeFlg", const.AC_SLOW_CHARGE, lambda value: {"moduleType": 0, "operateType": "TCP", "params": {"id": 65, "workMode": value}}),
EnabledEntity(client, "inv.cfgFanMode", const.AUTO_FAN_SPEED, lambda value: {"moduleType": 0, "operateType": "TCP", "params": {"id": 73, "fanMode": value}})
]
def selects(self, client: EcoflowMQTTClient) -> list[BaseSelectEntity]:
return [
TimeoutDictSelectEntity(client, "pd.standByMode", const.UNIT_TIMEOUT, const.UNIT_TIMEOUT_OPTIONS_LIMITED, lambda value: {"moduleType": 0, "operateType": "TCP", "params": {"id": 33, "standByMode": value}}),
TimeoutDictSelectEntity(client, "pd.carDelayOffMin", const.DC_TIMEOUT, const.DC_TIMEOUT_OPTIONS_LIMITED, lambda value: {"moduleType": 0, "operateType": "TCP", "params": {"cmdSet": 32, "id": 84, "carDelayOffMin": value}}),
TimeoutDictSelectEntity(client, "inv.cfgStandbyMin", const.AC_TIMEOUT, const.AC_TIMEOUT_OPTIONS_LIMITED, lambda value: {"moduleType": 0, "operateType": "TCP", "params": {"id": 153, "standByMins": value}})
# lambda is confirmed correct, but pd.lcdOffSec is missing from status
# TimeoutDictSelectEntity(client, "pd.lcdOffSec", const.SCREEN_TIMEOUT, const.SCREEN_TIMEOUT_OPTIONS,
# lambda value: {"moduleType": 0, "operateType": "TCP",
# "params": {"lcdTime": value, "id": 39}})
]
def migrate(self, version) -> list[EntityMigration]:
if version == 2:
return [
EntityMigration("pd.soc", Platform.SENSOR, MigrationAction.REMOVE),
]
return []
@@ -0,0 +1,91 @@
from homeassistant.components.switch import SwitchEntity
from . import const, BaseDevice
from .. import EcoflowMQTTClient
from ..entities import BaseSensorEntity, BaseNumberEntity, BaseSelectEntity
from ..number import SetTempEntity
from ..select import DictSelectEntity
from ..sensor import LevelSensorEntity, RemainSensorEntity, TempSensorEntity, \
WattsSensorEntity, QuotasStatusSensorEntity, \
MilliCelsiusSensorEntity, CapacitySensorEntity
class Wave2(BaseDevice):
def sensors(self, client: EcoflowMQTTClient) -> list[BaseSensorEntity]:
return [
# Power and Battery Entities
LevelSensorEntity(client, "bms.soc", const.MAIN_BATTERY_LEVEL)
.attr("bms.remainCap", const.ATTR_REMAIN_CAPACITY, 0),
CapacitySensorEntity(client, "bms.remainCap", const.MAIN_REMAIN_CAPACITY, False),
TempSensorEntity(client, "bms.tmp", const.BATTERY_TEMP)
.attr("bms.minCellTemp", const.ATTR_MIN_CELL_TEMP, 0)
.attr("bms.maxCellTemp", const.ATTR_MAX_CELL_TEMP, 0),
TempSensorEntity(client, "bms.minCellTmp", const.MIN_CELL_TEMP, False),
TempSensorEntity(client, "bms.maxCellTmp", const.MAX_CELL_TEMP, False),
RemainSensorEntity(client, "pd.batChgRemain", const.CHARGE_REMAINING_TIME),
RemainSensorEntity(client, "pd.batDsgRemain", const.DISCHARGE_REMAINING_TIME),
# heat pump
MilliCelsiusSensorEntity(client, "pd.condTemp", "Condensation temperature", False),
MilliCelsiusSensorEntity(client, "pd.heatEnv", "Return air temperature in condensation zone", False),
MilliCelsiusSensorEntity(client, "pd.coolEnv", "Air outlet temperature", False),
MilliCelsiusSensorEntity(client, "pd.evapTemp", "Evaporation temperature", False),
MilliCelsiusSensorEntity(client, "pd.motorOutTemp", "Exhaust temperature", False),
MilliCelsiusSensorEntity(client, "pd.airInTemp", "Evaporation zone return air temperature", False),
TempSensorEntity(client, "pd.coolTemp", "Air outlet temperature", False),
TempSensorEntity(client, "pd.envTemp", "Ambient temperature", False),
# power (pd)
WattsSensorEntity(client, "pd.mpptPwr", "PV input power"),
WattsSensorEntity(client, "pd.batPwrOut", "Battery output power"),
WattsSensorEntity(client, "pd.pvPower", "PV charging power"),
WattsSensorEntity(client, "pd.acPwrIn", "AC input power"),
WattsSensorEntity(client, "pd.psdrPower ", "Power supply power"),
WattsSensorEntity(client, "pd.sysPowerWatts", "System power"),
WattsSensorEntity(client, "pd.batPower ", "Battery power"),
# power (motor)
WattsSensorEntity(client, "motor.power", "Motor operating power"),
# power (power)
WattsSensorEntity(client, "power.batPwrOut", "Battery output power"),
WattsSensorEntity(client, "power.acPwrI", "AC input power"),
WattsSensorEntity(client, "power.mpptPwr ", "PV input power"),
QuotasStatusSensorEntity(client)
]
def numbers(self, client: EcoflowMQTTClient) -> list[BaseNumberEntity]:
return [
SetTempEntity(client, "pd.setTemp", "Set Temperature", 0, 40,
lambda value: {"moduleType": 1, "operateType": "setTemp",
"sn": client.device_sn,
"params": {"setTemp": int(value)}}),
]
def selects(self, client: EcoflowMQTTClient) -> list[BaseSelectEntity]:
return [
DictSelectEntity(client, "pd.fanValue", const.FAN_MODE, const.FAN_MODE_OPTIONS,
lambda value: {"moduleType": 1, "operateType": "fanValue",
"sn": client.device_sn,
"params": {"fanValue": value}}),
DictSelectEntity(client, "pd.mainMode", const.MAIN_MODE, const.MAIN_MODE_OPTIONS,
lambda value: {"moduleType": 1, "operateType": "mainMode",
"sn": client.device_sn,
"params": {"mainMode": value}}),
DictSelectEntity(client, "pd.powerMode", const.REMOTE_MODE, const.REMOTE_MODE_OPTIONS,
lambda value: {"moduleType": 1, "operateType": "powerMode",
"sn": client.device_sn,
"params": {"powerMode": value}}),
DictSelectEntity(client, "pd.subMode", const.POWER_SUB_MODE, const.POWER_SUB_MODE_OPTIONS,
lambda value: {"moduleType": 1, "operateType": "subMode",
"sn": client.device_sn,
"params": {"subMode": value}}),
]
def switches(self, client: EcoflowMQTTClient) -> list[SwitchEntity]:
return []