Skip to content

Commit

Permalink
split internal and public powerstream support
Browse files Browse the repository at this point in the history
  • Loading branch information
tolwi committed Aug 20, 2024
1 parent 8b9df82 commit 8d05f27
Show file tree
Hide file tree
Showing 2 changed files with 234 additions and 95 deletions.
214 changes: 122 additions & 92 deletions custom_components/ecoflow_cloud/devices/internal/powerstream.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from homeassistant.util import utcnow

from custom_components.ecoflow_cloud.devices import const, BaseDevice
from custom_components.ecoflow_cloud.devices import BaseDevice
from custom_components.ecoflow_cloud.entities import (
BaseSensorEntity, BaseNumberEntity, BaseSelectEntity, BaseSwitchEntity
)
Expand All @@ -12,113 +12,143 @@
DecivoltSensorEntity, InWattsSolarSensorEntity, LevelSensorEntity,
MiscSensorEntity, RemainSensorEntity, StatusSensorEntity,
)
from custom_components.ecoflow_cloud.number import DeciChargingPowerEntity, MinBatteryLevelEntity, MaxBatteryLevelEntity, BrightnessLevelEntity
from custom_components.ecoflow_cloud.select import PowerDictSelectEntity
from .proto import ecopacket_pb2 as ecopacket, powerstream_pb2 as powerstream
from ...api import EcoflowApiClient

# from ..number import MinBatteryLevelEntity, MaxBatteryLevelEntity
# from ..select import DictSelectEntity
_LOGGER = logging.getLogger(__name__)

