Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 36 additions & 14 deletions custom_components/ef_ble/eflib/devices/river2.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
from bleak.backends.scanner import AdvertisementData

from ..devicebase import DeviceBase
from ..entity import controls
from ..entity.base import dynamic
from ..model import (
DirectBmsMDeltaHeartbeatPack,
DirectEmsDeltaHeartbeatPack,
Expand Down Expand Up @@ -56,8 +58,8 @@ class Device(DeviceBase, RawDataProps):
ac_input_power = raw_field(pb_inv.input_watts)
ac_output_power = raw_field(pb_inv.output_watts)

remain_time_charging = raw_field(pb_ems.chg_remain_time)
remain_time_discharging = raw_field(pb_ems.dsg_remain_time)
remaining_time_charging = raw_field(pb_ems.chg_remain_time)
remaining_time_discharging = raw_field(pb_ems.dsg_remain_time)

dc_mode = raw_field(pb_mppt.cfg_chg_type, DCMode.from_value)

Expand Down Expand Up @@ -140,11 +142,13 @@ async def data_parse(self, packet: Packet) -> bool:

return processed

@controls.outlet(ac_ports)
async def enable_ac_ports(self, enabled: bool):
payload = bytes([1 if enabled else 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF])
packet = Packet(0x21, 0x05, 0x20, 0x42, payload, version=2)
await self._conn.sendPacket(packet)

@controls.switch(dc_12v_port)
async def enable_dc_12v_port(self, enabled: bool):
payload = bytes([0x01 if enabled else 0x00])
packet = Packet(0x21, 0x05, 0x20, 0x51, payload, version=2)
Expand All @@ -160,6 +164,7 @@ async def enable_ac_always_on(self, enabled: bool):
packet = Packet(0x21, 0x02, 0x20, 0x5F, payload, version=2)
await self._conn.sendPacket(packet)

@controls.switch(energy_backup)
async def enable_energy_backup(self, enabled: bool):
reserve = (
self.energy_backup_battery_level
Expand All @@ -172,15 +177,22 @@ async def enable_energy_backup(self, enabled: bool):
packet = Packet(0x21, 0x02, 0x20, 0x5E, payload, version=2)
await self._conn.sendPacket(packet)

async def set_energy_backup_battery_level(self, value: int) -> bool:
@controls.battery(
energy_backup_battery_level,
min=dynamic(battery_charge_limit_min),
max=dynamic(battery_charge_limit_max),
availability=energy_backup,
)
async def set_energy_backup_battery_level(self, value: float) -> bool:
percent = max(0, min(int(value), 100))
payload = bytes([0x01, percent, 0x00, 0x00])
packet = Packet(0x21, 0x02, 0x20, 0x5E, payload, version=2)
await self._conn.sendPacket(packet)
return True

async def set_battery_charge_limit_min(self, limit: int) -> bool:
limit = max(0, min(int(limit), 30))
@controls.battery(battery_charge_limit_min, max=dynamic(battery_charge_limit_max))
async def set_battery_charge_limit_min(self, value: float) -> bool:
limit = max(0, min(int(value), 30))
if (
self.battery_charge_limit_max is not None
and limit > self.battery_charge_limit_max
Expand All @@ -191,28 +203,38 @@ async def set_battery_charge_limit_min(self, limit: int) -> bool:
await self._conn.sendPacket(packet)
return True

async def set_battery_charge_limit_max(self, limit: int) -> bool:
if self.battery_charge_limit_min is not None and limit < int(
self.battery_charge_limit_min
@controls.battery(battery_charge_limit_max, min=dynamic(battery_charge_limit_min))
async def set_battery_charge_limit_max(self, value: float) -> bool:
limit = int(value)
if (
self.battery_charge_limit_min is not None
and limit < self.battery_charge_limit_min
):
return False

packet = Packet(0x21, 0x03, 0x20, 0x31, limit.to_bytes(), version=2)
await self._conn.sendPacket(packet)
return True

async def set_dc_charging_amps_max(self, value: int) -> bool:
packet = Packet(0x21, 0x05, 0x20, 0x47, value.to_bytes(), version=2)
@controls.current(dc_charging_max_amps, max=dynamic(dc_charging_current_max))
async def set_dc_charging_amps_max(self, value: float) -> bool:
payload = (int(value) * 1000).to_bytes(4, "little")
packet = Packet(0x21, 0x05, 0x20, 0x47, payload, version=2)
await self._conn.sendPacket(packet)
return True

async def set_dc_mode(self, value: DCMode) -> bool:
@controls.select(dc_mode, options=DCMode)
async def set_dc_mode(self, value: DCMode):
packet = Packet(0x21, 0x05, 0x20, 0x52, value.to_bytes(), version=2)
await self._conn.sendPacket(packet)
return True

async def set_ac_charging_speed(self, value: int):
payload = value.to_bytes(2, "little") + b"\xff"
@controls.power(
ac_charging_speed,
min=dynamic(min_ac_charging_power),
max=dynamic(max_ac_charging_power),
)
async def set_ac_charging_speed(self, value: float) -> bool:
payload = int(value).to_bytes(2, "little") + b"\xff"
packet = Packet(0x21, 0x05, 0x20, 0x45, payload, version=2)
await self._conn.sendPacket(packet)
return True
12 changes: 4 additions & 8 deletions custom_components/ef_ble/entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,6 @@ def _register_update_callback(
if prop_name is None or not hasattr(self._device, prop_name):
return

if value := getattr(self._device, prop_name, None):
setattr(self, entity_attr, get_state(value))
else:
setattr(self, entity_attr, None)

@callback
def state_updated(state: Any):
if (state := get_state(state)) is EcoflowEntity.SkipWrite:
Expand All @@ -65,10 +60,11 @@ def state_updated(state: Any):
setattr(self, entity_attr, state)
self.async_write_ha_state()

if (state := getattr(self._device, prop_name, None)) is not None:
setattr(self, entity_attr, get_state(state))
elif default_state is not None:
device_state = getattr(self._device, prop_name, None)
if device_state is None and default_state is not None:
setattr(self, entity_attr, default_state)
elif (initial := get_state(device_state)) is not EcoflowEntity.SkipWrite:
setattr(self, entity_attr, initial)

self._update_callbacks.append((prop_name, state_updated))

Expand Down
8 changes: 8 additions & 0 deletions custom_components/ef_ble/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -922,6 +922,14 @@
"dc_charging_type": {
"name": "DC Charging Type"
},
"dc_mode": {
"name": "DC Mode",
"state": {
"auto": "Auto",
"solar": "Solar",
"car": "Car"
}
},
"performance_mode": {
"name": "Performance Mode"
},
Expand Down
Loading