class PowerStream(BaseDevice):
def sensors(self, client: EcoflowApiClient) -> list[BaseSensorEntity]:
return [
InWattsSolarSensorEntity(client, self, "20_1.pv1InputWatts", "Solar 1 Watts"),
DecivoltSensorEntity(client, self, "20_1.pv1InputVolt", "Solar 1 Input Potential"),
CentivoltSensorEntity(client, self, "20_1.pv1OpVolt", "Solar 1 Op Potential"),
DeciampSensorEntity(client, self, "20_1.pv1InputCur", "Solar 1 Currrent"),
DecicelsiusSensorEntity(client, self, "20_1.pv1Temp", "Solar 1 Temperature"),
MiscSensorEntity(client, self, "20_1.pv1RelayStatus", "Solar 1 Relay Status"),
MiscSensorEntity(client, self, "20_1.pv1ErrCode", "Solar 1 Error Code", False),
MiscSensorEntity(client, self, "20_1.pv1WarnCode", "Solar 1 Warning Code", False),
MiscSensorEntity(client, self, "20_1.pv1Statue", "Solar 1 Status", False),

InWattsSolarSensorEntity(client, self, "20_1.pv2InputWatts", "Solar 2 Watts"),
DecivoltSensorEntity(client, self, "20_1.pv2InputVolt", "Solar 2 Input Potential"),
CentivoltSensorEntity(client, self, "20_1.pv2OpVolt", "Solar 2 Op Potential"),
DeciampSensorEntity(client, self, "20_1.pv2InputCur", "Solar 2 Current"),
DecicelsiusSensorEntity(client, self, "20_1.pv2Temp", "Solar 2 Temperature"),
MiscSensorEntity(client, self, "20_1.pv2RelayStatus", "Solar 2 Relay Status"),
MiscSensorEntity(client, self, "20_1.pv2ErrCode", "Solar 2 Error Code", False),
MiscSensorEntity(client, self, "20_1.pv2WarningCode", "Solar 2 Warning Code", False),
MiscSensorEntity(client, self, "20_1.pv2Statue", "Solar 2 Status", False),

MiscSensorEntity(client, self, "20_1.bpType", "Battery Type", False),
LevelSensorEntity(client, self, "20_1.batSoc", "Battery Charge"),
DeciwattsSensorEntity(client, self, "20_1.batInputWatts", "Battery Input Watts"),
DecivoltSensorEntity(client, self, "20_1.batInputVolt", "Battery Input Potential"),
DecivoltSensorEntity(client, self, "20_1.batOpVolt", "Battery Op Potential"),
AmpSensorEntity(client, self, "20_1.batInputCur", "Battery Input Current"),
DecicelsiusSensorEntity(client, self, "20_1.batTemp", "Battery Temperature"),
RemainSensorEntity(client, self, "20_1.chgRemainTime", "Charge Time"),
RemainSensorEntity(client, self, "20_1.dsgRemainTime", "Discharge Time"),
MiscSensorEntity(client, self, "20_1.batErrCode", "Battery Error Code", False),
MiscSensorEntity(client, self, "20_1.batWarningCode", "Battery Warning Code", False),
MiscSensorEntity(client, self, "20_1.batStatue", "Battery Status", False),

DecivoltSensorEntity(client, self, "20_1.llcInputVolt", "LLC Input Potential", False),
DecivoltSensorEntity(client, self, "20_1.llcOpVolt", "LLC Op Potential", False),
DecicelsiusSensorEntity(client, self, "20_1.llcTemp", "LLC Temperature"),
MiscSensorEntity(client, self, "20_1.llcErrCode", "LLC Error Code", False),
MiscSensorEntity(client, self, "20_1.llcWarningCode", "LLC Warning Code", False),
MiscSensorEntity(client, self, "20_1.llcStatue", "LLC Status", False),

MiscSensorEntity(client, self, "20_1.invOnOff", "Inverter On/Off Status"),
DeciwattsSensorEntity(client, self, "20_1.invOutputWatts", "Inverter Output Watts"),
DecivoltSensorEntity(client, self, "20_1.invInputVolt", "Inverter Output Potential", False),
DecivoltSensorEntity(client, self, "20_1.invOpVolt", "Inverter Op Potential"),
AmpSensorEntity(client, self, "20_1.invOutputCur", "Inverter Output Current"),
# AmpSensorEntity(client, self, "inv_dc_cur", "Inverter DC Current"),
DecihertzSensorEntity(client, self, "20_1.invFreq", "Inverter Frequency"),
DecicelsiusSensorEntity(client, self, "20_1.invTemp", "Inverter Temperature"),
MiscSensorEntity(client, self, "20_1.invRelayStatus", "Inverter Relay Status"),
MiscSensorEntity(client, self, "20_1.invErrCode", "Inverter Error Code", False),
MiscSensorEntity(client, self, "20_1.invWarnCode", "Inverter Warning Code", False),
MiscSensorEntity(client, self, "20_1.invStatue", "Inverter Status", False),

DeciwattsSensorEntity(client, self, "20_1.permanentWatts", "Other Loads"),
DeciwattsSensorEntity(client, self, "20_1.dynamicWatts", "Smart Plug Loads"),
DeciwattsSensorEntity(client, self, "20_1.ratedPower", "Rated Power"),

MiscSensorEntity(client, self, "20_1.lowerLimit", "Lower Battery Limit", False),
MiscSensorEntity(client, self, "20_1.upperLimit", "Upper Battery Limit", False),
MiscSensorEntity(client, self, "20_1.wirelessErrCode", "Wireless Error Code", False),
MiscSensorEntity(client, self, "20_1.wirelessWarnCode", "Wireless Warning Code", False),
MiscSensorEntity(client, self, "20_1.invBrightness", "LED Brightness", False),
MiscSensorEntity(client, self, "20_1.heartbeatFrequency", "Heartbeat Frequency", False),

StatusSensorEntity(client, self)
InWattsSolarSensorEntity(client, self, "pv1_input_watts", "Solar 1 Watts"),
DecivoltSensorEntity(client, self, "pv1_input_volt", "Solar 1 Input Potential"),
CentivoltSensorEntity(client, self, "pv1_op_volt", "Solar 1 Op Potential"),
DeciampSensorEntity(client, self, "pv1_input_cur", "Solar 1 Currrent"),
DecicelsiusSensorEntity(client, self, "pv1_temp", "Solar 1 Temperature"),
MiscSensorEntity(client, self, "pv1_relay_status", "Solar 1 Relay Status"),
MiscSensorEntity(client, self, "pv1_error_code", "Solar 1 Error Code", False),
MiscSensorEntity(client, self, "pv1_warning_code", "Solar 1 Warning Code", False),
MiscSensorEntity(client, self, "pv1_status", "Solar 1 Status", False),

InWattsSolarSensorEntity(client, self, "pv2_input_watts", "Solar 2 Watts"),
DecivoltSensorEntity(client, self, "pv2_input_volt", "Solar 2 Input Potential"),
CentivoltSensorEntity(client, self, "pv2_op_volt", "Solar 2 Op Potential"),
DeciampSensorEntity(client, self, "pv2_input_cur", "Solar 2 Current"),
DecicelsiusSensorEntity(client, self, "pv2_temp", "Solar 2 Temperature"),
MiscSensorEntity(client, self, "pv2_relay_status", "Solar 2 Relay Status"),
MiscSensorEntity(client, self, "pv2_error_code", "Solar 2 Error Code", False),
MiscSensorEntity(client, self, "pv2_warning_code", "Solar 2 Warning Code", False),
MiscSensorEntity(client, self, "pv2_status", "Solar 2 Status", False),

MiscSensorEntity(client, self, "bp_type", "Battery Type", False),
LevelSensorEntity(client, self, "bat_soc", "Battery Charge"),
DeciwattsSensorEntity(client, self, "bat_input_watts", "Battery Input Watts"),
DecivoltSensorEntity(client, self, "bat_input_volt", "Battery Input Potential"),
DecivoltSensorEntity(client, self, "bat_op_volt", "Battery Op Potential"),
AmpSensorEntity(client, self, "bat_input_cur", "Battery Input Current"),
DecicelsiusSensorEntity(client, self, "bat_temp", "Battery Temperature"),
RemainSensorEntity(client, self, "battery_charge_remain", "Charge Time"),
RemainSensorEntity(client, self, "battery_discharge_remain", "Discharge Time"),
MiscSensorEntity(client, self, "bat_error_code", "Battery Error Code", False),
MiscSensorEntity(client, self, "bat_warning_code", "Battery Warning Code", False),
MiscSensorEntity(client, self, "bat_status", "Battery Status", False),

DecivoltSensorEntity(client, self, "llc_input_volt", "LLC Input Potential", False),
DecivoltSensorEntity(client, self, "llc_op_volt", "LLC Op Potential", False),
MiscSensorEntity(client, self, "llc_error_code", "LLC Error Code", False),
MiscSensorEntity(client, self, "llc_warning_code", "LLC Warning Code", False),
MiscSensorEntity(client, self, "llc_status", "LLC Status", False),

MiscSensorEntity(client, self, "inv_on_off", "Inverter On/Off Status"),
DeciwattsSensorEntity(client, self, "inv_output_watts", "Inverter Output Watts"),
DecivoltSensorEntity(client, self, "inv_input_volt", "Inverter Output Potential", False),
DecivoltSensorEntity(client, self, "inv_op_volt", "Inverter Op Potential"),
AmpSensorEntity(client, self, "inv_output_cur", "Inverter Output Current"),
AmpSensorEntity(client, self, "inv_dc_cur", "Inverter DC Current"),
DecihertzSensorEntity(client, self, "inv_freq", "Inverter Frequency"),
DecicelsiusSensorEntity(client, self, "inv_temp", "Inverter Temperature"),
MiscSensorEntity(client, self, "inv_relay_status", "Inverter Relay Status"),
MiscSensorEntity(client, self, "inv_error_code", "Inverter Error Code", False),
MiscSensorEntity(client, self, "inv_warning_code", "Inverter Warning Code", False),
MiscSensorEntity(client, self, "inv_status", "Inverter Status", False),

DeciwattsSensorEntity(client, self, "permanent_watts", "Other Loads"),
DeciwattsSensorEntity(client, self, "dynamic_watts", "Smart Plug Loads"),
DeciwattsSensorEntity(client, self, "rated_power", "Rated Power"),

MiscSensorEntity(client, self, "lower_limit", "Lower Battery Limit", False),
MiscSensorEntity(client, self, "upper_limit", "Upper Battery Limit", False),
MiscSensorEntity(client, self, "wireless_error_code", "Wireless Error Code", False),
MiscSensorEntity(client, self, "wireless_warning_code", "Wireless Warning Code", False),
MiscSensorEntity(client, self, "inv_brightness", "LED Brightness", False),
MiscSensorEntity(client, self, "heartbeat_frequency", "Heartbeat Frequency", False),

StatusSensorEntity(client)
]


def numbers(self, client: EcoflowApiClient) -> list[BaseNumberEntity]:
return [
MinBatteryLevelEntity(client, self, "20_1.lowerLimit", "Min Disharge Level", 0, 30,
lambda value: {"sn": self.device_info.sn,
"cmdCode": "WN511_SET_BAT_LOWER_PACK",
"params": {"lowerLimit": value}}),

MaxBatteryLevelEntity(client, self, "20_1.upperLimit", "Max Charge Level", 70, 100,
lambda value: {"sn": self.device_info.sn,
"cmdCode": "WN511_SET_BAT_UPPER_PACK",
"params": {"upperLimit": value}}),

BrightnessLevelEntity(client, self, "20_1.invBrightness", const.BRIGHTNESS, 0, 1023,
lambda value: {"sn": self.device_info.sn,
"cmdCode": "WN511_SET_BRIGHTNESS_PACK",
"params": {"brightness": value}}),

DeciChargingPowerEntity(client, self, "20_1.permanentWatts", "Custom load power settings (0.1 W)", 0, 8000,
lambda value: {"sn": self.device_info.sn,
"cmdCode": "WN511_SET_PERMANENT_WATTS_PACK",
"params": {"permanentWatts": value}}),
# These will likely be some form of serialised data rather than JSON will look into it later
# MinBatteryLevelEntity(client, self, "lowerLimit", "Min Disharge Level", 50, 100,
# lambda value: {"moduleType": 0, "operateType": "TCP",
# "params": {"id": 00, "lowerLimit": value}}),
# MaxBatteryLevelEntity(client, self, "upperLimit", "Max Charge Level", 0, 30,
# lambda value: {"moduleType": 0, "operateType": "TCP",
# "params": {"id": 00, "upperLimit": value}}),
]

def switches(self, client: EcoflowApiClient) -> list[BaseSwitchEntity]:
return []

def selects(self, client: EcoflowApiClient) -> list[BaseSelectEntity]:
return [
PowerDictSelectEntity(client, self, "20_1.supplyPriority", "Power supply mode", const.POWER_SUPPLY_PRIORITY_OPTIONS,
lambda value: {"sn": self.device_info.sn,
"cmdCode": "WN511_SET_SUPPLY_PRIORITY_PACK",
"params": {"supplyPriority": value}}),
]
# DictSelectEntity(client, self, "supplyPriority", "Power supply mode", {"Prioritize power supply", "Prioritize power storage"},
# lambda value: {"moduleType": 00, "operateType": "supplyPriority",
# "params": {"supplyPriority": value}}),
]

def update_data(self, raw_data, data_type):
try:
payload =raw_data

while True:
packet = ecopacket.SendHeaderMsg()
packet.ParseFromString(payload)

_LOGGER.debug("cmd id %u payload \"%s\"", packet.msg.cmd_id, payload.hex())

if packet.msg.cmd_id != 1:
_LOGGER.info("Unsupported EcoPacket cmd id %u", packet.msg.cmd_id)

else:
heartbeat = powerstream.InverterHeartbeat()
heartbeat.ParseFromString(packet.msg.pdata)

raw = {"params": {}}

for descriptor in heartbeat.DESCRIPTOR.fields:
if not heartbeat.HasField(descriptor.name):
continue

raw["params"][descriptor.name] = getattr(heartbeat, descriptor.name)

_LOGGER.info("Found %u fields", len(raw["params"]))

raw["timestamp"] = utcnow()
self.data.update_data(raw)

if packet.ByteSize() >= len(payload):
break

_LOGGER.info("Found another frame in payload")

packet_length = len(payload) - packet.ByteSize()
payload = payload[:packet_length]

except Exception as error:
_LOGGER.error(error)
_LOGGER.info(raw_data.hex())

Loading

0 comments on commit 8d05f27

Please sign in to comment.