├── custom_components ├── __init__.py └── ecoflow_cloud │ ├── devices │ ├── public │ │ ├── __init__.py │ │ ├── wave2.py │ │ ├── river2.py │ │ ├── delta2.py │ │ ├── delta3.py │ │ ├── delta_max.py │ │ ├── river2_max.py │ │ ├── river2_pro.py │ │ ├── delta2_max.py │ │ ├── data_bridge.py │ │ ├── stream_microinverter.py │ │ ├── smart_plug.py │ │ ├── smart_meter.py │ │ └── smart_home_panel.py │ ├── internal │ │ ├── proto │ │ │ ├── __init__.py │ │ │ └── ef_smartmeter.proto │ │ ├── __init__.py │ │ ├── river_mini.py │ │ └── wave2.py │ ├── data_holder.py │ └── registry.py │ ├── _preload_proto.py │ ├── device_data.py │ ├── recorder.py │ ├── manifest.json │ ├── button.py │ ├── api │ ├── message.py │ ├── __init__.py │ └── ecoflow_mqtt.py │ ├── diagnostics.py │ ├── translations │ ├── ja.json │ ├── en.json │ ├── de.json │ ├── uk_UA.json │ ├── pl.json │ ├── it.json │ ├── fr.json │ └── pt-PT.json │ ├── select.py │ └── number.py ├── ruff.toml ├── requirements.txt ├── .vscode ├── settings.json ├── extensions.json ├── launch.json └── tasks.json ├── docs ├── devices │ ├── DIAGNOSTIC.md │ ├── Diagnostic-Public.md │ ├── Smart_Plug-Public.md │ ├── Stream_Microinverter-Public.md │ ├── SMART_METER.md │ ├── RIVER_MINI.md │ ├── Power_Ocean-Public.md │ ├── Smart_Home_Panel-Public.md │ ├── Smart_Meter-Public.md │ ├── STREAM_AC.md │ ├── STREAM_PRO.md │ ├── STREAM_ULTRA.md │ ├── WAVE_2.md │ ├── WAVE_2-Public.md │ ├── GLACIER.md │ ├── Stream_AC-Public.md │ ├── Stream_PRO-Public.md │ ├── Stream_Ultra-Public.md │ ├── DELTA_3.md │ ├── DELTA_3-Public.md │ ├── DELTA_MINI.md │ ├── PowerStream-Public.md │ ├── RIVER_MAX.md │ ├── RIVER_2_PRO.md │ ├── RIVER_2_Pro-Public.md │ ├── RIVER_PRO.md │ ├── RIVER_2.md │ ├── RIVER_2-Public.md │ ├── RIVER_2_MAX.md │ ├── RIVER_2_Max-Public.md │ ├── DELTA_PRO_3.md │ ├── POWERSTREAM.md │ ├── Delta_Pro_3-Public.md │ ├── DELTA_MAX.md │ ├── DELTA_Max-Public.md │ ├── DELTA_2.md │ ├── DELTA_2-Public.md │ └── DELTA_Pro_Ultra-Public.md ├── integration.md └── Contribution.md ├── hacs.json ├── .gitignore ├── .github ├── workflows │ ├── hassfest.yaml │ └── validate.yml └── ISSUE_TEMPLATE │ ├── config.yml │ ├── feature_request.yml │ ├── new_device.yml │ └── bug_report.yml ├── .devcontainer └── devcontainer.json ├── mise.toml └── debug.init.py /custom_components/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ruff.toml: -------------------------------------------------------------------------------- 1 | line-length = 120 2 | indent-width = 4 3 | -------------------------------------------------------------------------------- /custom_components/ecoflow_cloud/devices/public/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | homeassistant>=2024.5.5 2 | paho_mqtt>=2.1.0 3 | protobuf==6.32.0 4 | jsonpath-ng>=1.7.0 -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "python.testing.pytestArgs": ["--no-cov"], 3 | "python.testing.pytestEnabled": false 4 | } 5 | -------------------------------------------------------------------------------- /docs/devices/DIAGNOSTIC.md: -------------------------------------------------------------------------------- 1 | ## DIAGNOSTIC 2 | 3 | *Sensors* 4 | 5 | *Switches* 6 | 7 | *Sliders (numbers)* 8 | 9 | *Selects* 10 | 11 | 12 | -------------------------------------------------------------------------------- /hacs.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "EcoFlowCloud", 3 | "render_readme": true, 4 | "homeassistant": "2024.8.0", 5 | "hide_default_branch": true 6 | } 7 | -------------------------------------------------------------------------------- /docs/devices/Diagnostic-Public.md: -------------------------------------------------------------------------------- 1 | ## Diagnostic 2 | 3 | *Sensors* 4 | 5 | *Switches* 6 | 7 | *Sliders (numbers)* 8 | 9 | *Selects* 10 | 11 | 12 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "charliermarsh.ruff", 4 | "prettier.prettier-vscode", 5 | "ms-python.python" 6 | ] 7 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__ 2 | venv 3 | .venv 4 | .idea 5 | .DS_Store 6 | .vscode/settings.json 7 | .coverage 8 | requirements.test.txt 9 | requirements.txt 10 | setup.cfg 11 | tests 12 | -------------------------------------------------------------------------------- /custom_components/ecoflow_cloud/devices/internal/proto/__init__.py: -------------------------------------------------------------------------------- 1 | from enum import IntEnum 2 | 3 | 4 | class AddressId(IntEnum): 5 | IOT = 1 6 | IOT2 = 2 7 | APP = 32 8 | MQTT = 53 9 | 10 | 11 | class DirectionId(IntEnum): 12 | DEFAULT = 1 13 | -------------------------------------------------------------------------------- /.github/workflows/hassfest.yaml: -------------------------------------------------------------------------------- 1 | name: Validate with hassfest 2 | 3 | on: 4 | push: 5 | pull_request: 6 | schedule: 7 | - cron: "0 0 * * *" 8 | 9 | jobs: 10 | validate: 11 | runs-on: "ubuntu-latest" 12 | steps: 13 | - uses: "actions/checkout@v3" 14 | - uses: home-assistant/actions/hassfest@master 15 | -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "image": "dcbr/hass-custom-devcontainer", 3 | "postCreateCommand": "sudo -E container setup", 4 | "postStartCommand": "sudo -E container launch", 5 | "appPort": ["7123:8123", "8123:8123", "7357:4357"], 6 | "workspaceFolder": "/workspace", 7 | "workspaceMount": "source=${localWorkspaceFolder},target=/workspace,type=bind" 8 | } 9 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Gen docs", 6 | "type": "debugpy", 7 | "request": "launch", 8 | "program": "gen.py", 9 | "python": "${workspaceFolder}/.venv/bin/python", 10 | "cwd": "${workspaceFolder}/docs", 11 | "env": { 12 | "PYTHONPATH": "${workspaceFolder}" 13 | } 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /.github/workflows/validate.yml: -------------------------------------------------------------------------------- 1 | name: HACS validation 2 | 3 | on: 4 | push: 5 | pull_request: 6 | schedule: 7 | - cron: "0 0 * * *" 8 | workflow_dispatch: 9 | 10 | jobs: 11 | validate-hacs: 12 | runs-on: "ubuntu-latest" 13 | steps: 14 | - uses: "actions/checkout@v3" 15 | - name: HACS validation 16 | uses: "hacs/action@main" 17 | with: 18 | category: "integration" 19 | -------------------------------------------------------------------------------- /mise.toml: -------------------------------------------------------------------------------- 1 | [env] 2 | _.python.venv = { path = ".venv", create = true } 3 | 4 | [tools] 5 | python = "3.13" 6 | 7 | 8 | [tasks.lint] 9 | description = "Lint code" 10 | dir = "custom_components" 11 | run = """ 12 | # pyright . 13 | ruff check . 14 | """ 15 | 16 | [tasks.protoc] 17 | tools.protoc = "32.0" 18 | dir = "custom_components/ecoflow_cloud/devices/internal/proto" 19 | run = "protoc --proto_path=. --python_out=. --pyi_out=. *.proto" 20 | -------------------------------------------------------------------------------- /custom_components/ecoflow_cloud/_preload_proto.py: -------------------------------------------------------------------------------- 1 | from .devices.internal.proto import ( 2 | ef_dp3_iobroker_pb2, # noqa: F401 # pyright: ignore[reportUnusedImport] 3 | ef_river3_pb2, # noqa: F401 # pyright: ignore[reportUnusedImport] 4 | powerstream_pb2, # noqa: F401 # pyright: ignore[reportUnusedImport] 5 | stream_ac_pb2, # noqa: F401 # pyright: ignore[reportUnusedImport] 6 | ef_smartmeter_pb2, # noqa: F401 # pyright: ignore[reportUnusedImport] 7 | ) 8 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "label": "Generate Docs (workspace/venv)", 6 | "type": "shell", 7 | "command": "PYTHONPATH=/workspace /workspace/venv/bin/python gen.py", 8 | "options": { 9 | "cwd": "${workspaceFolder}/docs" 10 | }, 11 | "presentation": { 12 | "reveal": "always", 13 | "panel": "shared", 14 | "clear": true 15 | }, 16 | "problemMatcher": [] 17 | } 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /custom_components/ecoflow_cloud/device_data.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations # for DeviceData.parent: DeviceData 2 | 3 | import dataclasses 4 | 5 | 6 | @dataclasses.dataclass 7 | class DeviceOptions: 8 | refresh_period: int 9 | power_step: int 10 | diagnostic_mode: bool 11 | 12 | 13 | @dataclasses.dataclass 14 | class DeviceData: 15 | sn: str 16 | name: str 17 | device_type: str 18 | options: DeviceOptions 19 | display_name: str | None 20 | parent: DeviceData | None 21 | -------------------------------------------------------------------------------- /docs/devices/Smart_Plug-Public.md: -------------------------------------------------------------------------------- 1 | ## Smart_Plug 2 | 3 | *Sensors* 4 | - Temperature (`2_1.temp`) 5 | - Volts (`2_1.volt`) 6 | - Current (`2_1.current`) 7 | - Power (`2_1.watts`) 8 | 9 | *Switches* 10 | - On (`2_1.switchSta` -> `{"sn": "SN", "cmdCode": "WN511_SOCKET_SET_PLUG_SWITCH_MESSAGE", "params": {"plugSwitch": "VALUE"}}`) 11 | 12 | *Sliders (numbers)* 13 | - Brightness (`2_1.brightness` -> `{"sn": "SN", "cmdCode": "WN511_SOCKET_SET_BRIGHTNESS_PACK", "params": {"brightness": "VALUE"}}` [0 - 1023]) 14 | 15 | *Selects* 16 | 17 | 18 | -------------------------------------------------------------------------------- /custom_components/ecoflow_cloud/devices/public/wave2.py: -------------------------------------------------------------------------------- 1 | from .data_bridge import to_plain 2 | from ..internal.wave2 import Wave2 as InternalWave2 3 | from ...api import EcoflowApiClient 4 | from ...sensor import StatusSensorEntity 5 | 6 | 7 | class Wave2(InternalWave2): 8 | def _prepare_data(self, raw_data) -> dict[str, any]: 9 | res = super()._prepare_data(raw_data) 10 | res = to_plain(res) 11 | return res 12 | 13 | def _status_sensor(self, client: EcoflowApiClient) -> StatusSensorEntity: 14 | return StatusSensorEntity(client, self) 15 | -------------------------------------------------------------------------------- /custom_components/ecoflow_cloud/recorder.py: -------------------------------------------------------------------------------- 1 | from homeassistant.core import callback, HomeAssistant 2 | 3 | from . import ( 4 | ATTR_STATUS_UPDATES, 5 | ATTR_STATUS_DATA_LAST_UPDATE, 6 | ATTR_STATUS_LAST_UPDATE, 7 | ATTR_STATUS_PHASE, 8 | ATTR_QUOTA_REQUESTS, 9 | ) 10 | 11 | 12 | @callback 13 | def exclude_attributes(hass: HomeAssistant) -> set[str]: 14 | return { 15 | ATTR_STATUS_UPDATES, 16 | ATTR_STATUS_DATA_LAST_UPDATE, 17 | ATTR_STATUS_LAST_UPDATE, 18 | ATTR_STATUS_PHASE, 19 | ATTR_QUOTA_REQUESTS, 20 | } 21 | -------------------------------------------------------------------------------- /custom_components/ecoflow_cloud/devices/public/river2.py: -------------------------------------------------------------------------------- 1 | from .data_bridge import to_plain 2 | from ..internal.river2 import River2 as InternalRiver2 3 | from ...api import EcoflowApiClient 4 | from ...sensor import StatusSensorEntity 5 | 6 | 7 | class River2(InternalRiver2): 8 | def _prepare_data(self, raw_data) -> dict[str, any]: 9 | res = super()._prepare_data(raw_data) 10 | res = to_plain(res) 11 | return res 12 | 13 | def _status_sensor(self, client: EcoflowApiClient) -> StatusSensorEntity: 14 | return StatusSensorEntity(client, self) 15 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: 📖 Documentation 4 | url: https://github.com/tolwi/hassio-ecoflow-cloud/blob/main/README.md 5 | about: Check the README for setup instructions and device compatibility 6 | - name: 💬 Discussions 7 | url: https://github.com/tolwi/hassio-ecoflow-cloud/discussions 8 | about: Ask questions and discuss with the community 9 | - name: 🔧 Contribution Guide 10 | url: https://github.com/tolwi/hassio-ecoflow-cloud/blob/main/docs/Contribution.md 11 | about: Learn how to contribute to the project -------------------------------------------------------------------------------- /custom_components/ecoflow_cloud/devices/public/delta2.py: -------------------------------------------------------------------------------- 1 | from ...api import EcoflowApiClient 2 | from ...sensor import StatusSensorEntity 3 | from ..internal.delta2 import Delta2 as InternalDelta2 4 | from .data_bridge import to_plain 5 | 6 | 7 | class Delta2(InternalDelta2): 8 | 9 | def _prepare_data(self, raw_data) -> dict[str, any]: 10 | res = super()._prepare_data(raw_data) 11 | res = to_plain(res) 12 | return res 13 | 14 | def _status_sensor(self, client: EcoflowApiClient) -> StatusSensorEntity: 15 | return StatusSensorEntity(client, self) 16 | 17 | 18 | -------------------------------------------------------------------------------- /custom_components/ecoflow_cloud/devices/public/delta3.py: -------------------------------------------------------------------------------- 1 | from ...api import EcoflowApiClient 2 | from ...sensor import StatusSensorEntity 3 | from ..internal.delta3 import Delta3 as InternalDelta3 4 | from .data_bridge import to_plain 5 | 6 | 7 | class Delta3(InternalDelta3): 8 | 9 | def _prepare_data(self, raw_data) -> dict[str, any]: 10 | res = super()._prepare_data(raw_data) 11 | res = to_plain(res) 12 | return res 13 | 14 | def _status_sensor(self, client: EcoflowApiClient) -> StatusSensorEntity: 15 | return StatusSensorEntity(client, self) 16 | 17 | 18 | -------------------------------------------------------------------------------- /custom_components/ecoflow_cloud/devices/public/delta_max.py: -------------------------------------------------------------------------------- 1 | from ...api import EcoflowApiClient 2 | from ...sensor import StatusSensorEntity 3 | from ..internal.delta_max import DeltaMax as InternalDeltaMax 4 | from .data_bridge import to_plain 5 | 6 | 7 | class DeltaMax(InternalDeltaMax): 8 | 9 | def _prepare_data(self, raw_data) -> dict[str, any]: 10 | res = super()._prepare_data(raw_data) 11 | res = to_plain(res) 12 | return res 13 | 14 | def _status_sensor(self, client: EcoflowApiClient) -> StatusSensorEntity: 15 | return StatusSensorEntity(client, self) 16 | -------------------------------------------------------------------------------- /custom_components/ecoflow_cloud/devices/public/river2_max.py: -------------------------------------------------------------------------------- 1 | from .data_bridge import to_plain 2 | from ..internal.river2_max import River2Max as InternalRiver2Max 3 | from ...api import EcoflowApiClient 4 | from ...sensor import StatusSensorEntity 5 | 6 | 7 | class River2Max(InternalRiver2Max): 8 | def _prepare_data(self, raw_data) -> dict[str, any]: 9 | res = super()._prepare_data(raw_data) 10 | res = to_plain(res) 11 | return res 12 | 13 | def _status_sensor(self, client: EcoflowApiClient) -> StatusSensorEntity: 14 | return StatusSensorEntity(client, self) 15 | -------------------------------------------------------------------------------- /custom_components/ecoflow_cloud/devices/public/river2_pro.py: -------------------------------------------------------------------------------- 1 | from .data_bridge import to_plain 2 | from ..internal.river2_pro import River2Pro as InternalRiver2Pro 3 | from ...api import EcoflowApiClient 4 | from ...sensor import StatusSensorEntity 5 | 6 | 7 | class River2Pro(InternalRiver2Pro): 8 | def _prepare_data(self, raw_data) -> dict[str, any]: 9 | res = super()._prepare_data(raw_data) 10 | res = to_plain(res) 11 | return res 12 | 13 | def _status_sensor(self, client: EcoflowApiClient) -> StatusSensorEntity: 14 | return StatusSensorEntity(client, self) 15 | -------------------------------------------------------------------------------- /custom_components/ecoflow_cloud/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "domain": "ecoflow_cloud", 3 | "name": "Ecoflow-Cloud", 4 | "codeowners": [ 5 | "@tolwi" 6 | ], 7 | "config_flow": true, 8 | "dependencies": [ 9 | "mqtt", 10 | "integration" 11 | ], 12 | "documentation": "https://github.com/tolwi/hassio-ecoflow-cloud", 13 | "iot_class": "cloud_push", 14 | "issue_tracker": "https://github.com/tolwi/hassio-ecoflow-cloud/issues", 15 | "requirements": [ 16 | "paho-mqtt>=2.1.0", 17 | "protobuf==6.32.0", 18 | "jsonpath-ng>=1.7.0" 19 | ], 20 | "version": "1.4.0-beta6" 21 | } 22 | -------------------------------------------------------------------------------- /custom_components/ecoflow_cloud/devices/public/delta2_max.py: -------------------------------------------------------------------------------- 1 | from ...api import EcoflowApiClient 2 | from ...sensor import StatusSensorEntity 3 | from ..internal.delta2_max import Delta2Max as InternalDelta2Max 4 | from .data_bridge import to_plain 5 | 6 | 7 | class Delta2Max(InternalDelta2Max): 8 | 9 | def _prepare_data(self, raw_data) -> dict[str, any]: 10 | res = super()._prepare_data(raw_data) 11 | res = to_plain(res) 12 | return res 13 | 14 | def _status_sensor(self, client: EcoflowApiClient) -> StatusSensorEntity: 15 | return StatusSensorEntity(client, self) 16 | 17 | 18 | -------------------------------------------------------------------------------- /docs/devices/Stream_Microinverter-Public.md: -------------------------------------------------------------------------------- 1 | ## Stream_Microinverter 2 | 3 | *Sensors* 4 | - Power AC (`gridConnectionPower`) 5 | - Power PV 1 (`powGetPv`) _(auto)_ 6 | - Power PV 2 (`powGetPv2`) _(auto)_ 7 | - Power Volts (`gridConnectionVol`) _(disabled)_ 8 | - Power PV1 Volts (`plugInInfoPvVol`) _(auto)_ 9 | - Power PV2 Volts (`plugInInfoPv2Vol`) _(auto)_ 10 | - Power In Amps (`gridConnectionAmp`) _(disabled)_ 11 | - Power PV1 In Amps (`plugInInfoPvAmp`) _(auto)_ 12 | - Power PV2 In Amps (`plugInInfoPv2Amp`) _(auto)_ 13 | - Inverter NTC Temperature (`invNtcTemp3`) 14 | - Grid Frequency (`gridConnectionFreq`) 15 | - Status 16 | 17 | *Switches* 18 | 19 | *Sliders (numbers)* 20 | 21 | *Selects* 22 | 23 | 24 | -------------------------------------------------------------------------------- /custom_components/ecoflow_cloud/devices/internal/__init__.py: -------------------------------------------------------------------------------- 1 | def to_lower_camel_case(x: str) -> str: 2 | result = list[str]() 3 | 4 | upper_next = False 5 | 6 | for c in x: 7 | if c == "_": 8 | upper_next = True 9 | elif upper_next: 10 | result.append(c.upper()) 11 | upper_next = False 12 | else: 13 | result.append(c.lower()) 14 | return "".join(result) 15 | 16 | 17 | def flatten_dict(d, parent_key="", sep="."): 18 | items = [] 19 | for k, v in d.items(): 20 | new_key = f"{parent_key}{sep}{k}" if parent_key else k 21 | if isinstance(v, dict): 22 | items.extend(flatten_dict(v, new_key, sep=sep).items()) 23 | else: 24 | items.append((new_key, v)) 25 | return dict(items) 26 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.yml: -------------------------------------------------------------------------------- 1 | name: ✨ Feature Request 2 | description: Suggest a new feature 3 | title: "[Feature]: " 4 | labels: ["enhancement"] 5 | body: 6 | - type: dropdown 7 | id: request_type 8 | attributes: 9 | label: Feature Type 10 | options: 11 | - Additional sensor/entity 12 | - Configuration option 13 | - Localization/translation 14 | - Refactor/cleanup 15 | - Documentation improvement 16 | - Other 17 | validations: 18 | required: true 19 | 20 | - type: input 21 | id: device_model 22 | attributes: 23 | label: Device Model 24 | placeholder: "e.g., DELTA 2 Max, PowerStream" 25 | validations: 26 | required: true 27 | 28 | - type: textarea 29 | id: feature_description 30 | attributes: 31 | label: What feature do you want? 32 | placeholder: Describe the feature and why it would be useful 33 | validations: 34 | required: true -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/new_device.yml: -------------------------------------------------------------------------------- 1 | name: 📱 New Device Support 2 | description: Request support for a new EcoFlow device 3 | title: "[New Device]: " 4 | labels: ["new device"] 5 | body: 6 | - type: input 7 | id: device_model 8 | attributes: 9 | label: Device Model 10 | placeholder: "e.g., DELTA 3 Plus, RIVER 3" 11 | validations: 12 | required: true 13 | 14 | - type: input 15 | id: public_api_reference 16 | attributes: 17 | label: Public API Reference Link 18 | description: Link to the device documentation on https://developer-eu.ecoflow.com/us/document/ 19 | placeholder: "https://developer-eu.ecoflow.com/us/document/..." 20 | validations: 21 | required: true 22 | 23 | - type: textarea 24 | id: diagnostic_json 25 | attributes: 26 | label: Diagnostic Data (Optional) 27 | description: If available, paste diagnostic JSON data from HA or API responses 28 | placeholder: Paste JSON data here... 29 | render: json -------------------------------------------------------------------------------- /custom_components/ecoflow_cloud/button.py: -------------------------------------------------------------------------------- 1 | import logging 2 | from typing import Any 3 | 4 | from homeassistant.config_entries import ConfigEntry 5 | from homeassistant.core import HomeAssistant 6 | from homeassistant.helpers.entity_platform import AddEntitiesCallback 7 | 8 | from . import ECOFLOW_DOMAIN 9 | from .api import EcoflowApiClient 10 | from .entities import BaseButtonEntity 11 | 12 | _LOGGER = logging.getLogger(__name__) 13 | 14 | 15 | async def async_setup_entry( 16 | hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback 17 | ): 18 | client: EcoflowApiClient = hass.data[ECOFLOW_DOMAIN][entry.entry_id] 19 | for sn, device in client.devices.items(): 20 | async_add_entities(device.buttons(client)) 21 | 22 | 23 | class EnabledButtonEntity(BaseButtonEntity): 24 | def press(self, **kwargs: Any) -> None: 25 | if self._command: 26 | self.send_set_message(0, self.command_dict(0)) 27 | 28 | 29 | class DisabledButtonEntity(BaseButtonEntity): 30 | async def async_press(self, **kwargs: Any) -> None: 31 | if self._command: 32 | self.send_set_message(0, self.command_dict(0)) 33 | -------------------------------------------------------------------------------- /custom_components/ecoflow_cloud/api/message.py: -------------------------------------------------------------------------------- 1 | import json 2 | import random 3 | from abc import ABC, abstractmethod 4 | from typing import override 5 | 6 | from paho.mqtt.client import PayloadType 7 | 8 | 9 | class Message(ABC): 10 | @abstractmethod 11 | def to_mqtt_payload(self) -> PayloadType: 12 | raise NotImplementedError() 13 | 14 | 15 | JSONType = None | bool | int | float | str | list["JSONType"] | dict[str, "JSONType"] 16 | JSONDict = dict[str, JSONType] 17 | 18 | 19 | class JSONMessage(Message): 20 | def __init__(self, data: JSONDict) -> None: 21 | super().__init__() 22 | self.data = data 23 | 24 | @staticmethod 25 | def gen_seq() -> int: 26 | return 999900000 + random.randint(10000, 99999) 27 | 28 | @staticmethod 29 | def prepare_payload(command: JSONDict) -> JSONDict: 30 | payload: JSONDict = { 31 | "from": "HomeAssistant", 32 | "id": str(JSONMessage.gen_seq()), 33 | "version": "1.0", 34 | } 35 | payload.update(command) 36 | return payload 37 | 38 | @override 39 | def to_mqtt_payload(self) -> PayloadType: 40 | return json.dumps(JSONMessage.prepare_payload(self.data)) 41 | -------------------------------------------------------------------------------- /docs/devices/SMART_METER.md: -------------------------------------------------------------------------------- 1 | ## SMART_METER 2 | 3 | *Sensors* 4 | - Power Grid Global (`254_21.totalPower`) 5 | - Power Grid L1 (`254_21.powerL1`) _(disabled)_ 6 | - Power Grid L2 (`254_21.powerL2`) _(disabled)_ 7 | - Power Grid L3 (`254_21.powerL3`) _(disabled)_ 8 | - Power Grid (L1) In Amps (`254_21.currentL1`) _(disabled)_ 9 | - Power Grid (L2) In Amps (`254_21.currentL2`) _(disabled)_ 10 | - Power Grid (L3) In Amps (`254_21.currentL3`) _(disabled)_ 11 | - Power Grid (L1) Volts (`254_21.voltageL1`) _(disabled)_ 12 | - Power Grid (L2) Volts (`254_21.voltageL2`) _(disabled)_ 13 | - Power Grid (L3) Volts (`254_21.voltageL3`) _(disabled)_ 14 | - L1 net energy daily (`254_21.energy.energyL1daily`) _(disabled)_ 15 | - L2 net energy daily (`254_21.energy.energyL2daily`) _(disabled)_ 16 | - L3 net energy daily (`254_21.energy.energyL3daily`) _(disabled)_ 17 | - Net energy consumption (`254_21.energy.netEnergyConsumption`) 18 | - Lifetime delivery (`254_21.energy.lifeTimeEnergyDelivery`) 19 | - Lifetime consumption (`254_21.energy.lifeTimeEnergyConsumption`) 20 | - Timezone (`254_21.utcTimezone`) _(disabled)_ 21 | - Status 22 | 23 | *Switches* 24 | 25 | *Sliders (numbers)* 26 | 27 | *Selects* 28 | 29 | 30 | -------------------------------------------------------------------------------- /docs/devices/RIVER_MINI.md: -------------------------------------------------------------------------------- 1 | ## RIVER_MINI 2 | 3 | *Sensors* 4 | - Main Battery Level (`inv.soc`) 5 | - AC In Power (`inv.inputWatts`) 6 | - AC Out Power (`inv.outputWatts`) 7 | - AC In Volts (`inv.invInVol`) 8 | - AC Out Volts (`inv.invOutVol`) 9 | - Solar In Voltage (`inv.dcInVol`) 10 | - Solar In Current (`inv.dcInAmp`) 11 | - Inverter Inside Temperature (`inv.inTemp`) 12 | - Inverter Outside Temperature (`inv.outTemp`) 13 | - Solar In Energy (`pd.chgSunPower`) 14 | - Battery Charge Energy from AC (`pd.chgPowerAC`) 15 | - Battery Charge Energy from DC (`pd.chgPowerDC`) 16 | - Battery Discharge Energy to AC (`pd.dsgPowerAC`) 17 | - Battery Discharge Energy to DC (`pd.dsgPowerDC`) 18 | - Total In Power (`pd.wattsInSum`) 19 | - Total Out Power (`pd.wattsOutSum`) 20 | - Cycles (`inv.cycles`) 21 | 22 | *Switches* 23 | - AC Enabled (`inv.cfgAcEnabled` -> `{"moduleType": 0, "operateType": "TCP", "params": {"id": 66, "enabled": "VALUE"}}`) 24 | - X-Boost Enabled (`inv.cfgAcXboost` -> `{"moduleType": 0, "operateType": "TCP", "params": {"id": 66, "xboost": "VALUE"}}`) 25 | 26 | *Sliders (numbers)* 27 | - Max Charge Level (`inv.maxChargeSoc` -> `{"moduleType": 0, "operateType": "TCP", "params": {"id": 0, "maxChgSoc": "VALUE"}}` [30 - 100]) 28 | 29 | *Selects* 30 | 31 | 32 | -------------------------------------------------------------------------------- /docs/devices/Power_Ocean-Public.md: -------------------------------------------------------------------------------- 1 | ## Power_Ocean 2 | 3 | *Sensors* 4 | - bpSoc (`96_8.bpSoc`) 5 | - pcsAPhase.vol (`96_1.pcsAPhase.vol`) 6 | - pcsAPhase.amp (`96_1.pcsAPhase.amp`) 7 | - pcsAPhase.actPwr (`96_1.pcsAPhase.actPwr`) 8 | - pcsAPhase.reactPwr (`96_1.pcsAPhase.reactPwr`) 9 | - pcsAPhase.apparentPwr (`96_1.pcsAPhase.apparentPwr`) 10 | - pcsBPhase.vol (`96_1.pcsBPhase.vol`) 11 | - pcsBPhase.amp (`96_1.pcsBPhase.amp`) 12 | - pcsBPhase.actPwr (`96_1.pcsBPhase.actPwr`) 13 | - pcsBPhase.reactPwr (`96_1.pcsBPhase.reactPwr`) 14 | - pcsBPhase.apparentPwr (`96_1.pcsBPhase.apparentPwr`) 15 | - pcsCPhase.vol (`96_1.pcsCPhase.vol`) 16 | - pcsCPhase.amp (`96_1.pcsCPhase.amp`) 17 | - pcsCPhase.actPwr (`96_1.pcsCPhase.actPwr`) 18 | - pcsCPhase.reactPwr (`96_1.pcsCPhase.reactPwr`) 19 | - pcsCPhase.apparentPwr (`96_1.pcsCPhase.apparentPwr`) 20 | - mpptPv1.pwr (`96_1.mpptHeartBeat[0].mpptPv[0].pwr`) 21 | - mpptPv1.amp (`96_1.mpptHeartBeat[0].mpptPv[0].amp`) 22 | - mpptPv1.vol (`96_1.mpptHeartBeat[0].mpptPv[0].vol`) 23 | - mpptPv2.pwr (`96_1.mpptHeartBeat[0].mpptPv[1].pwr`) 24 | - mpptPv2.amp (`96_1.mpptHeartBeat[0].mpptPv[1].amp`) 25 | - mpptPv2.vol (`96_1.mpptHeartBeat[0].mpptPv[1].vol`) 26 | - Status 27 | 28 | *Switches* 29 | 30 | *Sliders (numbers)* 31 | 32 | *Selects* 33 | 34 | 35 | -------------------------------------------------------------------------------- /docs/devices/Smart_Home_Panel-Public.md: -------------------------------------------------------------------------------- 1 | ## Smart_Home_Panel 2 | 3 | *Sensors* 4 | - Power Grid (`heartbeat.gridSta`) 5 | - Battery Level (`heartbeat.backupBatPer`) 6 | - Remaining Time (`heartbeat.backupChaTime`) 7 | - Main Battery Temperature (`heartbeat.energyInfos[0].emsBatTemp`) 8 | - Main Battery Input Power (`heartbeat.energyInfos[0].lcdInputWatts`) (energy: _[Device Name]_ Main Battery Input Energy) 9 | - Main Battery Output Power (`heartbeat.energyInfos[0].outputPower`) (energy: _[Device Name]_ Main Battery Output Energy) 10 | - Power Grid Today (`heartbeat.gridDayWatth`) 11 | - Battery Today (`heartbeat.backupDayWatth`) 12 | 13 | *Switches* 14 | - EPS Mode (`'epsModeInfo.eps'` -> `{"operateType": "TCP", "params": {"cmdSet": 11, "id": 24, "eps": "VALUE"}}`) 15 | - Main Battery Charge (`heartbeat.backupCmdChCtrlInfos[0].ctrlSta` -> `{"operateType": "TCP", "params": {"cmdSet": 11, "id": 17, "sta": 2, "ctrlMode": 1, "ch": 10}}`) 16 | 17 | *Sliders (numbers)* 18 | - Min Discharge Level (`'backupChaDiscCfg.discLower'` -> `{"operateType": "TCP", "params": {"cmdSet": 11, "id": 29, "discLower": "VALUE", "forceChargeHigh": 100}}` [0 - 30]) 19 | - Max Charge Level (`'backupChaDiscCfg.forceChargeHigh'` -> `{"operateType": "TCP", "params": {"cmdSet": 11, "id": 29, "forceChargeHigh": "VALUE", "discLower": 0}}` [50 - 100]) 20 | 21 | *Selects* 22 | 23 | 24 | -------------------------------------------------------------------------------- /docs/integration.md: -------------------------------------------------------------------------------- 1 | In order to add a new entity for a device type, following info is needed: 2 | 3 | - _sensor_: name, data_key 4 | - _switch_: name, data_key, action_command 5 | - _select_: name, data_key, action_command, options 6 | - _slider_: name, data_key, action_command, min, max 7 | 8 | Current integrations details: 9 | 10 | - [DELTA_2](devices/DELTA_2.md) 11 | - [RIVER_2](devices/RIVER_2.md) 12 | - [RIVER_2_MAX](devices/RIVER_2_MAX.md) 13 | - [RIVER_2_PRO](devices/RIVER_2_PRO.md) 14 | - [DELTA_PRO](devices/DELTA_PRO.md) 15 | - [RIVER_MAX](devices/RIVER_MAX.md) 16 | - [RIVER_PRO](devices/RIVER_PRO.md) 17 | - [RIVER_MINI](devices/RIVER_MINI.md) 18 | - [DELTA_MINI](devices/DELTA_MINI.md) 19 | - [DELTA_MAX](devices/DELTA_MAX.md) 20 | - [DELTA_2_MAX](devices/DELTA_2_MAX.md) 21 | - [POWERSTREAM](devices/POWERSTREAM.md) 22 | - [GLACIER](devices/GLACIER.md) 23 | - [WAVE_2](devices/WAVE_2.md) 24 | - [DELTA_2](devices/DELTA_2-Public.md) 25 | - [DELTA_2_Max](devices/DELTA_2_Max-Public.md) 26 | - [RIVER_2](devices/RIVER_2-Public.md) 27 | - [RIVER_2_Max](devices/RIVER_2_Max-Public.md) 28 | - [Smart_Home_Panel](devices/Smart_Home_Panel-Public.md) 29 | - [Smart_Meter](devices/Smart_Meter-Public.md) 30 | - [Smart_Plug](devices/Smart_Plug-Public.md) 31 | - [Stream_AC](devices/Stream_AC-Public.md) 32 | - [Stream_ULTRA](devices/Stream_Ultra-Public.md) 33 | - [Stream_Microinverter](devices/Stream_Microinverter-Public.md) 34 | - [PowerStream](devices/PowerStream-Public.md) 35 | - [Diagnostic](devices/Diagnostic-Public.md) 36 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.yml: -------------------------------------------------------------------------------- 1 | name: 🐛 Bug Report 2 | description: Report a bug or issue 3 | title: "[Bug]: " 4 | labels: ["bug"] 5 | body: 6 | - type: input 7 | id: versions 8 | attributes: 9 | label: Versions 10 | placeholder: "Integration v1.4.0-beta2, HA 2025.9.2" 11 | validations: 12 | required: true 13 | 14 | - type: input 15 | id: device_model 16 | attributes: 17 | label: Device Model 18 | placeholder: "e.g., DELTA 2 Max, PowerStream" 19 | validations: 20 | required: true 21 | 22 | - type: dropdown 23 | id: integration_type 24 | attributes: 25 | label: Integration Type 26 | options: 27 | - Internal/Private API 28 | - Public API 29 | - Not sure 30 | validations: 31 | required: true 32 | 33 | - type: textarea 34 | id: problem 35 | attributes: 36 | label: What's the problem? 37 | placeholder: Describe the issue and what you expected to happen 38 | validations: 39 | required: true 40 | 41 | - type: textarea 42 | id: logs 43 | attributes: 44 | label: Logs (if any) 45 | placeholder: Paste relevant logs here 46 | render: text 47 | 48 | - type: checkboxes 49 | id: status 50 | attributes: 51 | label: Device Status 52 | options: 53 | - label: Works in EcoFlow app 54 | - label: Shows as connected in HA 55 | - label: All entities show zeros/unavailable 56 | - label: Was working before -------------------------------------------------------------------------------- /custom_components/ecoflow_cloud/diagnostics.py: -------------------------------------------------------------------------------- 1 | from datetime import timedelta 2 | 3 | from homeassistant.config_entries import ConfigEntry 4 | from homeassistant.core import HomeAssistant 5 | 6 | from . import ECOFLOW_DOMAIN 7 | from .api import EcoflowApiClient 8 | 9 | 10 | def _to_serializable(x): 11 | t = type(x) 12 | if t is dict: 13 | x = {y: _to_serializable(x[y]) for y in x} 14 | if t is timedelta: 15 | x = x.__str__() 16 | return x 17 | 18 | 19 | async def async_get_config_entry_diagnostics(hass: HomeAssistant, entry: ConfigEntry): 20 | client: EcoflowApiClient = hass.data[ECOFLOW_DOMAIN][entry.entry_id] 21 | values = {"EcoFlow":[]} 22 | for (sn, device) in client.devices.items(): 23 | value = { 24 | 'device': device.device_info.device_type, 25 | 'name': device.device_info.name, 26 | 'sn': sn, 27 | 'params_time': device.data.params_time, 28 | 'status_time': device.data.status_time, 29 | 'params': dict(sorted(device.data.params.items())), 30 | 'set': [dict(sorted(k.items())) for k in device.data.set], 31 | 'set_reply': [dict(sorted(k.items())) for k in device.data.set_reply], 32 | 'get': [dict(sorted(k.items())) for k in device.data.get], 33 | 'get_reply': [dict(sorted(k.items())) for k in device.data.get_reply], 34 | 'raw_data': device.data.raw_data, 35 | } 36 | values["EcoFlow"].append(value) 37 | return values 38 | -------------------------------------------------------------------------------- /debug.init.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import logging 3 | import os 4 | from types import MappingProxyType 5 | 6 | from homeassistant.config_entries import ConfigEntry 7 | from homeassistant.core import HomeAssistant 8 | 9 | from custom_components.ecoflow_cloud.devices.powerkit import PowerKit 10 | from custom_components.ecoflow_cloud.entities import BaseSensorEntity 11 | from custom_components.ecoflow_cloud import EcoflowAuthentication, EcoflowMQTTClient 12 | 13 | logging.basicConfig(level=logging.INFO) 14 | _LOGGER = logging.getLogger(__name__) 15 | 16 | loop = asyncio.new_event_loop() 17 | asyncio.set_event_loop(loop) 18 | 19 | async def main(): 20 | 21 | data = MappingProxyType( 22 | { 23 | "type": "powerkit", 24 | "device_id": os.environ['ecoflowSn'] 25 | } 26 | ) 27 | 28 | config = ConfigEntry( 29 | version='1.0.0', 30 | minor_version='1', 31 | domain='homeassistant.local', 32 | title='debugEcoflow', 33 | data=data, 34 | source='', 35 | options= MappingProxyType( 36 | { 37 | "refresh_period_sec": 1 38 | }) 39 | ) 40 | auth = EcoflowAuthentication(os.environ['ecoflowUserName'], os.environ['ecoflowPassword']) 41 | auth.authorize() 42 | home = HomeAssistant('./') 43 | client = EcoflowMQTTClient(home, config, auth) 44 | powerkit = PowerKit() 45 | sensors = powerkit.sensors(client) 46 | client.data.params_observable().subscribe(lambda v: updateSensors(v)) 47 | def updateSensors(data: dict[str, any]): 48 | for v in sensors: 49 | v.hass = home 50 | v._updated(data) 51 | _LOGGER.info(v.name) 52 | _LOGGER.info(v._attr_native_value) 53 | 54 | while True: 55 | await asyncio.sleep(1) 56 | asyncio.run(main()) 57 | -------------------------------------------------------------------------------- /docs/Contribution.md: -------------------------------------------------------------------------------- 1 | ## Contribute 2 | 3 | 1. open an issue 4 | 1. make a fork of this repo 5 | 1. make your changes 6 | 1. test it (manual because right now their a no automated tests) 7 | 1. make a pull request 8 | 1. wait for approval 9 | 10 | ### Setting up your development machine 11 | 12 | > Note for the easy documentation only the dev container way is described here. If you want to develop nativ on you PC good luck for now 13 | 14 | You need: 15 | 16 | - [VsCode](https://code.visualstudio.com/) 17 | - [Dev Containers Extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) 18 | - some container engine that is supported by Dev Containers Extension for example Docker 19 | 20 | Starting Development 21 | 22 | 1. Start an empty VsCode 23 | 1. Press `STRG` + `SHIFT` + `P` 24 | 1. Select `Dev Containers: Clone Repository in Container Volume...` 25 | 1. Provide the URL of your fork 26 | 1. Wait (depending on your internet connection and PC this step can take more then half an hour, only the first time) 27 | 1. Press `STRG` + `SHIFT` + `P` 28 | 1. Select `Tasks: Run Task` 29 | 1. Select `Reset homeassistant` 30 | 1. Now you can select in the Debugger of VsCode `Home Assistant` (this will again run for a while) 31 | 1. Now you should have a running instance of Home Assistant and you can access it on your host via `http://127.0.0.1:8123/` 32 | 33 | If you want to debug again after the first start we recommend using `Home Assistant (skip pip)` because it's way faster. 34 | 35 | After you finished your main work we recommend to run the task `Generate Docs`: 36 | 37 | 1. Press `STRG` + `SHIFT` + `P` 38 | 1. Select `Tasks: Run Task` 39 | 1. Select `Generate Docs` 40 | 1. Replace the paragraph `Current state` in `README.md` with `summary.md` content 41 | 42 | This will update the device documentation. 43 | -------------------------------------------------------------------------------- /custom_components/ecoflow_cloud/devices/public/data_bridge.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | _LOGGER = logging.getLogger(__name__) 4 | 5 | plain_to_status: dict[str, str] = { 6 | "pd": "pdStatus", 7 | "mppt": "mpptStatus", 8 | "bms_emsStatus": "emsStatus", 9 | "bms_bmsStatus": "bmsStatus", 10 | "bms_bmsInfo": "bmsInfo", 11 | "inv": "invStatus", 12 | "bms_slave": "bmsSlaveStatus", 13 | "bms_slave_bmsSlaveStatus_1": "bmsSlaveStatus_1", 14 | "bms_slave_bmsSlaveStatus_2": "bmsSlaveStatus_2", 15 | } 16 | 17 | status_to_plain = dict((v, k) for (k, v) in plain_to_status.items()) 18 | 19 | 20 | def to_plain(raw_data: dict[str, any]) -> dict[str, any]: 21 | new_params = {} 22 | prefix = "" 23 | if "typeCode" in raw_data: 24 | prefix1 = status_to_plain.get( 25 | raw_data["typeCode"], "unknown_" + raw_data["typeCode"] 26 | ) 27 | prefix += f"{prefix1}." 28 | elif "cmdFunc" in raw_data and "cmdId" in raw_data: 29 | prefix += f"{raw_data['cmdFunc']}_{raw_data['cmdId']}." 30 | else : 31 | prefix += "" 32 | 33 | if "param" in raw_data: 34 | for k, v in raw_data["param"].items(): 35 | new_params[f"{prefix}{k}"] = v 36 | 37 | if "params" in raw_data: 38 | for k, v in raw_data["params"].items(): 39 | new_params[f"{prefix}{k}"] = v 40 | 41 | for k, v in raw_data.items(): 42 | if k != "param" and k != "params": 43 | new_params[f"{prefix}{k}"] = v 44 | 45 | new_params2 = {} 46 | for k, v in new_params.items(): 47 | new_params2[k] = v 48 | if isinstance(v, dict): 49 | for k2, v2 in v.items(): 50 | new_params2[f"{k}.{k2}"] = v2 51 | 52 | result = {"params": new_params2, "raw_data": raw_data} 53 | _LOGGER.debug(str(result)) 54 | 55 | return result -------------------------------------------------------------------------------- /docs/devices/Smart_Meter-Public.md: -------------------------------------------------------------------------------- 1 | ## Smart_Meter 2 | 3 | *Sensors* 4 | - Power Grid Global (`powGetSysGrid`) 5 | - Power Grid L1 (`gridConnectionPowerL1`) _(disabled)_ 6 | - Power Grid L2 (`gridConnectionPowerL2`) _(disabled)_ 7 | - Power Grid L3 (`gridConnectionPowerL3`) _(disabled)_ 8 | - Power Grid (L1) In Amps (`gridConnectionAmpL1`) _(disabled)_ 9 | - Power Grid (L2) In Amps (`gridConnectionAmpL2`) _(disabled)_ 10 | - Power Grid (L3) In Amps (`gridConnectionAmpL3`) _(disabled)_ 11 | - Power Grid (L1) Volts (`gridConnectionVolL1`) _(disabled)_ 12 | - Power Grid (L2) Volts (`gridConnectionVolL2`) _(disabled)_ 13 | - Power Grid (L3) Volts (`gridConnectionVolL3`) _(disabled)_ 14 | - Flag L1 (`gridConnectionFlagL1`) _(disabled)_ 15 | - Flag L2 (`gridConnectionFlagL2`) _(disabled)_ 16 | - Flag L3 (`gridConnectionFlagL3`) _(disabled)_ 17 | - L1 Lifetime net usage (`gridConnectionDataRecord.todayActiveL1`) _(disabled)_ 18 | - L2 Lifetime net usage (`gridConnectionDataRecord.todayActiveL2`) _(disabled)_ 19 | - L3 Lifetime net usage (`gridConnectionDataRecord.todayActiveL3`) _(disabled)_ 20 | - Lifetime consumption (`gridConnectionDataRecord.todayActive`) 21 | - Net energy consumption (`gridConnectionDataRecord.totalActiveEnergy`) 22 | - Lifetime delivery (`gridConnectionDataRecord.totalReactiveEnergy`) 23 | - Timezone (`utcTimezone`) _(disabled)_ 24 | - Grid connection power factor (`gridConnectionPowerFactor`) _(disabled)_ 25 | - Grid connection state (`gridConnectionSta`) _(disabled)_ 26 | - Country code (`countryCode`) _(disabled)_ 27 | - Town code (`townCode`) _(disabled)_ 28 | - System group id (`systemGroupId`) _(disabled)_ 29 | - Factory mode enabled (`factoryModeEnable`) _(disabled)_ 30 | - Debug mode enabled (`debugModeEnable`) _(disabled)_ 31 | - Status 32 | 33 | *Switches* 34 | 35 | *Sliders (numbers)* 36 | 37 | *Selects* 38 | 39 | 40 | -------------------------------------------------------------------------------- /custom_components/ecoflow_cloud/translations/ja.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "EcoFlow-Cloud", 3 | "config": { 4 | "step": { 5 | "user": { 6 | "data": { 7 | "group": "デバイスグループ" 8 | } 9 | }, 10 | "api": { 11 | "menu_options": { 12 | "api_add_device": "デバイスを追加", 13 | "remove_device": "デバイスを削除", 14 | "finish": "完了" 15 | }, 16 | "data": { 17 | "access_key": "アクセスキー", 18 | "secret_key": "シークレットキー", 19 | "load_all_devices": "自動デバイス読み込み" 20 | } 21 | }, 22 | "choose_type": { 23 | "menu_options": { 24 | "api": "パブリックAPIを使用", 25 | "manual": "Ecoflowアカウントを使用" 26 | } 27 | }, 28 | "select_device": { 29 | "data": { 30 | "select_device": "デバイスを選択" 31 | } 32 | }, 33 | "confirm_cloud_device": { 34 | "data": { 35 | "device_type": "デバイスタイプ", 36 | "device_name": "デバイス名", 37 | "device_id": "デバイスSN" 38 | } 39 | }, 40 | "manual": { 41 | "menu_options": { 42 | "manual_add_device": "デバイスを追加", 43 | "remove_device": "デバイスを削除", 44 | "finish": "完了" 45 | }, 46 | "data": { 47 | "username": "ユーザーメールアドレス", 48 | "password": "ユーザーパスワード" 49 | } 50 | }, 51 | "manual_device_input": { 52 | "data": { 53 | "device_type": "デバイスタイプ", 54 | "device_name": "デバイス名", 55 | "device_id": "デバイスSN" 56 | } 57 | } 58 | } 59 | }, 60 | "options": { 61 | "step": { 62 | "init": { 63 | "data": { 64 | "select_device": "デバイスを選択" 65 | } 66 | }, 67 | "options": { 68 | "data": { 69 | "power_step": "充電電力スライダーのステップ", 70 | "refresh_period_sec": "データ更新間隔(秒)", 71 | "diagnostic_mode": "診断モード" 72 | } 73 | } 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /docs/devices/STREAM_AC.md: -------------------------------------------------------------------------------- 1 | ## STREAM_AC 2 | 3 | *Sensors* 4 | - Cumulative Capacity Charge (mAh) (`accuChgCap`) _(disabled)_ 5 | - Cumulative Energy Charge (Wh) (`accuChgEnergy`) _(disabled)_ 6 | - Cumulative Capacity Discharge (mAh) (`accuDsgCap`) _(disabled)_ 7 | - Cumulative Energy Discharge (Wh) (`accuDsgEnergy`) _(disabled)_ 8 | - Charge Remaining Time (`bmsChgRemTime`) _(disabled)_ 9 | - Discharge Remaining Time (`bmsDsgRemTime`) _(disabled)_ 10 | - Cycles (`cycles`) _(disabled)_ 11 | - Design Capacity (`designCap`) _(disabled)_ 12 | - Power Battery SOC (`f32ShowSoc`) _(disabled)_ 13 | - Full Capacity (`fullCap`) _(disabled)_ 14 | - Power AC (`gridConnectionPower`) 15 | - Power Volts (`gridConnectionVol`) _(disabled)_ 16 | - In Power (`inputWatts`) _(disabled)_ 17 | - Max Cell Temperature (`maxCellTemp`) _(disabled)_ 18 | - Max Cell Volts (`maxCellVol`) _(disabled)_ 19 | - Min Cell Temperature (`minCellTemp`) _(disabled)_ 20 | - Min Cell Volts (`minCellVol`) _(disabled)_ 21 | - Out Power (`outputWatts`) _(disabled)_ 22 | - Power Battery (`powGetBpCms`) 23 | - Power PV 1 (`powGetPv`) _(auto)_ 24 | - Power PV 2 (`powGetPv2`) _(auto)_ 25 | - Power PV 3 (`powGetPv3`) _(auto)_ 26 | - Power PV 4 (`powGetPv4`) _(auto)_ 27 | - Power PV Sum (`powGetPvSum`) 28 | - Power SCHUKO1 (`powGetSchuko1`) _(auto)_ 29 | - Power SCHUKO2 (`powGetSchuko2`) _(auto)_ 30 | - Power Grid (`powGetSysGrid`) 31 | - Power Sys Load (`powGetSysLoad`) 32 | - Power Sys Load From Battery (`powGetSysLoadFromBp`) 33 | - Power Sys Load From Grid (`powGetSysLoadFromGrid`) 34 | - Power Sys Load From PV (`powGetSysLoadFromPv`) 35 | - Real State of Health (`realSoh`) _(disabled)_ 36 | - Remain Capacity (`remainCap`) _(disabled)_ 37 | - Remaining Time (`remainTime`) _(disabled)_ 38 | - Power Battery (`soc`) _(disabled)_ 39 | - State of Health (`soh`) _(disabled)_ 40 | - Power AC SYS (`sysGridConnectionPower`) _(disabled)_ 41 | - Battery Temperature (`temp`) _(disabled)_ 42 | - Battery Volts (`vol`) _(disabled)_ 43 | 44 | *Switches* 45 | 46 | *Sliders (numbers)* 47 | 48 | *Selects* 49 | 50 | 51 | -------------------------------------------------------------------------------- /docs/devices/STREAM_PRO.md: -------------------------------------------------------------------------------- 1 | ## STREAM_PRO 2 | 3 | *Sensors* 4 | - Cumulative Capacity Charge (mAh) (`accuChgCap`) _(disabled)_ 5 | - Cumulative Energy Charge (Wh) (`accuChgEnergy`) _(disabled)_ 6 | - Cumulative Capacity Discharge (mAh) (`accuDsgCap`) _(disabled)_ 7 | - Cumulative Energy Discharge (Wh) (`accuDsgEnergy`) _(disabled)_ 8 | - Charge Remaining Time (`bmsChgRemTime`) _(disabled)_ 9 | - Discharge Remaining Time (`bmsDsgRemTime`) _(disabled)_ 10 | - Cycles (`cycles`) _(disabled)_ 11 | - Design Capacity (`designCap`) _(disabled)_ 12 | - Power Battery SOC (`f32ShowSoc`) _(disabled)_ 13 | - Full Capacity (`fullCap`) _(disabled)_ 14 | - Power AC (`gridConnectionPower`) 15 | - Power Volts (`gridConnectionVol`) _(disabled)_ 16 | - In Power (`inputWatts`) _(disabled)_ 17 | - Max Cell Temperature (`maxCellTemp`) _(disabled)_ 18 | - Max Cell Volts (`maxCellVol`) _(disabled)_ 19 | - Min Cell Temperature (`minCellTemp`) _(disabled)_ 20 | - Min Cell Volts (`minCellVol`) _(disabled)_ 21 | - Out Power (`outputWatts`) _(disabled)_ 22 | - Power Battery (`powGetBpCms`) 23 | - Power PV 1 (`powGetPv`) _(auto)_ 24 | - Power PV 2 (`powGetPv2`) _(auto)_ 25 | - Power PV 3 (`powGetPv3`) _(auto)_ 26 | - Power PV 4 (`powGetPv4`) _(auto)_ 27 | - Power PV Sum (`powGetPvSum`) 28 | - Power SCHUKO1 (`powGetSchuko1`) _(auto)_ 29 | - Power SCHUKO2 (`powGetSchuko2`) _(auto)_ 30 | - Power Grid (`powGetSysGrid`) 31 | - Power Sys Load (`powGetSysLoad`) 32 | - Power Sys Load From Battery (`powGetSysLoadFromBp`) 33 | - Power Sys Load From Grid (`powGetSysLoadFromGrid`) 34 | - Power Sys Load From PV (`powGetSysLoadFromPv`) 35 | - Real State of Health (`realSoh`) _(disabled)_ 36 | - Remain Capacity (`remainCap`) _(disabled)_ 37 | - Remaining Time (`remainTime`) _(disabled)_ 38 | - Power Battery (`soc`) _(disabled)_ 39 | - State of Health (`soh`) _(disabled)_ 40 | - Power AC SYS (`sysGridConnectionPower`) _(disabled)_ 41 | - Battery Temperature (`temp`) _(disabled)_ 42 | - Battery Volts (`vol`) _(disabled)_ 43 | 44 | *Switches* 45 | 46 | *Sliders (numbers)* 47 | 48 | *Selects* 49 | 50 | 51 | -------------------------------------------------------------------------------- /docs/devices/STREAM_ULTRA.md: -------------------------------------------------------------------------------- 1 | ## STREAM_ULTRA 2 | 3 | *Sensors* 4 | - Cumulative Capacity Charge (mAh) (`accuChgCap`) _(disabled)_ 5 | - Cumulative Energy Charge (Wh) (`accuChgEnergy`) _(disabled)_ 6 | - Cumulative Capacity Discharge (mAh) (`accuDsgCap`) _(disabled)_ 7 | - Cumulative Energy Discharge (Wh) (`accuDsgEnergy`) _(disabled)_ 8 | - Charge Remaining Time (`bmsChgRemTime`) _(disabled)_ 9 | - Discharge Remaining Time (`bmsDsgRemTime`) _(disabled)_ 10 | - Cycles (`cycles`) _(disabled)_ 11 | - Design Capacity (`designCap`) _(disabled)_ 12 | - Power Battery SOC (`f32ShowSoc`) _(disabled)_ 13 | - Full Capacity (`fullCap`) _(disabled)_ 14 | - Power AC (`gridConnectionPower`) 15 | - Power Volts (`gridConnectionVol`) _(disabled)_ 16 | - In Power (`inputWatts`) _(disabled)_ 17 | - Max Cell Temperature (`maxCellTemp`) _(disabled)_ 18 | - Max Cell Volts (`maxCellVol`) _(disabled)_ 19 | - Min Cell Temperature (`minCellTemp`) _(disabled)_ 20 | - Min Cell Volts (`minCellVol`) _(disabled)_ 21 | - Out Power (`outputWatts`) _(disabled)_ 22 | - Power Battery (`powGetBpCms`) 23 | - Power PV 1 (`powGetPv`) _(auto)_ 24 | - Power PV 2 (`powGetPv2`) _(auto)_ 25 | - Power PV 3 (`powGetPv3`) _(auto)_ 26 | - Power PV 4 (`powGetPv4`) _(auto)_ 27 | - Power PV Sum (`powGetPvSum`) 28 | - Power SCHUKO1 (`powGetSchuko1`) _(auto)_ 29 | - Power SCHUKO2 (`powGetSchuko2`) _(auto)_ 30 | - Power Grid (`powGetSysGrid`) 31 | - Power Sys Load (`powGetSysLoad`) 32 | - Power Sys Load From Battery (`powGetSysLoadFromBp`) 33 | - Power Sys Load From Grid (`powGetSysLoadFromGrid`) 34 | - Power Sys Load From PV (`powGetSysLoadFromPv`) 35 | - Real State of Health (`realSoh`) _(disabled)_ 36 | - Remain Capacity (`remainCap`) _(disabled)_ 37 | - Remaining Time (`remainTime`) _(disabled)_ 38 | - Power Battery (`soc`) _(disabled)_ 39 | - State of Health (`soh`) _(disabled)_ 40 | - Power AC SYS (`sysGridConnectionPower`) _(disabled)_ 41 | - Battery Temperature (`temp`) _(disabled)_ 42 | - Battery Volts (`vol`) _(disabled)_ 43 | 44 | *Switches* 45 | 46 | *Sliders (numbers)* 47 | 48 | *Selects* 49 | 50 | 51 | -------------------------------------------------------------------------------- /custom_components/ecoflow_cloud/translations/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "EcoFlow-Cloud", 3 | "config": { 4 | "step": { 5 | "user": { 6 | "data": { 7 | "group": "Device group" 8 | } 9 | }, 10 | "api": { 11 | "menu_options": { 12 | "api_add_device": "Add device", 13 | "remove_device": "Remove device", 14 | "finish": "Finish" 15 | }, 16 | "data": { 17 | "access_key": "Access key", 18 | "secret_key": "Secret key", 19 | "load_all_devices": "Automatic device loading" 20 | } 21 | }, 22 | "choose_type": { 23 | "menu_options": { 24 | "api": "Use public API", 25 | "manual": "Use application API" 26 | } 27 | }, 28 | "select_device": { 29 | "data": { 30 | "select_device": "Select device" 31 | } 32 | }, 33 | "confirm_cloud_device": { 34 | "data": { 35 | "device_type": "Device type", 36 | "device_name": "Device name", 37 | "device_id": "Device SN" 38 | } 39 | }, 40 | "manual": { 41 | "menu_options": { 42 | "manual_add_device": "Add device", 43 | "remove_device": "Remove device", 44 | "finish": "Finish" 45 | }, 46 | "data": { 47 | "username": "User email", 48 | "password": "User password" 49 | } 50 | }, 51 | "manual_device_input": { 52 | "data": { 53 | "device_type": "Device type", 54 | "device_name": "Device name", 55 | "device_id": "Device SN" 56 | } 57 | } 58 | } 59 | }, 60 | "options": { 61 | "step": { 62 | "init": { 63 | "data": { 64 | "select_device": "Select device" 65 | } 66 | }, 67 | "options": { 68 | "data": { 69 | "power_step": "Charging power slider step", 70 | "refresh_period_sec": "Data refresh period (sec)", 71 | "diagnostic_mode": "Diagnostic mode" 72 | } 73 | } 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /custom_components/ecoflow_cloud/translations/de.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "EcoFlow-Cloud", 3 | "config": { 4 | "step": { 5 | "user": { 6 | "data": { 7 | "group": "Gerätegruppe" 8 | } 9 | }, 10 | "api": { 11 | "menu_options": { 12 | "api_add_device": "Gerät hinzufügen", 13 | "remove_device": "Gerät entfernen", 14 | "finish": "Abschließen" 15 | }, 16 | "data": { 17 | "access_key": "Zugriffsschlüssel", 18 | "secret_key": "Geheimschlüssel", 19 | "load_all_devices": "Automatisches Laden von Geräten" 20 | } 21 | }, 22 | "choose_type": { 23 | "menu_options": { 24 | "api": "Öffentliche API verwenden", 25 | "manual": "Anwendungs-API verwenden" 26 | } 27 | }, 28 | "select_device": { 29 | "data": { 30 | "select_device": "Gerät auswählen" 31 | } 32 | }, 33 | "confirm_cloud_device": { 34 | "data": { 35 | "device_type": "Gerätetyp", 36 | "device_name": "Gerätename", 37 | "device_id": "Gerät SN" 38 | } 39 | }, 40 | "manual": { 41 | "menu_options": { 42 | "manual_add_device": "Gerät hinzufügen", 43 | "remove_device": "Gerät entfernen", 44 | "finish": "Abschließen" 45 | }, 46 | "data": { 47 | "username": "Benutzer-E-Mail", 48 | "password": "Benutzerpasswort" 49 | } 50 | }, 51 | "manual_device_input": { 52 | "data": { 53 | "device_type": "Gerätetyp", 54 | "device_name": "Gerätename", 55 | "device_id": "Gerät SN" 56 | } 57 | } 58 | } 59 | }, 60 | "options": { 61 | "step": { 62 | "init": { 63 | "data": { 64 | "select_device": "Gerät auswählen" 65 | } 66 | }, 67 | "options": { 68 | "data": { 69 | "power_step": "Schieberegler-Schritt für Ladeleistung", 70 | "refresh_period_sec": "Datenaktualisierungsperiode (Sek.)", 71 | "diagnostic_mode": "Diagnosemodus" 72 | } 73 | } 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /custom_components/ecoflow_cloud/translations/uk_UA.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "EcoFlow-Cloud", 3 | "config": { 4 | "step": { 5 | "user": { 6 | "data": { 7 | "group": "Група пристроїв" 8 | } 9 | }, 10 | "api": { 11 | "menu_options": { 12 | "api_add_device": "Додати пристрій", 13 | "remove_device": "Видалити пристрій", 14 | "finish": "Завершити" 15 | }, 16 | "data": { 17 | "access_key": "Access key", 18 | "secret_key": "Secret key", 19 | "load_all_devices": "Автоматичне завантаження пристроїв" 20 | } 21 | }, 22 | "choose_type": { 23 | "menu_options": { 24 | "api": "Використовувати public API", 25 | "manual": "Використовувати application API" 26 | } 27 | }, 28 | "select_device": { 29 | "data": { 30 | "select_device": "Вибрати пристрій" 31 | } 32 | }, 33 | "confirm_cloud_device": { 34 | "data": { 35 | "device_type": "Тип пристрою", 36 | "device_name": "Назва пристрою", 37 | "device_id": "SN пристрою" 38 | } 39 | }, 40 | "manual": { 41 | "menu_options": { 42 | "manual_add_device": "Додати пристрій", 43 | "remove_device": "Видалити пристрій", 44 | "finish": "Завершити" 45 | }, 46 | "data": { 47 | "username": "Email користувача", 48 | "password": "Password користувача" 49 | } 50 | }, 51 | "manual_device_input": { 52 | "data": { 53 | "device_type": "Тип пристрою", 54 | "device_name": "Назва пристрою", 55 | "device_id": "SN пристрою" 56 | } 57 | } 58 | } 59 | }, 60 | "options": { 61 | "step": { 62 | "init": { 63 | "data": { 64 | "select_device": "Вибрати пристрій" 65 | } 66 | }, 67 | "options": { 68 | "data": { 69 | "power_step": "Крок регулятора потужності заряджання", 70 | "refresh_period_sec": "Період оновлення даних (сек)", 71 | "diagnostic_mode": "Діагностичний режим" 72 | } 73 | } 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /custom_components/ecoflow_cloud/translations/pl.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "EcoFlow-Cloud", 3 | "config": { 4 | "step": { 5 | "user": { 6 | "data": { 7 | "group": "Grupa urządzeń" 8 | } 9 | }, 10 | "api": { 11 | "menu_options": { 12 | "api_add_device": "Dodaj urządzenie", 13 | "remove_device": "Usuń urządzenie", 14 | "finish": "Zakończ" 15 | }, 16 | "data": { 17 | "access_key": "Klucz dostępu", 18 | "secret_key": "Klucz tajny", 19 | "load_all_devices": "Automatyczne ładowanie urządzeń" 20 | } 21 | }, 22 | "choose_type": { 23 | "menu_options": { 24 | "api": "Użyj publicznego API", 25 | "manual": "Użyj API aplikacji" 26 | } 27 | }, 28 | "select_device": { 29 | "data": { 30 | "select_device": "Wybierz urządzenie" 31 | } 32 | }, 33 | "confirm_cloud_device": { 34 | "data": { 35 | "device_type": "Typ urządzenia", 36 | "device_name": "Nazwa urządzenia", 37 | "device_id": "Numer seryjny urządzenia (SN)" 38 | } 39 | }, 40 | "manual": { 41 | "menu_options": { 42 | "manual_add_device": "Dodaj urządzenie", 43 | "remove_device": "Usuń urządzenie", 44 | "finish": "Zakończ" 45 | }, 46 | "data": { 47 | "username": "Adres e-mail użytkownika", 48 | "password": "Hasło użytkownika" 49 | } 50 | }, 51 | "manual_device_input": { 52 | "data": { 53 | "device_type": "Typ urządzenia", 54 | "device_name": "Nazwa urządzenia", 55 | "device_id": "Numer seryjny urządzenia (SN)" 56 | } 57 | } 58 | } 59 | }, 60 | "options": { 61 | "step": { 62 | "init": { 63 | "data": { 64 | "select_device": "Wybierz urządzenie" 65 | } 66 | }, 67 | "options": { 68 | "data": { 69 | "power_step": "Krok suwaka mocy ładowania", 70 | "refresh_period_sec": "Okres odświeżania danych (sek)", 71 | "diagnostic_mode": "Tryb diagnostyczny" 72 | } 73 | } 74 | } 75 | } 76 | } -------------------------------------------------------------------------------- /docs/devices/WAVE_2.md: -------------------------------------------------------------------------------- 1 | ## WAVE_2 2 | 3 | *Sensors* 4 | - Main Battery Level (`bms.soc`) 5 | - Main Remain Capacity (`bms.remainCap`) _(disabled)_ 6 | - Battery Temperature (`bms.tmp`) 7 | - Min Cell Temperature (`bms.minCellTmp`) _(disabled)_ 8 | - Max Cell Temperature (`bms.maxCellTmp`) _(disabled)_ 9 | - Charge Remaining Time (`pd.batChgRemain`) 10 | - Discharge Remaining Time (`pd.batDsgRemain`) 11 | - Condensation temperature (`pd.condTemp`) _(disabled)_ 12 | - Return air temperature in condensation zone (`pd.heatEnv`) _(disabled)_ 13 | - Air outlet temperature (`pd.coolEnv`) _(disabled)_ 14 | - Evaporation temperature (`pd.evapTemp`) _(disabled)_ 15 | - Exhaust temperature (`pd.motorOutTemp`) _(disabled)_ 16 | - Evaporation zone return air temperature (`pd.airInTemp`) _(disabled)_ 17 | - Air outlet temperature (`pd.coolTemp`) _(disabled)_ 18 | - Ambient temperature (`pd.envTemp`) _(disabled)_ 19 | - PV input power (`pd.mpptPwr`) 20 | - Battery output power (`pd.batPwrOut`) 21 | - PV charging power (`pd.pvPower`) 22 | - AC input power (`pd.acPwrIn`) 23 | - Power supply power (`pd.psdrPower `) 24 | - System power (`pd.sysPowerWatts`) 25 | - Battery power (`pd.batPower `) 26 | - Motor operating power (`motor.power`) 27 | - Battery output power (`power.batPwrOut`) 28 | - AC input power (`power.acPwrI`) 29 | - PV input power (`power.mpptPwr `) 30 | - Status 31 | 32 | *Switches* 33 | 34 | *Sliders (numbers)* 35 | - Set Temperature (`pd.setTemp` -> `{"moduleType": 1, "operateType": "setTemp", "sn": "SN", "params": {"setTemp": "VALUE"}}` [0 - 40]) 36 | 37 | *Selects* 38 | - Wind speed (`pd.fanValue` -> `{"moduleType": 1, "operateType": "fanValue", "sn": "SN", "params": {"fanValue": "VALUE"}}` [Low (0), Medium (1), High (2)]) 39 | - Main mode (`pd.mainMode` -> `{"moduleType": 1, "operateType": "mainMode", "sn": "SN", "params": {"mainMode": "VALUE"}}` [Cool (0), Heat (1), Fan (2)]) 40 | - Remote startup/shutdown (`pd.powerMode` -> `{"moduleType": 1, "operateType": "powerMode", "sn": "SN", "params": {"powerMode": "VALUE"}}` [Startup (1), Standby (2), Shutdown (3)]) 41 | - Sub-mode (`pd.subMode` -> `{"moduleType": 1, "operateType": "subMode", "sn": "SN", "params": {"subMode": "VALUE"}}` [Max (0), Sleep (1), Eco (2), Manual (3)]) 42 | 43 | 44 | -------------------------------------------------------------------------------- /docs/devices/WAVE_2-Public.md: -------------------------------------------------------------------------------- 1 | ## WAVE_2 2 | 3 | *Sensors* 4 | - Main Battery Level (`bms.soc`) 5 | - Main Remain Capacity (`bms.remainCap`) _(disabled)_ 6 | - Battery Temperature (`bms.tmp`) 7 | - Min Cell Temperature (`bms.minCellTmp`) _(disabled)_ 8 | - Max Cell Temperature (`bms.maxCellTmp`) _(disabled)_ 9 | - Charge Remaining Time (`pd.batChgRemain`) 10 | - Discharge Remaining Time (`pd.batDsgRemain`) 11 | - Condensation temperature (`pd.condTemp`) _(disabled)_ 12 | - Return air temperature in condensation zone (`pd.heatEnv`) _(disabled)_ 13 | - Air outlet temperature (`pd.coolEnv`) _(disabled)_ 14 | - Evaporation temperature (`pd.evapTemp`) _(disabled)_ 15 | - Exhaust temperature (`pd.motorOutTemp`) _(disabled)_ 16 | - Evaporation zone return air temperature (`pd.airInTemp`) _(disabled)_ 17 | - Air outlet temperature (`pd.coolTemp`) _(disabled)_ 18 | - Ambient temperature (`pd.envTemp`) _(disabled)_ 19 | - PV input power (`pd.mpptPwr`) 20 | - Battery output power (`pd.batPwrOut`) 21 | - PV charging power (`pd.pvPower`) 22 | - AC input power (`pd.acPwrIn`) 23 | - Power supply power (`pd.psdrPower `) 24 | - System power (`pd.sysPowerWatts`) 25 | - Battery power (`pd.batPower `) 26 | - Motor operating power (`motor.power`) 27 | - Battery output power (`power.batPwrOut`) 28 | - AC input power (`power.acPwrI`) 29 | - PV input power (`power.mpptPwr `) 30 | - Status 31 | 32 | *Switches* 33 | 34 | *Sliders (numbers)* 35 | - Set Temperature (`pd.setTemp` -> `{"moduleType": 1, "operateType": "setTemp", "sn": "SN", "params": {"setTemp": "VALUE"}}` [0 - 40]) 36 | 37 | *Selects* 38 | - Wind speed (`pd.fanValue` -> `{"moduleType": 1, "operateType": "fanValue", "sn": "SN", "params": {"fanValue": "VALUE"}}` [Low (0), Medium (1), High (2)]) 39 | - Main mode (`pd.mainMode` -> `{"moduleType": 1, "operateType": "mainMode", "sn": "SN", "params": {"mainMode": "VALUE"}}` [Cool (0), Heat (1), Fan (2)]) 40 | - Remote startup/shutdown (`pd.powerMode` -> `{"moduleType": 1, "operateType": "powerMode", "sn": "SN", "params": {"powerMode": "VALUE"}}` [Startup (1), Standby (2), Shutdown (3)]) 41 | - Sub-mode (`pd.subMode` -> `{"moduleType": 1, "operateType": "subMode", "sn": "SN", "params": {"subMode": "VALUE"}}` [Max (0), Sleep (1), Eco (2), Manual (3)]) 42 | 43 | 44 | -------------------------------------------------------------------------------- /custom_components/ecoflow_cloud/translations/it.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "EcoFlow-Cloud", 3 | "config": { 4 | "step": { 5 | "user": { 6 | "data": { 7 | "group": "Gruppo di dispositivi" 8 | } 9 | }, 10 | "api": { 11 | "menu_options": { 12 | "api_add_device": "Aggiungi dispositivo", 13 | "remove_device": "Rimuovi dispositivo", 14 | "finish": "Fine" 15 | }, 16 | "data": { 17 | "access_key": "Access key", 18 | "secret_key": "Secret key", 19 | "load_all_devices": "Caricamento automatico dei dispositivi" 20 | } 21 | }, 22 | "choose_type": { 23 | "menu_options": { 24 | "api": "Usa API pubblica", 25 | "manual": "Usa API dell'applicazione" 26 | } 27 | }, 28 | "select_device": { 29 | "data": { 30 | "select_device": "Seleziona dispositivo" 31 | } 32 | }, 33 | "confirm_cloud_device": { 34 | "data": { 35 | "device_type": "Tipo di dispositivo", 36 | "device_name": "Nome del dispositivo", 37 | "device_id": "SN del dispositivo" 38 | } 39 | }, 40 | "manual": { 41 | "menu_options": { 42 | "manual_add_device": "Aggiungi dispositivo", 43 | "remove_device": "Rimuovi dispositivo", 44 | "finish": "Fine" 45 | }, 46 | "data": { 47 | "username": "Email utente", 48 | "password": "Password utente" 49 | } 50 | }, 51 | "manual_device_input": { 52 | "data": { 53 | "device_type": "Tipo di dispositivo", 54 | "device_name": "Nome del dispositivo", 55 | "device_id": "SN del dispositivo" 56 | } 57 | } 58 | } 59 | }, 60 | "options": { 61 | "step": { 62 | "init": { 63 | "data": { 64 | "select_device": "Seleziona dispositivo" 65 | } 66 | }, 67 | "options": { 68 | "data": { 69 | "power_step": "Passo dello slider della potenza di carica", 70 | "refresh_period_sec": "Periodo di aggiornamento dati (sec)", 71 | "diagnostic_mode": "Modalità diagnostica" 72 | } 73 | } 74 | } 75 | } 76 | } -------------------------------------------------------------------------------- /custom_components/ecoflow_cloud/translations/fr.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "EcoFlow-Cloud", 3 | "config": { 4 | "step": { 5 | "user": { 6 | "data": { 7 | "group": "Groupe d'appareils" 8 | } 9 | }, 10 | "api": { 11 | "menu_options": { 12 | "api_add_device": "Ajouter un appareil", 13 | "remove_device": "Supprimer un appareil", 14 | "finish": "Terminer" 15 | }, 16 | "data": { 17 | "access_key": "Clé d'accès", 18 | "secret_key": "Clé secrète", 19 | "load_all_devices": "Chargement automatique des appareils" 20 | } 21 | }, 22 | "choose_type": { 23 | "menu_options": { 24 | "api": "Utiliser l'API publique", 25 | "manual": "Utiliser l'API de l'application" 26 | } 27 | }, 28 | "select_device": { 29 | "data": { 30 | "select_device": "Sélectionner un appareil" 31 | } 32 | }, 33 | "confirm_cloud_device": { 34 | "data": { 35 | "device_type": "Type d'appareil", 36 | "device_name": "Nom de l'appareil", 37 | "device_id": "SN de l'appareil" 38 | } 39 | }, 40 | "manual": { 41 | "menu_options": { 42 | "manual_add_device": "Ajouter un appareil", 43 | "remove_device": "Supprimer un appareil", 44 | "finish": "Terminer" 45 | }, 46 | "data": { 47 | "username": "E-mail de l'utilisateur", 48 | "password": "Mot de passe de l'utilisateur" 49 | } 50 | }, 51 | "manual_device_input": { 52 | "data": { 53 | "device_type": "Type d'appareil", 54 | "device_name": "Nom de l'appareil", 55 | "device_id": "SN de l'appareil" 56 | } 57 | } 58 | } 59 | }, 60 | "options": { 61 | "step": { 62 | "init": { 63 | "data": { 64 | "select_device": "Sélectionner un appareil" 65 | } 66 | }, 67 | "options": { 68 | "data": { 69 | "power_step": "Pas du curseur de puissance de charge", 70 | "refresh_period_sec": "Période de rafraîchissement des données (sec)", 71 | "diagnostic_mode": "Mode diagnostic" 72 | } 73 | } 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /custom_components/ecoflow_cloud/translations/pt-PT.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "EcoFlow-Cloud", 3 | "config": { 4 | "step": { 5 | "user": { 6 | "data": { 7 | "group": "Grupo de dispositivos" 8 | } 9 | }, 10 | "api": { 11 | "menu_options": { 12 | "api_add_device": "Adicionar dispositivo", 13 | "remove_device": "Remover dispositivo", 14 | "finish": "Concluir" 15 | }, 16 | "data": { 17 | "access_key": "Chave de acesso", 18 | "secret_key": "Chave secreta", 19 | "load_all_devices": "Carregamento automático de dispositivos" 20 | } 21 | }, 22 | "choose_type": { 23 | "menu_options": { 24 | "api": "Usar API pública", 25 | "manual": "Usar API do aplicativo" 26 | } 27 | }, 28 | "select_device": { 29 | "data": { 30 | "select_device": "Selecionar dispositivo" 31 | } 32 | }, 33 | "confirm_cloud_device": { 34 | "data": { 35 | "device_type": "Tipo de dispositivo", 36 | "device_name": "Nome do dispositivo", 37 | "device_id": "SN do dispositivo" 38 | } 39 | }, 40 | "manual": { 41 | "menu_options": { 42 | "manual_add_device": "Adicionar dispositivo", 43 | "remove_device": "Remover dispositivo", 44 | "finish": "Concluir" 45 | }, 46 | "data": { 47 | "username": "E-mail do usuário", 48 | "password": "Senha do usuário" 49 | } 50 | }, 51 | "manual_device_input": { 52 | "data": { 53 | "device_type": "Tipo de dispositivo", 54 | "device_name": "Nome do dispositivo", 55 | "device_id": "SN do dispositivo" 56 | } 57 | } 58 | } 59 | }, 60 | "options": { 61 | "step": { 62 | "init": { 63 | "data": { 64 | "select_device": "Selecionar dispositivo" 65 | } 66 | }, 67 | "options": { 68 | "data": { 69 | "power_step": "Incremento do controle deslizante de potência de carga", 70 | "refresh_period_sec": "Período de atualização de dados (seg.)", 71 | "diagnostic_mode": "Modo de diagnóstico" 72 | } 73 | } 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /docs/devices/GLACIER.md: -------------------------------------------------------------------------------- 1 | ## GLACIER 2 | 3 | *Sensors* 4 | - Main Battery Level (`bms_bmsStatus.soc`) 5 | - Main Design Capacity (`bms_bmsStatus.designCap`) _(disabled)_ 6 | - Main Full Capacity (`bms_bmsStatus.fullCap`) _(disabled)_ 7 | - Main Remain Capacity (`bms_bmsStatus.remainCap`) _(disabled)_ 8 | - Battery Level (`bms_emsStatus.f32LcdSoc`) 9 | - Battery Charging State (`bms_emsStatus.chgState`) 10 | - Total In Power (`bms_bmsStatus.inWatts`) 11 | - Total Out Power (`bms_bmsStatus.outWatts`) 12 | - Motor Power (`pd.motorWat`) 13 | - Charge Remaining Time (`bms_emsStatus.chgRemain`) 14 | - Discharge Remaining Time (`bms_emsStatus.dsgRemain`) 15 | - Cycles (`bms_bmsStatus.cycles`) 16 | - Battery Temperature (`bms_bmsStatus.tmp`) 17 | - Min Cell Temperature (`bms_bmsStatus.minCellTmp`) _(disabled)_ 18 | - Max Cell Temperature (`bms_bmsStatus.maxCellTmp`) _(disabled)_ 19 | - Battery Volts (`bms_bmsStatus.vol`) _(disabled)_ 20 | - Min Cell Volts (`bms_bmsStatus.minCellVol`) _(disabled)_ 21 | - Max Cell Volts (`bms_bmsStatus.maxCellVol`) _(disabled)_ 22 | - Battery Present (`pd.batFlag`) 23 | - XT60 State (`pd.xt60InState`) 24 | - Fan Level (`bms_emsStatus.fanLvl`) 25 | - Ambient Temperature (`pd.ambientTmp`) 26 | - Exhaust Temperature (`pd.exhaustTmp`) 27 | - Water Temperature (`pd.tempWater`) 28 | - Left Temperature (`pd.tmpL`) 29 | - Right Temperature (`pd.tmpR`) 30 | - Dual Zone Mode (`pd.flagTwoZone`) 31 | - Ice Time Remain (`pd.iceTm`) 32 | - Ice Percentage (`pd.icePercent`) 33 | - Ice Make Mode (`pd.iceMkMode`) 34 | - Ice Alert (`pd.iceAlert`) 35 | - Ice Water Level OK (`pd.waterLine`) 36 | - Status 37 | 38 | *Switches* 39 | - Beeper (`pd.beepEn` -> `{"moduleType": 1, "operateType": "beepEn", "params": {"flag": "VALUE"}}`) 40 | - Eco Mode (`pd.coolMode` -> `{"moduleType": 1, "operateType": "ecoMode", "params": {"mode": "VALUE"}}`) 41 | - Power (`pd.pwrState` -> `{"moduleType": 1, "operateType": "powerOff", "params": {"enable": "VALUE"}}`) 42 | 43 | *Sliders (numbers)* 44 | - Left Set Temperature (`pd.tmpLSet` -> `{"moduleType": 1, "operateType": "temp", "params": {"tmpM": 0, "tmpL": "VALUE", "tmpR": 0}}` [-25 - 10]) 45 | - Combined Set Temperature (`pd.tmpMSet` -> `{"moduleType": 1, "operateType": "temp", "params": {"tmpM": "VALUE", "tmpL": 0, "tmpR": 0}}` [-25 - 10]) 46 | - Right Set Temperature (`pd.tmpRSet` -> `{"moduleType": 1, "operateType": "temp", "params": {"tmpM": 0, "tmpL": 0, "tmpR": "VALUE"}}` [-25 - 10]) 47 | 48 | *Selects* 49 | 50 | 51 | -------------------------------------------------------------------------------- /custom_components/ecoflow_cloud/devices/public/stream_microinverter.py: -------------------------------------------------------------------------------- 1 | from ...api import EcoflowApiClient 2 | from ...entities import ( 3 | BaseNumberEntity, 4 | BaseSelectEntity, 5 | BaseSensorEntity, 6 | BaseSwitchEntity, 7 | ) 8 | from ...sensor import ( 9 | StatusSensorEntity, 10 | InAmpSensorEntity, 11 | WattsSensorEntity, 12 | VoltSensorEntity, 13 | CelsiusSensorEntity, 14 | FrequencySensorEntity, 15 | ) 16 | from .. import BaseDevice, const 17 | from .data_bridge import to_plain 18 | 19 | 20 | class StreamMicroinveter(BaseDevice): 21 | 22 | def sensors(self, client: EcoflowApiClient) -> list[BaseSensorEntity]: 23 | return [ 24 | WattsSensorEntity(client, self, "gridConnectionPower", const.STREAM_POWER_AC), 25 | WattsSensorEntity(client, self, "powGetPv", const.STREAM_POWER_PV_1, False, True), 26 | WattsSensorEntity(client, self, "powGetPv2", const.STREAM_POWER_PV_2, False, True), 27 | 28 | VoltSensorEntity(client, self, "gridConnectionVol", const.STREAM_POWER_VOL, False), 29 | VoltSensorEntity(client, self, "plugInInfoPvVol", const.STREAM_IN_VOL_PV_1, False, True), 30 | VoltSensorEntity(client, self, "plugInInfoPv2Vol", const.STREAM_IN_VOL_PV_2, False, True), 31 | 32 | InAmpSensorEntity(client, self, "gridConnectionAmp", const.STREAM_POWER_AMP, False), 33 | InAmpSensorEntity(client, self, "plugInInfoPvAmp", const.STREAM_IN_AMPS_PV_1, False, True), 34 | InAmpSensorEntity(client, self, "plugInInfoPv2Amp", const.STREAM_IN_AMPS_PV_2, False, True), 35 | 36 | CelsiusSensorEntity(client, self, "invNtcTemp3", "Inverter NTC Temperature"), 37 | FrequencySensorEntity(client, self, "gridConnectionFreq", "Grid Frequency"), 38 | StatusSensorEntity(client, self) 39 | ] 40 | 41 | 42 | def numbers(self, client: EcoflowApiClient) -> list[BaseNumberEntity]: 43 | return [] 44 | 45 | def switches(self, client: EcoflowApiClient) -> list[BaseSwitchEntity]: 46 | return [] 47 | 48 | def selects(self, client: EcoflowApiClient) -> list[BaseSelectEntity]: 49 | return [] 50 | 51 | def _prepare_data(self, raw_data) -> dict[str, any]: 52 | res = super()._prepare_data(raw_data) 53 | res = to_plain(res) 54 | return res 55 | 56 | def _status_sensor(self, client: EcoflowApiClient) -> StatusSensorEntity: 57 | return StatusSensorEntity(client, self) 58 | 59 | 60 | -------------------------------------------------------------------------------- /custom_components/ecoflow_cloud/devices/public/smart_plug.py: -------------------------------------------------------------------------------- 1 | from homeassistant.components.number import NumberEntity 2 | from homeassistant.components.select import SelectEntity 3 | from homeassistant.components.sensor import SensorEntity 4 | from homeassistant.components.switch import SwitchEntity 5 | 6 | from ...api import EcoflowApiClient 7 | from ...number import BrightnessLevelEntity 8 | from ...sensor import ( 9 | MilliampSensorEntity, 10 | DeciwattsSensorEntity, 11 | TempSensorEntity, 12 | VoltSensorEntity, 13 | ) 14 | from ...switch import EnabledEntity 15 | from .. import BaseDevice, const 16 | from .data_bridge import to_plain 17 | 18 | 19 | class SmartPlug(BaseDevice): 20 | def sensors(self, client: EcoflowApiClient) -> list[SensorEntity]: 21 | return [ 22 | TempSensorEntity(client, self, "2_1.temp", const.TEMPERATURE), 23 | VoltSensorEntity(client, self, "2_1.volt", const.VOLT), 24 | MilliampSensorEntity(client, self, "2_1.current", const.CURRENT).attr( 25 | "2_1.maxCur", const.MAX_CURRENT, 0 26 | ), 27 | DeciwattsSensorEntity(client, self, "2_1.watts", const.POWER), 28 | ] 29 | 30 | def numbers(self, client: EcoflowApiClient) -> list[NumberEntity]: 31 | return [ 32 | BrightnessLevelEntity( 33 | client, 34 | self, 35 | "2_1.brightness", 36 | const.BRIGHTNESS, 37 | 0, 38 | 1023, 39 | lambda value: { 40 | "sn": self.device_info.sn, 41 | "cmdCode": "WN511_SOCKET_SET_BRIGHTNESS_PACK", 42 | "params": {"brightness": value}, 43 | }, 44 | ), 45 | ] 46 | 47 | def switches(self, client: EcoflowApiClient) -> list[SwitchEntity]: 48 | return [ 49 | EnabledEntity( 50 | client, 51 | self, 52 | "2_1.switchSta", 53 | const.MODE_ON, 54 | lambda value: { 55 | "sn": self.device_info.sn, 56 | "cmdCode": "WN511_SOCKET_SET_PLUG_SWITCH_MESSAGE", 57 | "params": {"plugSwitch": value}, 58 | }, 59 | ), 60 | ] 61 | 62 | def selects(self, client: EcoflowApiClient) -> list[SelectEntity]: 63 | return [] 64 | 65 | def _prepare_data(self, raw_data) -> dict[str, any]: 66 | res = super()._prepare_data(raw_data) 67 | res = to_plain(res) 68 | 69 | return res 70 | -------------------------------------------------------------------------------- /custom_components/ecoflow_cloud/select.py: -------------------------------------------------------------------------------- 1 | from typing import Any, Callable 2 | 3 | from homeassistant.config_entries import ConfigEntry 4 | from homeassistant.core import HomeAssistant 5 | from homeassistant.helpers.entity import EntityCategory 6 | from homeassistant.helpers.entity_platform import AddEntitiesCallback 7 | 8 | from . import ECOFLOW_DOMAIN 9 | from .api import EcoflowApiClient, Message 10 | from .devices import BaseDevice 11 | from .entities import BaseSelectEntity 12 | 13 | 14 | async def async_setup_entry( 15 | hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback 16 | ): 17 | client: EcoflowApiClient = hass.data[ECOFLOW_DOMAIN][entry.entry_id] 18 | for sn, device in client.devices.items(): 19 | async_add_entities(device.selects(client)) 20 | 21 | 22 | class DictSelectEntity(BaseSelectEntity[int]): 23 | _attr_entity_category = EntityCategory.CONFIG 24 | _attr_available = False 25 | 26 | def __init__( 27 | self, 28 | client: EcoflowApiClient, 29 | device: BaseDevice, 30 | mqtt_key: str, 31 | title: str, 32 | options: dict[str, Any], 33 | command: Callable[[int], dict[str, Any] | Message] 34 | | Callable[[int, dict[str, Any]], dict[str, Any] | Message] 35 | | None, 36 | enabled: bool = True, 37 | auto_enable: bool = False, 38 | ): 39 | super().__init__(client, device, mqtt_key, title, command, enabled, auto_enable) 40 | self._options_dict = options 41 | self._options = list(options.keys()) 42 | self._current_option = None 43 | 44 | def options_dict(self) -> dict[str, int]: 45 | return self._options_dict 46 | 47 | def _update_value(self, val: Any) -> bool: 48 | lval = [k for k, v in self._options_dict.items() if v == val] 49 | if len(lval) == 1: 50 | self._current_option = lval[0] 51 | return True 52 | else: 53 | return False 54 | 55 | @property 56 | def options(self) -> list[str]: 57 | """Return available select options.""" 58 | return self._options 59 | 60 | @property 61 | def current_option(self) -> str: 62 | """Return current select option.""" 63 | return self._current_option 64 | 65 | def select_option(self, option: str) -> None: 66 | if self._command: 67 | val = self._options_dict[option] 68 | self.send_set_message(val, self.command_dict(val)) 69 | 70 | 71 | class TimeoutDictSelectEntity(DictSelectEntity): 72 | _attr_icon = "mdi:timer-outline" 73 | 74 | 75 | class PowerDictSelectEntity(DictSelectEntity): 76 | _attr_icon = "mdi:battery-charging-wireless" 77 | -------------------------------------------------------------------------------- /docs/devices/Stream_AC-Public.md: -------------------------------------------------------------------------------- 1 | ## Stream_AC 2 | 3 | *Sensors* 4 | - Cumulative Capacity Charge (mAh) (`accuChgCap`) _(disabled)_ 5 | - Cumulative Energy Charge (Wh) (`accuChgEnergy`) 6 | - Cumulative Capacity Discharge (mAh) (`accuDsgCap`) _(disabled)_ 7 | - Cumulative Energy Discharge (Wh) (`accuDsgEnergy`) 8 | - Charge Remaining Time (`bmsChgRemTime`) _(disabled)_ 9 | - Discharge Remaining Time (`bmsDsgRemTime`) _(disabled)_ 10 | - Max Charge Level (`cmsMaxChgSoc`) 11 | - Min Discharge Level (`cmsMinDsgSoc`) 12 | - Cycles (`cycles`) 13 | - Design Capacity (`designCap`) _(disabled)_ 14 | - Power Battery SOC (`f32ShowSoc`) 15 | - Full Capacity (`fullCap`) _(disabled)_ 16 | - Power AC (`gridConnectionPower`) 17 | - Power Volts (`gridConnectionVol`) _(disabled)_ 18 | - In Power (`inputWatts`) 19 | - Max Cell Temperature (`maxCellTemp`) _(disabled)_ 20 | - Max Cell Volts (`maxCellVol`) _(disabled)_ 21 | - Min Cell Temperature (`minCellTemp`) _(disabled)_ 22 | - Min Cell Volts (`minCellVol`) _(disabled)_ 23 | - Out Power (`outputWatts`) 24 | - Power Battery (`powGetBpCms`) 25 | - Power PV 1 (`powGetPv`) _(auto)_ 26 | - Power PV 2 (`powGetPv2`) _(auto)_ 27 | - Power PV 3 (`powGetPv3`) _(auto)_ 28 | - Power PV 4 (`powGetPv4`) _(auto)_ 29 | - Power PV Sum (`powGetPvSum`) 30 | - Power SCHUKO1 (`powGetSchuko1`) _(auto)_ 31 | - Power SCHUKO2 (`powGetSchuko2`) _(auto)_ 32 | - Power Grid (`powGetSysGrid`) 33 | - Power Sys Load (`powGetSysLoad`) 34 | - Power Sys Load From Battery (`powGetSysLoadFromBp`) 35 | - Power Sys Load From Grid (`powGetSysLoadFromGrid`) 36 | - Power Sys Load From PV (`powGetSysLoadFromPv`) 37 | - Real State of Health (`realSoh`) _(disabled)_ 38 | - Remain Capacity (`remainCap`) _(disabled)_ 39 | - Remaining Time (`remainTime`) 40 | - Power Battery (`soc`) 41 | - State of Health (`soh`) 42 | - Power AC SYS (`sysGridConnectionPower`) 43 | - Battery Temperature (`temp`) 44 | - Battery Volts (`vol`) _(disabled)_ 45 | 46 | *Switches* 47 | - AC 1 On (`relay2Onoff` -> `{"sn": "SN", "cmdId": 17, "cmdFunc": 254, "dirDest": 1, "dirSrc": 1, "dest": 2, "needAck": true, "params": {"cfgRelay2Onoff": "VALUE"}}`) 48 | - AC 2 On (`relay3Onoff` -> `{"sn": "SN", "cmdId": 17, "cmdFunc": 254, "dirDest": 1, "dirSrc": 1, "dest": 2, "needAck": true, "params": {"cfgRelay3Onoff": "VALUE"}}`) 49 | - Operating mode - Self-powered (`energyStrategyOperateMode.operateSelfPoweredOpen` -> `{"sn": "SN", "cmdId": 17, "cmdFunc": 254, "dirDest": 1, "dirSrc": 1, "dest": 2, "needAck": true, "params": {"cfgEnergyStrategyOperateMode": {"operateSelfPoweredOpen": 6666}}}`) 50 | - Operating mode - AI Mode (`energyStrategyOperateMode.operateIntelligentScheduleModeOpen` -> `{"sn": "SN", "cmdId": 17, "cmdFunc": 254, "dirDest": 1, "dirSrc": 1, "dest": 2, "needAck": true, "params": {"cfgEnergyStrategyOperateMode": {"operateIntelligentScheduleModeOpen": 6666}}}`) 51 | - Feed-in control (`feedGridMode` -> `{"sn": "SN", "cmdId": 17, "cmdFunc": 254, "dirDest": 1, "dirSrc": 1, "dest": 2, "needAck": true, "params": {"cfgFeedGridMode": "VALUE"}}`) 52 | 53 | *Sliders (numbers)* 54 | - Backup Reserve Level (`backupReverseSoc` -> `{"sn": "SN", "cmdId": 17, "cmdFunc": 254, "dirDest": 1, "dirSrc": 1, "dest": 2, "needAck": true, "params": {"cfgBackupReverseSoc": "VALUE"}}` [3 - 95]) 55 | 56 | *Selects* 57 | 58 | 59 | -------------------------------------------------------------------------------- /docs/devices/Stream_PRO-Public.md: -------------------------------------------------------------------------------- 1 | ## Stream_PRO 2 | 3 | *Sensors* 4 | - Cumulative Capacity Charge (mAh) (`accuChgCap`) _(disabled)_ 5 | - Cumulative Energy Charge (Wh) (`accuChgEnergy`) 6 | - Cumulative Capacity Discharge (mAh) (`accuDsgCap`) _(disabled)_ 7 | - Cumulative Energy Discharge (Wh) (`accuDsgEnergy`) 8 | - Charge Remaining Time (`bmsChgRemTime`) _(disabled)_ 9 | - Discharge Remaining Time (`bmsDsgRemTime`) _(disabled)_ 10 | - Max Charge Level (`cmsMaxChgSoc`) 11 | - Min Discharge Level (`cmsMinDsgSoc`) 12 | - Cycles (`cycles`) 13 | - Design Capacity (`designCap`) _(disabled)_ 14 | - Power Battery SOC (`f32ShowSoc`) 15 | - Full Capacity (`fullCap`) _(disabled)_ 16 | - Power AC (`gridConnectionPower`) 17 | - Power Volts (`gridConnectionVol`) _(disabled)_ 18 | - In Power (`inputWatts`) 19 | - Max Cell Temperature (`maxCellTemp`) _(disabled)_ 20 | - Max Cell Volts (`maxCellVol`) _(disabled)_ 21 | - Min Cell Temperature (`minCellTemp`) _(disabled)_ 22 | - Min Cell Volts (`minCellVol`) _(disabled)_ 23 | - Out Power (`outputWatts`) 24 | - Power Battery (`powGetBpCms`) 25 | - Power PV 1 (`powGetPv`) _(auto)_ 26 | - Power PV 2 (`powGetPv2`) _(auto)_ 27 | - Power PV 3 (`powGetPv3`) _(auto)_ 28 | - Power PV 4 (`powGetPv4`) _(auto)_ 29 | - Power PV Sum (`powGetPvSum`) 30 | - Power SCHUKO1 (`powGetSchuko1`) _(auto)_ 31 | - Power SCHUKO2 (`powGetSchuko2`) _(auto)_ 32 | - Power Grid (`powGetSysGrid`) 33 | - Power Sys Load (`powGetSysLoad`) 34 | - Power Sys Load From Battery (`powGetSysLoadFromBp`) 35 | - Power Sys Load From Grid (`powGetSysLoadFromGrid`) 36 | - Power Sys Load From PV (`powGetSysLoadFromPv`) 37 | - Real State of Health (`realSoh`) _(disabled)_ 38 | - Remain Capacity (`remainCap`) _(disabled)_ 39 | - Remaining Time (`remainTime`) 40 | - Power Battery (`soc`) 41 | - State of Health (`soh`) 42 | - Power AC SYS (`sysGridConnectionPower`) 43 | - Battery Temperature (`temp`) 44 | - Battery Volts (`vol`) _(disabled)_ 45 | 46 | *Switches* 47 | - AC 1 On (`relay2Onoff` -> `{"sn": "SN", "cmdId": 17, "cmdFunc": 254, "dirDest": 1, "dirSrc": 1, "dest": 2, "needAck": true, "params": {"cfgRelay2Onoff": "VALUE"}}`) 48 | - AC 2 On (`relay3Onoff` -> `{"sn": "SN", "cmdId": 17, "cmdFunc": 254, "dirDest": 1, "dirSrc": 1, "dest": 2, "needAck": true, "params": {"cfgRelay3Onoff": "VALUE"}}`) 49 | - Operating mode - Self-powered (`energyStrategyOperateMode.operateSelfPoweredOpen` -> `{"sn": "SN", "cmdId": 17, "cmdFunc": 254, "dirDest": 1, "dirSrc": 1, "dest": 2, "needAck": true, "params": {"cfgEnergyStrategyOperateMode": {"operateSelfPoweredOpen": 6666}}}`) 50 | - Operating mode - AI Mode (`energyStrategyOperateMode.operateIntelligentScheduleModeOpen` -> `{"sn": "SN", "cmdId": 17, "cmdFunc": 254, "dirDest": 1, "dirSrc": 1, "dest": 2, "needAck": true, "params": {"cfgEnergyStrategyOperateMode": {"operateIntelligentScheduleModeOpen": 6666}}}`) 51 | - Feed-in control (`feedGridMode` -> `{"sn": "SN", "cmdId": 17, "cmdFunc": 254, "dirDest": 1, "dirSrc": 1, "dest": 2, "needAck": true, "params": {"cfgFeedGridMode": "VALUE"}}`) 52 | 53 | *Sliders (numbers)* 54 | - Backup Reserve Level (`backupReverseSoc` -> `{"sn": "SN", "cmdId": 17, "cmdFunc": 254, "dirDest": 1, "dirSrc": 1, "dest": 2, "needAck": true, "params": {"cfgBackupReverseSoc": "VALUE"}}` [3 - 95]) 55 | 56 | *Selects* 57 | 58 | 59 | -------------------------------------------------------------------------------- /docs/devices/Stream_Ultra-Public.md: -------------------------------------------------------------------------------- 1 | ## Stream_Ultra 2 | 3 | *Sensors* 4 | - Cumulative Capacity Charge (mAh) (`accuChgCap`) _(disabled)_ 5 | - Cumulative Energy Charge (Wh) (`accuChgEnergy`) 6 | - Cumulative Capacity Discharge (mAh) (`accuDsgCap`) _(disabled)_ 7 | - Cumulative Energy Discharge (Wh) (`accuDsgEnergy`) 8 | - Charge Remaining Time (`bmsChgRemTime`) _(disabled)_ 9 | - Discharge Remaining Time (`bmsDsgRemTime`) _(disabled)_ 10 | - Max Charge Level (`cmsMaxChgSoc`) 11 | - Min Discharge Level (`cmsMinDsgSoc`) 12 | - Cycles (`cycles`) 13 | - Design Capacity (`designCap`) _(disabled)_ 14 | - Power Battery SOC (`f32ShowSoc`) 15 | - Full Capacity (`fullCap`) _(disabled)_ 16 | - Power AC (`gridConnectionPower`) 17 | - Power Volts (`gridConnectionVol`) _(disabled)_ 18 | - In Power (`inputWatts`) 19 | - Max Cell Temperature (`maxCellTemp`) _(disabled)_ 20 | - Max Cell Volts (`maxCellVol`) _(disabled)_ 21 | - Min Cell Temperature (`minCellTemp`) _(disabled)_ 22 | - Min Cell Volts (`minCellVol`) _(disabled)_ 23 | - Out Power (`outputWatts`) 24 | - Power Battery (`powGetBpCms`) 25 | - Power PV 1 (`powGetPv`) _(auto)_ 26 | - Power PV 2 (`powGetPv2`) _(auto)_ 27 | - Power PV 3 (`powGetPv3`) _(auto)_ 28 | - Power PV 4 (`powGetPv4`) _(auto)_ 29 | - Power PV Sum (`powGetPvSum`) 30 | - Power SCHUKO1 (`powGetSchuko1`) _(auto)_ 31 | - Power SCHUKO2 (`powGetSchuko2`) _(auto)_ 32 | - Power Grid (`powGetSysGrid`) 33 | - Power Sys Load (`powGetSysLoad`) 34 | - Power Sys Load From Battery (`powGetSysLoadFromBp`) 35 | - Power Sys Load From Grid (`powGetSysLoadFromGrid`) 36 | - Power Sys Load From PV (`powGetSysLoadFromPv`) 37 | - Real State of Health (`realSoh`) _(disabled)_ 38 | - Remain Capacity (`remainCap`) _(disabled)_ 39 | - Remaining Time (`remainTime`) 40 | - Power Battery (`soc`) 41 | - State of Health (`soh`) 42 | - Power AC SYS (`sysGridConnectionPower`) 43 | - Battery Temperature (`temp`) 44 | - Battery Volts (`vol`) _(disabled)_ 45 | 46 | *Switches* 47 | - AC 1 On (`relay2Onoff` -> `{"sn": "SN", "cmdId": 17, "cmdFunc": 254, "dirDest": 1, "dirSrc": 1, "dest": 2, "needAck": true, "params": {"cfgRelay2Onoff": "VALUE"}}`) 48 | - AC 2 On (`relay3Onoff` -> `{"sn": "SN", "cmdId": 17, "cmdFunc": 254, "dirDest": 1, "dirSrc": 1, "dest": 2, "needAck": true, "params": {"cfgRelay3Onoff": "VALUE"}}`) 49 | - Operating mode - Self-powered (`energyStrategyOperateMode.operateSelfPoweredOpen` -> `{"sn": "SN", "cmdId": 17, "cmdFunc": 254, "dirDest": 1, "dirSrc": 1, "dest": 2, "needAck": true, "params": {"cfgEnergyStrategyOperateMode": {"operateSelfPoweredOpen": 6666}}}`) 50 | - Operating mode - AI Mode (`energyStrategyOperateMode.operateIntelligentScheduleModeOpen` -> `{"sn": "SN", "cmdId": 17, "cmdFunc": 254, "dirDest": 1, "dirSrc": 1, "dest": 2, "needAck": true, "params": {"cfgEnergyStrategyOperateMode": {"operateIntelligentScheduleModeOpen": 6666}}}`) 51 | - Feed-in control (`feedGridMode` -> `{"sn": "SN", "cmdId": 17, "cmdFunc": 254, "dirDest": 1, "dirSrc": 1, "dest": 2, "needAck": true, "params": {"cfgFeedGridMode": "VALUE"}}`) 52 | 53 | *Sliders (numbers)* 54 | - Backup Reserve Level (`backupReverseSoc` -> `{"sn": "SN", "cmdId": 17, "cmdFunc": 254, "dirDest": 1, "dirSrc": 1, "dest": 2, "needAck": true, "params": {"cfgBackupReverseSoc": "VALUE"}}` [3 - 95]) 55 | 56 | *Selects* 57 | 58 | 59 | -------------------------------------------------------------------------------- /custom_components/ecoflow_cloud/devices/internal/river_mini.py: -------------------------------------------------------------------------------- 1 | from custom_components.ecoflow_cloud.api import EcoflowApiClient 2 | from custom_components.ecoflow_cloud.devices import const, BaseDevice 3 | from custom_components.ecoflow_cloud.entities import BaseSensorEntity, BaseNumberEntity, BaseSwitchEntity, BaseSelectEntity 4 | from custom_components.ecoflow_cloud.number import MaxBatteryLevelEntity 5 | from custom_components.ecoflow_cloud.sensor import LevelSensorEntity, TempSensorEntity, \ 6 | CyclesSensorEntity, InEnergySensorEntity, InWattsSensorEntity, OutEnergySensorEntity, OutWattsSensorEntity, \ 7 | MilliampSensorEntity, InMilliVoltSensorEntity, \ 8 | BeMilliVoltSensorEntity 9 | from custom_components.ecoflow_cloud.switch import EnabledEntity 10 | 11 | 12 | class RiverMini(BaseDevice): 13 | def sensors(self, client: EcoflowApiClient) -> list[BaseSensorEntity]: 14 | return [ 15 | LevelSensorEntity(client, self, "inv.soc", const.MAIN_BATTERY_LEVEL) 16 | .attr("inv.maxChargeSoc", const.ATTR_DESIGN_CAPACITY, 0), 17 | 18 | InWattsSensorEntity(client, self, "inv.inputWatts", const.AC_IN_POWER), 19 | OutWattsSensorEntity(client, self, "inv.outputWatts", const.AC_OUT_POWER), 20 | 21 | BeMilliVoltSensorEntity(client, self, "inv.invInVol", const.AC_IN_VOLT), 22 | BeMilliVoltSensorEntity(client, self, "inv.invOutVol", const.AC_OUT_VOLT), 23 | 24 | InMilliVoltSensorEntity(client, self, "inv.dcInVol", const.SOLAR_IN_VOLTAGE), 25 | MilliampSensorEntity(client, self, "inv.dcInAmp", const.SOLAR_IN_CURRENT), 26 | 27 | TempSensorEntity(client, self, "inv.inTemp", const.INV_IN_TEMP), 28 | TempSensorEntity(client, self, "inv.outTemp", const.INV_OUT_TEMP), 29 | 30 | InEnergySensorEntity(client, self, "pd.chgSunPower", const.SOLAR_IN_ENERGY), 31 | InEnergySensorEntity(client, self, "pd.chgPowerAC", const.CHARGE_AC_ENERGY), 32 | InEnergySensorEntity(client, self, "pd.chgPowerDC", const.CHARGE_DC_ENERGY), 33 | OutEnergySensorEntity(client, self, "pd.dsgPowerAC", const.DISCHARGE_AC_ENERGY), 34 | OutEnergySensorEntity(client, self, "pd.dsgPowerDC", const.DISCHARGE_DC_ENERGY), 35 | 36 | InWattsSensorEntity(client, self, "pd.wattsInSum", const.TOTAL_IN_POWER), 37 | OutWattsSensorEntity(client, self, "pd.wattsOutSum", const.TOTAL_OUT_POWER), 38 | 39 | CyclesSensorEntity(client, self, "inv.cycles", const.CYCLES), 40 | ] 41 | 42 | def numbers(self, client: EcoflowApiClient) -> list[BaseNumberEntity]: 43 | return [ 44 | MaxBatteryLevelEntity(client, self, "inv.maxChargeSoc", const.MAX_CHARGE_LEVEL, 30, 100, 45 | lambda value: {"moduleType": 0, "operateType": "TCP", 46 | "params": {"id": 0, "maxChgSoc": value}}), 47 | ] 48 | 49 | def switches(self, client: EcoflowApiClient) -> list[BaseSwitchEntity]: 50 | return [ 51 | EnabledEntity(client, self, "inv.cfgAcEnabled", const.AC_ENABLED, lambda value: {"moduleType": 0, "operateType": "TCP", "params": {"id": 66, "enabled": value}}), 52 | EnabledEntity(client, self, "inv.cfgAcXboost", const.XBOOST_ENABLED, lambda value: {"moduleType": 0, "operateType": "TCP", "params": {"id": 66, "xboost": value}}), 53 | ] 54 | 55 | def selects(self, client: EcoflowApiClient) -> list[BaseSelectEntity]: 56 | return [] -------------------------------------------------------------------------------- /docs/devices/DELTA_3.md: -------------------------------------------------------------------------------- 1 | ## DELTA_3 2 | 3 | *Sensors* 4 | - Main Battery Level (`soc`) 5 | - Main Design Capacity (`designCap`) _(disabled)_ 6 | - Main Full Capacity (`fullCap`) _(disabled)_ 7 | - Main Remain Capacity (`remainCap`) _(disabled)_ 8 | - State of Health (`soh`) 9 | - Battery Level (`v1p0.lcdShowSoc`) 10 | - Total In Power (`powInSumW`) (energy: _[Device Name]_ Total In Energy) 11 | - Total Out Power (`powOutSumW`) (energy: _[Device Name]_ Total Out Energy) 12 | - AC In Power (`powGetAcIn`) (energy: _[Device Name]_ AC In Energy) 13 | - AC Out Power (`powGetAcOut`) (energy: _[Device Name]_ AC Out Energy) 14 | - AC In Volts (`plugInInfoAcInVol`) 15 | - AC Out Volts (`plugInInfoAcOutVol`) 16 | - Solar In Power (`powGetPv`) (energy: _[Device Name]_ Solar In Energy) 17 | - DC Out Power (`powGetDc`) 18 | - Type-C (1) Out Power (`powGetTypec1`) 19 | - Type-C (2) Out Power (`powGetTypec2`) 20 | - USB QC (1) Out Power (`powGetQcusb1`) 21 | - USB QC (2) Out Power (`powGetQcusb2`) 22 | - Charge Remaining Time (`v1p0.chgRemainTime`) 23 | - Discharge Remaining Time (`v1p0.dsgRemainTime`) 24 | - Cycles (`cycles`) 25 | - Battery Temperature (`temp`) 26 | - Min Cell Temperature (`minCellTemp`) _(disabled)_ 27 | - Max Cell Temperature (`maxCellTemp`) _(disabled)_ 28 | - Battery Volts (`vol`) _(disabled)_ 29 | - Min Cell Volts (`minCellVol`) _(disabled)_ 30 | - Max Cell Volts (`maxCellVol`) _(disabled)_ 31 | - Status 32 | 33 | *Switches* 34 | - Beeper (`enBeep` -> `{"moduleType": 5, "operateType": "quietMode", "params": {"enabled": "VALUE"}}`) 35 | - X-Boost Enabled (`xboostEn` -> `{"moduleType": 5, "operateType": "acOutCfg", "params": {"enabled": 255, "out_voltage": -1, "out_freq": 255, "xboost": "VALUE"}}`) 36 | 37 | *Sliders (numbers)* 38 | - Max Charge Level (`v1p0.maxChargeSoc` -> `{"moduleType": 2, "operateType": "upsConfig", "params": {"maxChgSoc": "VALUE"}}` [50 - 100]) 39 | - Min Discharge Level (`v1p0.minDsgSoc` -> `{"moduleType": 2, "operateType": "dsgCfg", "params": {"minDsgSoc": "VALUE"}}` [0 - 30]) 40 | - Backup Reserve Level (`backupReverseSoc` -> `{"moduleType": 1, "operateType": "watthConfig", "params": {"isConfig": 1, "backupReverseSoc": "VALUE", "minDsgSoc": 0, "minChgSoc": 0}}` [5 - 100]) 41 | - Generator Auto Start Level (`v1p0.minOpenOilEbSoc` -> `{"moduleType": 2, "operateType": "openOilSoc", "params": {"openOilSoc": "VALUE"}}` [0 - 30]) 42 | - Generator Auto Stop Level (`v1p0.maxCloseOilEbSoc` -> `{"moduleType": 2, "operateType": "closeOilSoc", "params": {"closeOilSoc": "VALUE"}}` [50 - 100]) 43 | - AC Charging Power (`plugInInfoAcInChgPowMax` -> `{"moduleType": 5, "operateType": "acChgCfg", "params": {"chgWatts": "VALUE", "chgPauseFlag": 255}}` [200 - 1200]) 44 | 45 | *Selects* 46 | - Screen Timeout (`screenOffTime` -> `{"moduleType": 1, "operateType": "lcdCfg", "params": {"brighLevel": 255, "delayOff": "VALUE"}}` [Never (0), 10 sec (10), 30 sec (30), 1 min (60), 5 min (300), 30 min (1800)]) 47 | - Unit Timeout (`devStandbyTime` -> `{"moduleType": 1, "operateType": "standbyTime", "params": {"standbyMin": "VALUE"}}` [Never (0), 30 min (30), 1 hr (60), 2 hr (120), 4 hr (240), 6 hr (360), 12 hr (720), 24 hr (1440)]) 48 | - AC Timeout (`acStandbyTime` -> `{"moduleType": 5, "operateType": "standbyTime", "params": {"standbyMins": "VALUE"}}` [Never (0), 30 min (30), 1 hr (60), 2 hr (120), 4 hr (240), 6 hr (360), 12 hr (720), 24 hr (1440)]) 49 | - DC (12V) Timeout (`dcStandbyTime` -> `{"moduleType": 5, "operateType": "carStandby", "params": {"standbyMins": "VALUE"}}` [Never (0), 30 min (30), 1 hr (60), 2 hr (120), 4 hr (240), 6 hr (360), 12 hr (720), 24 hr (1440)]) 50 | 51 | 52 | -------------------------------------------------------------------------------- /docs/devices/DELTA_3-Public.md: -------------------------------------------------------------------------------- 1 | ## DELTA_3 2 | 3 | *Sensors* 4 | - Main Battery Level (`soc`) 5 | - Main Design Capacity (`designCap`) _(disabled)_ 6 | - Main Full Capacity (`fullCap`) _(disabled)_ 7 | - Main Remain Capacity (`remainCap`) _(disabled)_ 8 | - State of Health (`soh`) 9 | - Battery Level (`v1p0.lcdShowSoc`) 10 | - Total In Power (`powInSumW`) (energy: _[Device Name]_ Total In Energy) 11 | - Total Out Power (`powOutSumW`) (energy: _[Device Name]_ Total Out Energy) 12 | - AC In Power (`powGetAcIn`) (energy: _[Device Name]_ AC In Energy) 13 | - AC Out Power (`powGetAcOut`) (energy: _[Device Name]_ AC Out Energy) 14 | - AC In Volts (`plugInInfoAcInVol`) 15 | - AC Out Volts (`plugInInfoAcOutVol`) 16 | - Solar In Power (`powGetPv`) (energy: _[Device Name]_ Solar In Energy) 17 | - DC Out Power (`powGetDc`) 18 | - Type-C (1) Out Power (`powGetTypec1`) 19 | - Type-C (2) Out Power (`powGetTypec2`) 20 | - USB QC (1) Out Power (`powGetQcusb1`) 21 | - USB QC (2) Out Power (`powGetQcusb2`) 22 | - Charge Remaining Time (`v1p0.chgRemainTime`) 23 | - Discharge Remaining Time (`v1p0.dsgRemainTime`) 24 | - Cycles (`cycles`) 25 | - Battery Temperature (`temp`) 26 | - Min Cell Temperature (`minCellTemp`) _(disabled)_ 27 | - Max Cell Temperature (`maxCellTemp`) _(disabled)_ 28 | - Battery Volts (`vol`) _(disabled)_ 29 | - Min Cell Volts (`minCellVol`) _(disabled)_ 30 | - Max Cell Volts (`maxCellVol`) _(disabled)_ 31 | - Status 32 | 33 | *Switches* 34 | - Beeper (`enBeep` -> `{"moduleType": 5, "operateType": "quietMode", "params": {"enabled": "VALUE"}}`) 35 | - X-Boost Enabled (`xboostEn` -> `{"moduleType": 5, "operateType": "acOutCfg", "params": {"enabled": 255, "out_voltage": -1, "out_freq": 255, "xboost": "VALUE"}}`) 36 | 37 | *Sliders (numbers)* 38 | - Max Charge Level (`v1p0.maxChargeSoc` -> `{"moduleType": 2, "operateType": "upsConfig", "params": {"maxChgSoc": "VALUE"}}` [50 - 100]) 39 | - Min Discharge Level (`v1p0.minDsgSoc` -> `{"moduleType": 2, "operateType": "dsgCfg", "params": {"minDsgSoc": "VALUE"}}` [0 - 30]) 40 | - Backup Reserve Level (`backupReverseSoc` -> `{"moduleType": 1, "operateType": "watthConfig", "params": {"isConfig": 1, "backupReverseSoc": "VALUE", "minDsgSoc": 0, "minChgSoc": 0}}` [5 - 100]) 41 | - Generator Auto Start Level (`v1p0.minOpenOilEbSoc` -> `{"moduleType": 2, "operateType": "openOilSoc", "params": {"openOilSoc": "VALUE"}}` [0 - 30]) 42 | - Generator Auto Stop Level (`v1p0.maxCloseOilEbSoc` -> `{"moduleType": 2, "operateType": "closeOilSoc", "params": {"closeOilSoc": "VALUE"}}` [50 - 100]) 43 | - AC Charging Power (`plugInInfoAcInChgPowMax` -> `{"moduleType": 5, "operateType": "acChgCfg", "params": {"chgWatts": "VALUE", "chgPauseFlag": 255}}` [200 - 1200]) 44 | 45 | *Selects* 46 | - Screen Timeout (`screenOffTime` -> `{"moduleType": 1, "operateType": "lcdCfg", "params": {"brighLevel": 255, "delayOff": "VALUE"}}` [Never (0), 10 sec (10), 30 sec (30), 1 min (60), 5 min (300), 30 min (1800)]) 47 | - Unit Timeout (`devStandbyTime` -> `{"moduleType": 1, "operateType": "standbyTime", "params": {"standbyMin": "VALUE"}}` [Never (0), 30 min (30), 1 hr (60), 2 hr (120), 4 hr (240), 6 hr (360), 12 hr (720), 24 hr (1440)]) 48 | - AC Timeout (`acStandbyTime` -> `{"moduleType": 5, "operateType": "standbyTime", "params": {"standbyMins": "VALUE"}}` [Never (0), 30 min (30), 1 hr (60), 2 hr (120), 4 hr (240), 6 hr (360), 12 hr (720), 24 hr (1440)]) 49 | - DC (12V) Timeout (`dcStandbyTime` -> `{"moduleType": 5, "operateType": "carStandby", "params": {"standbyMins": "VALUE"}}` [Never (0), 30 min (30), 1 hr (60), 2 hr (120), 4 hr (240), 6 hr (360), 12 hr (720), 24 hr (1440)]) 50 | 51 | 52 | -------------------------------------------------------------------------------- /docs/devices/DELTA_MINI.md: -------------------------------------------------------------------------------- 1 | ## DELTA_MINI 2 | 3 | *Sensors* 4 | - Main Battery Level (`bmsMaster.soc`) 5 | - Main Battery Level (Precise) (`bmsMaster.f32ShowSoc`) _(disabled)_ 6 | - Main Design Capacity (`bmsMaster.designCap`) _(disabled)_ 7 | - Main Full Capacity (`bmsMaster.fullCap`) _(disabled)_ 8 | - Main Remain Capacity (`bmsMaster.remainCap`) _(disabled)_ 9 | - State of Health (`bmsMaster.soh`) 10 | - Battery Level (`ems.lcdShowSoc`) 11 | - Battery Level (Precise) (`ems.f32LcdShowSoc`) _(disabled)_ 12 | - Total In Power (`pd.wattsInSum`) 13 | - Total Out Power (`pd.wattsOutSum`) 14 | - AC In Power (`inv.inputWatts`) 15 | - AC Out Power (`inv.outputWatts`) 16 | - AC In Volts (`inv.acInVol`) 17 | - AC Out Volts (`inv.invOutVol`) 18 | - Solar In Power (`mppt.inWatts`) 19 | - Solar In Voltage (`mppt.inVol`) 20 | - Solar In Current (`mppt.inAmp`) 21 | - DC Out Power (`mppt.outWatts`) 22 | - DC Out Voltage (`mppt.outVol`) 23 | - DC Car Out Power (`mppt.carOutWatts`) 24 | - DC Anderson Out Power (`mppt.dcdc12vWatts`) 25 | - Type-C (1) Out Power (`pd.typec1Watts`) 26 | - Type-C (2) Out Power (`pd.typec2Watts`) 27 | - USB (1) Out Power (`pd.usb1Watts`) 28 | - USB (2) Out Power (`pd.usb2Watts`) 29 | - USB QC (1) Out Power (`pd.qcUsb1Watts`) 30 | - USB QC (2) Out Power (`pd.qcUsb2Watts`) 31 | - Charge Remaining Time (`ems.chgRemainTime`) 32 | - Discharge Remaining Time (`ems.dsgRemainTime`) 33 | - Cycles (`bmsMaster.cycles`) 34 | - Battery Temperature (`bmsMaster.temp`) _(disabled)_ 35 | - Main Battery Current (`bmsMaster.amp`) _(disabled)_ 36 | - Battery Volts (`bmsMaster.vol`) _(disabled)_ 37 | - Solar In Energy (`pd.chgSunPower`) 38 | - Battery Charge Energy from AC (`pd.chgPowerAc`) 39 | - Battery Charge Energy from DC (`pd.chgPowerDc`) 40 | - Battery Discharge Energy to AC (`pd.dsgPowerAc`) 41 | - Battery Discharge Energy to DC (`pd.dsgPowerDc`) 42 | - Status 43 | 44 | *Switches* 45 | - Beeper (`pd.beepState` -> `{"moduleType": 0, "operateType": "TCP", "params": {"id": 38, "enabled": "VALUE"}}`) 46 | - DC (12V) Enabled (`mppt.carState` -> `{"moduleType": 0, "operateType": "TCP", "params": {"id": 81, "enabled": "VALUE"}}`) 47 | - AC Enabled (`inv.cfgAcEnabled` -> `{"moduleType": 0, "operateType": "TCP", "params": {"id": 66, "enabled": "VALUE"}}`) 48 | - X-Boost Enabled (`inv.cfgAcXboost` -> `{"moduleType": 0, "operateType": "TCP", "params": {"id": 66, "xboost": "VALUE"}}`) 49 | 50 | *Sliders (numbers)* 51 | - Max Charge Level (`ems.maxChargeSoc` -> `{"moduleType": 0, "operateType": "TCP", "params": {"id": 49, "maxChgSoc": "VALUE"}}` [50 - 100]) 52 | - Min Discharge Level (`ems.minDsgSoc` -> `{"moduleType": 0, "operateType": "TCP", "params": {"id": 51, "minDsgSoc": "VALUE"}}` [0 - 30]) 53 | - AC Charging Power (`inv.cfgSlowChgWatts` -> `{"moduleType": 0, "operateType": "TCP", "params": {"slowChgPower": "VALUE", "id": 69}}` [200 - 900]) 54 | 55 | *Selects* 56 | - DC (12V) Charge Current (`mppt.cfgDcChgCurrent` -> `{"moduleType": 0, "operateType": "TCP", "params": {"currMa": "VALUE", "id": 71}}` [4A (4000), 6A (6000), 8A (8000)]) 57 | - Screen Timeout (`pd.lcdOffSec` -> `{"moduleType": 0, "operateType": "TCP", "params": {"lcdTime": "VALUE", "id": 39}}` [Never (0), 10 sec (10), 30 sec (30), 1 min (60), 5 min (300), 30 min (1800)]) 58 | - Unit Timeout (`pd.standByMode` -> `{"moduleType": 0, "operateType": "TCP", "params": {"standByMode": "VALUE", "id": 33}}` [Never (0), 30 min (30), 1 hr (60), 2 hr (120), 6 hr (360), 12 hr (720)]) 59 | - AC Timeout (`inv.cfgStandbyMin` -> `{"moduleType": 0, "operateType": "TCP", "params": {"standByMins": "VALUE", "id": 153}}` [Never (0), 30 min (30), 1 hr (60), 2 hr (120), 4 hr (240), 6 hr (360), 12 hr (720), 24 hr (1440)]) 60 | 61 | 62 | -------------------------------------------------------------------------------- /docs/devices/PowerStream-Public.md: -------------------------------------------------------------------------------- 1 | ## PowerStream 2 | 3 | *Sensors* 4 | - ESP Temperature (`20_1.espTempsensor`) 5 | - Solar 1 Watts (`20_1.pv1InputWatts`) 6 | - Solar 1 Input Potential (`20_1.pv1InputVolt`) 7 | - Solar 1 Op Potential (`20_1.pv1OpVolt`) 8 | - Solar 1 Current (`20_1.pv1InputCur`) 9 | - Solar 1 Temperature (`20_1.pv1Temp`) 10 | - Solar 1 Relay Status (`20_1.pv1RelayStatus`) 11 | - Solar 1 Error Code (`20_1.pv1ErrCode`) _(disabled)_ 12 | - Solar 1 Warning Code (`20_1.pv1WarnCode`) _(disabled)_ 13 | - Solar 1 Status (`20_1.pv1Statue`) _(disabled)_ 14 | - Solar 2 Watts (`20_1.pv2InputWatts`) 15 | - Solar 2 Input Potential (`20_1.pv2InputVolt`) 16 | - Solar 2 Op Potential (`20_1.pv2OpVolt`) 17 | - Solar 2 Current (`20_1.pv2InputCur`) 18 | - Solar 2 Temperature (`20_1.pv2Temp`) 19 | - Solar 2 Relay Status (`20_1.pv2RelayStatus`) 20 | - Solar 2 Error Code (`20_1.pv2ErrCode`) _(disabled)_ 21 | - Solar 2 Warning Code (`20_1.pv2WarningCode`) _(disabled)_ 22 | - Solar 2 Status (`20_1.pv2Statue`) _(disabled)_ 23 | - Battery Type (`20_1.bpType`) _(disabled)_ 24 | - Battery Charge (`20_1.batSoc`) 25 | - Battery Input Watts (`20_1.batInputWatts`) 26 | - Battery Input Potential (`20_1.batInputVolt`) 27 | - Battery Op Potential (`20_1.batOpVolt`) 28 | - Battery Input Current (`20_1.batInputCur`) 29 | - Battery Temperature (`20_1.batTemp`) 30 | - Charge Time (`20_1.chgRemainTime`) 31 | - Discharge Time (`20_1.dsgRemainTime`) 32 | - Battery Error Code (`20_1.batErrCode`) _(disabled)_ 33 | - Battery Warning Code (`20_1.batWarningCode`) _(disabled)_ 34 | - Battery Status (`20_1.batStatue`) _(disabled)_ 35 | - LLC Input Potential (`20_1.llcInputVolt`) _(disabled)_ 36 | - LLC Op Potential (`20_1.llcOpVolt`) _(disabled)_ 37 | - LLC Temperature (`20_1.llcTemp`) 38 | - LLC Error Code (`20_1.llcErrCode`) _(disabled)_ 39 | - LLC Warning Code (`20_1.llcWarningCode`) _(disabled)_ 40 | - LLC Status (`20_1.llcStatue`) _(disabled)_ 41 | - Inverter On/Off Status (`20_1.invOnOff`) 42 | - Inverter Output Watts (`20_1.invOutputWatts`) 43 | - Inverter Output Potential (`20_1.invInputVolt`) _(disabled)_ 44 | - Inverter Op Potential (`20_1.invOpVolt`) 45 | - Inverter Output Current (`20_1.invOutputCur`) 46 | - Inverter Frequency (`20_1.invFreq`) 47 | - Inverter Temperature (`20_1.invTemp`) 48 | - Inverter Relay Status (`20_1.invRelayStatus`) 49 | - Inverter Error Code (`20_1.invErrCode`) _(disabled)_ 50 | - Inverter Warning Code (`20_1.invWarnCode`) _(disabled)_ 51 | - Inverter Status (`20_1.invStatue`) _(disabled)_ 52 | - Other Loads (`20_1.permanentWatts`) 53 | - Smart Plug Loads (`20_1.dynamicWatts`) 54 | - Rated Power (`20_1.ratedPower`) 55 | - Lower Battery Limit (`20_1.lowerLimit`) _(disabled)_ 56 | - Upper Battery Limit (`20_1.upperLimit`) _(disabled)_ 57 | - Wireless Error Code (`20_1.wirelessErrCode`) _(disabled)_ 58 | - Wireless Warning Code (`20_1.wirelessWarnCode`) _(disabled)_ 59 | - LED Brightness (`20_1.invBrightness`) _(disabled)_ 60 | - Heartbeat Frequency (`20_1.heartbeatFrequency`) _(disabled)_ 61 | - Status 62 | 63 | *Switches* 64 | 65 | *Sliders (numbers)* 66 | - Min Discharge Level (`20_1.lowerLimit` -> `{"sn": "SN", "cmdCode": "WN511_SET_BAT_LOWER_PACK", "params": {"lowerLimit": "VALUE"}}` [0 - 30]) 67 | - Max Charge Level (`20_1.upperLimit` -> `{"sn": "SN", "cmdCode": "WN511_SET_BAT_UPPER_PACK", "params": {"upperLimit": "VALUE"}}` [70 - 100]) 68 | - Brightness (`20_1.invBrightness` -> `{"sn": "SN", "cmdCode": "WN511_SET_BRIGHTNESS_PACK", "params": {"brightness": "VALUE"}}` [0 - 1023]) 69 | - Custom load power settings (`20_1.permanentWatts` -> `{"sn": "SN", "cmdCode": "WN511_SET_PERMANENT_WATTS_PACK", "params": {"permanentWatts": "VALUE"}}` [0 - 800]) 70 | 71 | *Selects* 72 | - Power supply mode (`20_1.supplyPriority` -> `{"sn": "SN", "cmdCode": "WN511_SET_SUPPLY_PRIORITY_PACK", "params": {"supplyPriority": "VALUE"}}` [Prioritize power supply (0), Prioritize power storage (1)]) 73 | 74 | 75 | -------------------------------------------------------------------------------- /docs/devices/RIVER_MAX.md: -------------------------------------------------------------------------------- 1 | ## RIVER_MAX 2 | 3 | *Sensors* 4 | - Main Battery Level (`bmsMaster.soc`) 5 | - Main Design Capacity (`bmsMaster.designCap`) _(disabled)_ 6 | - Main Full Capacity (`bmsMaster.fullCap`) _(disabled)_ 7 | - Main Remain Capacity (`bmsMaster.remainCap`) _(disabled)_ 8 | - Battery Level (`pd.soc`) 9 | - Total In Power (`pd.wattsInSum`) 10 | - Total Out Power (`pd.wattsOutSum`) 11 | - Solar In Current (`inv.dcInAmp`) 12 | - Solar In Voltage (`inv.dcInVol`) 13 | - AC In Power (`inv.inputWatts`) 14 | - AC Out Power (`inv.outputWatts`) 15 | - AC In Volts (`inv.acInVol`) 16 | - AC Out Volts (`inv.invOutVol`) 17 | - DC Out Power (`pd.carWatts`) 18 | - Type-C Out Power (`pd.typecWatts`) 19 | - DC Temperature (`pd.carTemp`) _(disabled)_ 20 | - USB C Temperature (`pd.typecTemp`) _(disabled)_ 21 | - USB (1) Out Power (`pd.usb1Watts`) 22 | - USB (2) Out Power (`pd.usb2Watts`) 23 | - USB (3) Out Power (`pd.usb3Watts`) 24 | - Remaining Time (`pd.remainTime`) 25 | - Cycles (`bmsMaster.cycles`) 26 | - Battery Temperature (`bmsMaster.temp`) 27 | - Min Cell Temperature (`bmsMaster.minCellTemp`) _(disabled)_ 28 | - Max Cell Temperature (`bmsMaster.maxCellTemp`) _(disabled)_ 29 | - Battery Current (`bmsMaster.amp`) _(disabled)_ 30 | - Battery Volts (`bmsMaster.vol`) _(disabled)_ 31 | - Min Cell Volts (`bmsMaster.minCellVol`) _(disabled)_ 32 | - Max Cell Volts (`bmsMaster.maxCellVol`) _(disabled)_ 33 | - Inverter Inside Temperature (`inv.inTemp`) 34 | - Inverter Outside Temperature (`inv.outTemp`) 35 | - Solar In Energy (`pd.chgSunPower`) 36 | - Battery Charge Energy from AC (`pd.chgPowerAC`) 37 | - Battery Charge Energy from DC (`pd.chgPowerDC`) 38 | - Battery Discharge Energy to AC (`pd.dsgPowerAC`) 39 | - Battery Discharge Energy to DC (`pd.dsgPowerDC`) 40 | - Slave Battery Level (`bmsSlave1.soc`) _(auto)_ 41 | - Slave Design Capacity (`bmsSlave1.designCap`) _(disabled)_ 42 | - Slave Full Capacity (`bmsSlave1.fullCap`) _(disabled)_ 43 | - Slave Remain Capacity (`bmsSlave1.remainCap`) _(disabled)_ 44 | - Slave Battery Temperature (`bmsSlave1.temp`) _(auto)_ 45 | - Slave Min Cell Temperature (`bmsSlave1.minCellTemp`) _(disabled)_ 46 | - Slave Max Cell Temperature (`bmsSlave1.maxCellTemp`) _(disabled)_ 47 | - Slave Battery Current (`bmsSlave1.amp`) _(disabled)_ 48 | - Slave Battery Volts (`bmsSlave1.vol`) _(disabled)_ 49 | - Slave Min Cell Volts (`bmsSlave1.minCellVol`) _(disabled)_ 50 | - Slave Max Cell Volts (`bmsSlave1.maxCellVol`) _(disabled)_ 51 | - Slave Cycles (`bmsSlave1.cycles`) _(auto)_ 52 | - Status 53 | 54 | *Switches* 55 | - Beeper (`pd.beepState` -> `{"moduleType": 0, "operateType": "TCP", "params": {"id": 38, "enabled": "VALUE"}}`) 56 | - AC Enabled (`inv.cfgAcEnabled` -> `{"moduleType": 0, "operateType": "TCP", "params": {"id": 66, "enabled": "VALUE"}}`) 57 | - DC (12V) Enabled (`pd.carSwitch` -> `{"moduleType": 0, "operateType": "TCP", "params": {"id": 34, "enabled": "VALUE"}}`) 58 | - X-Boost Enabled (`inv.cfgAcXboost` -> `{"moduleType": 0, "operateType": "TCP", "params": {"id": 66, "xboost": "VALUE"}}`) 59 | - Auto Fan Speed (`inv.cfgFanMode` -> `{"moduleType": 0, "operateType": "TCP", "params": {"id": 73, "fanMode": "VALUE"}}`) 60 | 61 | *Sliders (numbers)* 62 | - Max Charge Level (`bmsMaster.maxChargeSoc` -> `{"moduleType": 0, "operateType": "TCP", "params": {"id": 49, "maxChgSoc": "VALUE"}}` [30 - 100]) 63 | 64 | *Selects* 65 | - Unit Timeout (`pd.standByMode` -> `{"moduleType": 0, "operateType": "TCP", "params": {"id": 33, "standByMode": "VALUE"}}` [Never (0), 30 min (30), 1 hr (60), 2 hr (120), 6 hr (360), 12 hr (720)]) 66 | - DC (12V) Timeout (`pd.carDelayOffMin` -> `{"moduleType": 0, "operateType": "TCP", "params": {"cmdSet": 32, "id": 84, "carDelayOffMin": "VALUE"}}` [Never (0), 2 hr (120), 4 hr (240), 6 hr (360), 12 hr (720), 24 hr (1440)]) 67 | - AC Timeout (`inv.cfgStandbyMin` -> `{"moduleType": 0, "operateType": "TCP", "params": {"id": 153, "standByMins": "VALUE"}}` [Never (0), 2 hr (120), 4 hr (240), 6 hr (360), 12 hr (720), 24 hr (1440)]) 68 | 69 | 70 | -------------------------------------------------------------------------------- /docs/devices/RIVER_2_PRO.md: -------------------------------------------------------------------------------- 1 | ## RIVER_2_PRO 2 | 3 | *Sensors* 4 | - Main Battery Level (`bms_bmsStatus.soc`) 5 | - Main Design Capacity (`bms_bmsStatus.designCap`) _(disabled)_ 6 | - Main Full Capacity (`bms_bmsStatus.fullCap`) _(disabled)_ 7 | - Main Remain Capacity (`bms_bmsStatus.remainCap`) _(disabled)_ 8 | - State of Health (`bms_bmsStatus.soh`) 9 | - Battery Level (`bms_emsStatus.lcdShowSoc`) 10 | - Battery Charging State (`bms_emsStatus.chgState`) 11 | - Total In Power (`pd.wattsInSum`) (energy: _[Device Name]_ Total In Energy) 12 | - Total Out Power (`pd.wattsOutSum`) (energy: _[Device Name]_ Total Out Energy) 13 | - AC In Power (`inv.inputWatts`) (energy: _[Device Name]_ AC In Energy) 14 | - AC Out Power (`inv.outputWatts`) (energy: _[Device Name]_ AC Out Energy) 15 | - AC In Volts (`inv.acInVol`) 16 | - AC Out Volts (`inv.invOutVol`) 17 | - Type-C In Power (`pd.typecChaWatts`) 18 | - Solar In Power (`mppt.inWatts`) (energy: _[Device Name]_ Solar In Energy) 19 | - DC Out Power (`pd.carWatts`) 20 | - Type-C Out Power (`pd.typec1Watts`) 21 | - USB Out Power (`pd.usb1Watts`) 22 | - Charge Remaining Time (`bms_emsStatus.chgRemainTime`) 23 | - Discharge Remaining Time (`bms_emsStatus.dsgRemainTime`) 24 | - Remaining Time (`pd.remainTime`) 25 | - Inv Out Temperature (`inv.outTemp`) 26 | - Cycles (`bms_bmsStatus.cycles`) 27 | - Battery Temperature (`bms_bmsStatus.temp`) 28 | - Min Cell Temperature (`bms_bmsStatus.minCellTemp`) _(disabled)_ 29 | - Max Cell Temperature (`bms_bmsStatus.maxCellTemp`) _(disabled)_ 30 | - Battery Volts (`bms_bmsStatus.vol`) _(disabled)_ 31 | - Min Cell Volts (`bms_bmsStatus.minCellVol`) _(disabled)_ 32 | - Max Cell Volts (`bms_bmsStatus.maxCellVol`) _(disabled)_ 33 | - Status 34 | 35 | *Switches* 36 | - AC Enabled (`mppt.cfgAcEnabled` -> `{"moduleType": 5, "operateType": "acOutCfg", "params": {"enabled": "VALUE", "out_voltage": -1, "out_freq": 255, "xboost": 255}}`) 37 | - X-Boost Enabled (`mppt.cfgAcXboost` -> `{"moduleType": 5, "operateType": "acOutCfg", "params": {"enabled": 255, "out_voltage": -1, "out_freq": 255, "xboost": "VALUE"}}`) 38 | - DC (12V) Enabled (`pd.carState` -> `{"moduleType": 5, "operateType": "mpptCar", "params": {"enabled": "VALUE"}}`) 39 | - Backup Reserve Enabled (`pd.watchIsConfig` -> `{"moduleType": 1, "operateType": "watthConfig", "params": {"isConfig": "VALUE", "bpPowerSoc": 333300, "minDsgSoc": 0, "minChgSoc": 0}}`) 40 | 41 | *Sliders (numbers)* 42 | - Max Charge Level (`bms_emsStatus.maxChargeSoc` -> `{"moduleType": 2, "operateType": "upsConfig", "params": {"maxChgSoc": "VALUE"}}` [50 - 100]) 43 | - Min Discharge Level (`bms_emsStatus.minDsgSoc` -> `{"moduleType": 2, "operateType": "dsgCfg", "params": {"minDsgSoc": "VALUE"}}` [0 - 30]) 44 | - AC Charging Power (`mppt.cfgChgWatts` -> `{"moduleType": 5, "operateType": "acChgCfg", "params": {"chgWatts": "VALUE", "chgPauseFlag": 255}}` [100 - 950]) 45 | - Backup Reserve Level (`pd.bpPowerSoc` -> `{"moduleType": 1, "operateType": "watthConfig", "params": {"isConfig": 1, "bpPowerSoc": "VALUE", "minDsgSoc": 0, "minChgSoc": 0}}` [5 - 100]) 46 | 47 | *Selects* 48 | - DC (12V) Charge Current (`mppt.dcChgCurrent` -> `{"moduleType": 5, "operateType": "dcChgCfg", "params": {"dcChgCfg": "VALUE"}}` [4A (4000), 6A (6000), 8A (8000)]) 49 | - DC Mode (`mppt.cfgChgType` -> `{"moduleType": 5, "operateType": "chaType", "params": {"chaType": "VALUE"}}` [Auto (0), Solar Recharging (1), Car Recharging (2)]) 50 | - Screen Timeout (`mppt.scrStandbyMin` -> `{"moduleType": 5, "operateType": "lcdCfg", "params": {"brighLevel": 255, "delayOff": "VALUE"}}` [Never (0), 10 sec (10), 30 sec (30), 1 min (60), 5 min (300), 30 min (1800)]) 51 | - Unit Timeout (`mppt.powStandbyMin` -> `{"moduleType": 5, "operateType": "standby", "params": {"standbyMins": "VALUE"}}` [Never (0), 30 min (30), 1 hr (60), 2 hr (120), 4 hr (240), 6 hr (360), 12 hr (720), 24 hr (1440)]) 52 | - AC Timeout (`mppt.acStandbyMins` -> `{"moduleType": 5, "operateType": "acStandby", "params": {"standbyMins": "VALUE"}}` [Never (0), 30 min (30), 1 hr (60), 2 hr (120), 4 hr (240), 6 hr (360), 12 hr (720), 24 hr (1440)]) 53 | 54 | 55 | -------------------------------------------------------------------------------- /docs/devices/RIVER_2_Pro-Public.md: -------------------------------------------------------------------------------- 1 | ## RIVER_2_Pro 2 | 3 | *Sensors* 4 | - Main Battery Level (`bms_bmsStatus.soc`) 5 | - Main Design Capacity (`bms_bmsStatus.designCap`) _(disabled)_ 6 | - Main Full Capacity (`bms_bmsStatus.fullCap`) _(disabled)_ 7 | - Main Remain Capacity (`bms_bmsStatus.remainCap`) _(disabled)_ 8 | - State of Health (`bms_bmsStatus.soh`) 9 | - Battery Level (`bms_emsStatus.lcdShowSoc`) 10 | - Battery Charging State (`bms_emsStatus.chgState`) 11 | - Total In Power (`pd.wattsInSum`) (energy: _[Device Name]_ Total In Energy) 12 | - Total Out Power (`pd.wattsOutSum`) (energy: _[Device Name]_ Total Out Energy) 13 | - AC In Power (`inv.inputWatts`) (energy: _[Device Name]_ AC In Energy) 14 | - AC Out Power (`inv.outputWatts`) (energy: _[Device Name]_ AC Out Energy) 15 | - AC In Volts (`inv.acInVol`) 16 | - AC Out Volts (`inv.invOutVol`) 17 | - Type-C In Power (`pd.typecChaWatts`) 18 | - Solar In Power (`mppt.inWatts`) (energy: _[Device Name]_ Solar In Energy) 19 | - DC Out Power (`pd.carWatts`) 20 | - Type-C Out Power (`pd.typec1Watts`) 21 | - USB Out Power (`pd.usb1Watts`) 22 | - Charge Remaining Time (`bms_emsStatus.chgRemainTime`) 23 | - Discharge Remaining Time (`bms_emsStatus.dsgRemainTime`) 24 | - Remaining Time (`pd.remainTime`) 25 | - Inv Out Temperature (`inv.outTemp`) 26 | - Cycles (`bms_bmsStatus.cycles`) 27 | - Battery Temperature (`bms_bmsStatus.temp`) 28 | - Min Cell Temperature (`bms_bmsStatus.minCellTemp`) _(disabled)_ 29 | - Max Cell Temperature (`bms_bmsStatus.maxCellTemp`) _(disabled)_ 30 | - Battery Volts (`bms_bmsStatus.vol`) _(disabled)_ 31 | - Min Cell Volts (`bms_bmsStatus.minCellVol`) _(disabled)_ 32 | - Max Cell Volts (`bms_bmsStatus.maxCellVol`) _(disabled)_ 33 | - Status 34 | 35 | *Switches* 36 | - AC Enabled (`mppt.cfgAcEnabled` -> `{"moduleType": 5, "operateType": "acOutCfg", "params": {"enabled": "VALUE", "out_voltage": -1, "out_freq": 255, "xboost": 255}}`) 37 | - X-Boost Enabled (`mppt.cfgAcXboost` -> `{"moduleType": 5, "operateType": "acOutCfg", "params": {"enabled": 255, "out_voltage": -1, "out_freq": 255, "xboost": "VALUE"}}`) 38 | - DC (12V) Enabled (`pd.carState` -> `{"moduleType": 5, "operateType": "mpptCar", "params": {"enabled": "VALUE"}}`) 39 | - Backup Reserve Enabled (`pd.watchIsConfig` -> `{"moduleType": 1, "operateType": "watthConfig", "params": {"isConfig": "VALUE", "bpPowerSoc": 333300, "minDsgSoc": 0, "minChgSoc": 0}}`) 40 | 41 | *Sliders (numbers)* 42 | - Max Charge Level (`bms_emsStatus.maxChargeSoc` -> `{"moduleType": 2, "operateType": "upsConfig", "params": {"maxChgSoc": "VALUE"}}` [50 - 100]) 43 | - Min Discharge Level (`bms_emsStatus.minDsgSoc` -> `{"moduleType": 2, "operateType": "dsgCfg", "params": {"minDsgSoc": "VALUE"}}` [0 - 30]) 44 | - AC Charging Power (`mppt.cfgChgWatts` -> `{"moduleType": 5, "operateType": "acChgCfg", "params": {"chgWatts": "VALUE", "chgPauseFlag": 255}}` [100 - 950]) 45 | - Backup Reserve Level (`pd.bpPowerSoc` -> `{"moduleType": 1, "operateType": "watthConfig", "params": {"isConfig": 1, "bpPowerSoc": "VALUE", "minDsgSoc": 0, "minChgSoc": 0}}` [5 - 100]) 46 | 47 | *Selects* 48 | - DC (12V) Charge Current (`mppt.dcChgCurrent` -> `{"moduleType": 5, "operateType": "dcChgCfg", "params": {"dcChgCfg": "VALUE"}}` [4A (4000), 6A (6000), 8A (8000)]) 49 | - DC Mode (`mppt.cfgChgType` -> `{"moduleType": 5, "operateType": "chaType", "params": {"chaType": "VALUE"}}` [Auto (0), Solar Recharging (1), Car Recharging (2)]) 50 | - Screen Timeout (`mppt.scrStandbyMin` -> `{"moduleType": 5, "operateType": "lcdCfg", "params": {"brighLevel": 255, "delayOff": "VALUE"}}` [Never (0), 10 sec (10), 30 sec (30), 1 min (60), 5 min (300), 30 min (1800)]) 51 | - Unit Timeout (`mppt.powStandbyMin` -> `{"moduleType": 5, "operateType": "standby", "params": {"standbyMins": "VALUE"}}` [Never (0), 30 min (30), 1 hr (60), 2 hr (120), 4 hr (240), 6 hr (360), 12 hr (720), 24 hr (1440)]) 52 | - AC Timeout (`mppt.acStandbyMins` -> `{"moduleType": 5, "operateType": "acStandby", "params": {"standbyMins": "VALUE"}}` [Never (0), 30 min (30), 1 hr (60), 2 hr (120), 4 hr (240), 6 hr (360), 12 hr (720), 24 hr (1440)]) 53 | 54 | 55 | -------------------------------------------------------------------------------- /custom_components/ecoflow_cloud/api/__init__.py: -------------------------------------------------------------------------------- 1 | import logging 2 | from abc import ABC, abstractmethod 3 | from typing import Any 4 | 5 | from aiohttp import ClientResponse 6 | from attr import dataclass 7 | 8 | from ..device_data import DeviceData 9 | from .message import JSONMessage, Message 10 | 11 | _LOGGER = logging.getLogger(__name__) 12 | 13 | 14 | class EcoflowException(Exception): 15 | pass 16 | 17 | 18 | @dataclass 19 | class EcoflowMqttInfo: 20 | url: str 21 | port: int 22 | username: str 23 | password: str 24 | client_id: str | None = None 25 | 26 | 27 | class EcoflowApiClient(ABC): 28 | def __init__(self): 29 | self.mqtt_info: EcoflowMqttInfo 30 | self.devices: dict[str, Any] = {} 31 | self.mqtt_client = None 32 | 33 | @abstractmethod 34 | async def login(self): 35 | pass 36 | 37 | @abstractmethod 38 | async def fetch_all_available_devices(self): 39 | pass 40 | 41 | @abstractmethod 42 | async def quota_all(self, device_sn: str | None): 43 | pass 44 | 45 | @abstractmethod 46 | def configure_device(self, device_data: DeviceData): 47 | pass 48 | 49 | def add_device(self, device): 50 | self.devices[device.device_data.sn] = device 51 | 52 | def remove_device(self, device): 53 | self.devices.pop(device.device_data.sn, None) 54 | 55 | def _accept_mqqt_certification(self, resp_json: dict): 56 | _LOGGER.info(f"Received MQTT credentials: {resp_json}") 57 | try: 58 | mqtt_url = resp_json["data"]["url"] 59 | mqtt_port = int(resp_json["data"]["port"]) 60 | mqtt_username = resp_json["data"]["certificateAccount"] 61 | mqtt_password = resp_json["data"]["certificatePassword"] 62 | self.mqtt_info = EcoflowMqttInfo( 63 | mqtt_url, mqtt_port, mqtt_username, mqtt_password 64 | ) 65 | except KeyError as key: 66 | raise EcoflowException(f"Failed to extract key {key} from {resp_json}") 67 | 68 | _LOGGER.info(f"Successfully extracted account: {self.mqtt_info.username}") 69 | 70 | async def _get_json_response(self, resp: ClientResponse): 71 | if resp.status != 200: 72 | raise EcoflowException(f"Got HTTP status code {resp.status}: {resp.reason}") 73 | 74 | try: 75 | json_resp = await resp.json() 76 | response_message = json_resp["message"] 77 | except KeyError as key: 78 | raise EcoflowException(f"Failed to extract key {key} from {resp}") 79 | except Exception as error: 80 | raise EcoflowException( 81 | f"Failed to parse response: {resp.text} Error: {error}" 82 | ) 83 | 84 | if response_message.lower() != "success": 85 | raise EcoflowException(f"{response_message}") 86 | 87 | return json_resp 88 | 89 | def send_get_message(self, device_sn: str, command: dict | Message): 90 | if isinstance(command, dict): 91 | command = JSONMessage(command) 92 | 93 | self.mqtt_client.publish( 94 | self.devices[device_sn].device_info.get_topic, command.to_mqtt_payload() 95 | ) 96 | 97 | def send_set_message( 98 | self, device_sn: str, mqtt_state: dict[str, Any], command: dict | Message 99 | ): 100 | if isinstance(command, dict): 101 | command = JSONMessage(command) 102 | 103 | self.devices[device_sn].data.update_to_target_state(mqtt_state) 104 | self.mqtt_client.publish( 105 | self.devices[device_sn].device_info.set_topic, command.to_mqtt_payload() 106 | ) 107 | 108 | def start(self): 109 | from custom_components.ecoflow_cloud.api.ecoflow_mqtt import EcoflowMQTTClient 110 | 111 | self.mqtt_client = EcoflowMQTTClient(self.mqtt_info, self.devices) 112 | 113 | def stop(self): 114 | assert self.mqtt_client is not None 115 | self.mqtt_client.stop() 116 | -------------------------------------------------------------------------------- /docs/devices/RIVER_PRO.md: -------------------------------------------------------------------------------- 1 | ## RIVER_PRO 2 | 3 | *Sensors* 4 | - Main Battery Level (`bmsMaster.soc`) 5 | - Main Full Capacity (`bmsMaster.fullCap`) _(disabled)_ 6 | - Main Remain Capacity (`bmsMaster.remainCap`) _(disabled)_ 7 | - Battery Level (`pd.soc`) 8 | - Total In Power (`pd.wattsInSum`) 9 | - Total Out Power (`pd.wattsOutSum`) 10 | - Solar In Current (`inv.dcInAmp`) 11 | - Solar In Voltage (`inv.dcInVol`) 12 | - AC In Power (`inv.inputWatts`) 13 | - AC Out Power (`inv.outputWatts`) 14 | - AC In Volts (`inv.invInVol`) 15 | - AC Out Volts (`inv.invOutVol`) 16 | - DC Out Power (`pd.carWatts`) 17 | - Type-C Out Power (`pd.typecWatts`) 18 | - DC Temperature (`pd.carTemp`) _(disabled)_ 19 | - USB C Temperature (`pd.typecTemp`) _(disabled)_ 20 | - USB (1) Out Power (`pd.usb1Watts`) 21 | - USB (2) Out Power (`pd.usb2Watts`) 22 | - USB (3) Out Power (`pd.usb3Watts`) 23 | - Remaining Time (`pd.remainTime`) 24 | - Cycles (`bmsMaster.cycles`) 25 | - Battery Temperature (`bmsMaster.temp`) 26 | - Min Cell Temperature (`bmsMaster.minCellTemp`) _(disabled)_ 27 | - Max Cell Temperature (`bmsMaster.maxCellTemp`) _(disabled)_ 28 | - Battery Current (`bmsMaster.amp`) _(disabled)_ 29 | - Battery Volts (`bmsMaster.vol`) _(disabled)_ 30 | - Min Cell Volts (`bmsMaster.minCellVol`) _(disabled)_ 31 | - Max Cell Volts (`bmsMaster.maxCellVol`) _(disabled)_ 32 | - Inverter Inside Temperature (`inv.inTemp`) 33 | - Inverter Outside Temperature (`inv.outTemp`) 34 | - Solar In Energy (`pd.chgSunPower`) 35 | - Battery Charge Energy from AC (`pd.chgPowerAC`) 36 | - Battery Charge Energy from DC (`pd.chgPowerDC`) 37 | - Battery Discharge Energy to AC (`pd.dsgPowerAC`) 38 | - Battery Discharge Energy to DC (`pd.dsgPowerDC`) 39 | - Slave Battery Level (`bmsSlave1.soc`) _(auto)_ 40 | - Slave Full Capacity (`bmsSlave1.fullCap`) _(disabled)_ 41 | - Slave Remain Capacity (`bmsSlave1.remainCap`) _(disabled)_ 42 | - Slave Cycles (`bmsSlave1.cycles`) _(auto)_ 43 | - Slave Battery Temperature (`bmsSlave1.temp`) _(auto)_ 44 | - Slave Min Cell Temperature (`bmsSlave1.minCellTemp`) _(disabled)_ 45 | - Slave Max Cell Temperature (`bmsSlave1.maxCellTemp`) _(disabled)_ 46 | - Slave Battery Current (`bmsSlave1.amp`) _(disabled)_ 47 | - Slave Battery Volts (`bmsSlave1.vol`) _(disabled)_ 48 | - Slave Min Cell Volts (`bmsSlave1.minCellVol`) _(disabled)_ 49 | - Slave Max Cell Volts (`bmsSlave1.maxCellVol`) _(disabled)_ 50 | - Status 51 | 52 | *Switches* 53 | - Beeper (`pd.beepState` -> `{"moduleType": 0, "operateType": "TCP", "params": {"id": 38, "enabled": "VALUE"}}`) 54 | - AC Always On (`inv.acAutoOutConfig` -> `{"moduleType": 0, "operateType": "TCP", "params": {"id": 95, "acautooutConfig": "VALUE", "minAcoutSoc": 255}}`) 55 | - DC (12V) Enabled (`pd.carSwitch` -> `{"moduleType": 0, "operateType": "TCP", "params": {"id": 34, "enabled": "VALUE"}}`) 56 | - AC Enabled (`inv.cfgAcEnabled` -> `{"moduleType": 0, "operateType": "TCP", "params": {"id": 66, "enabled": "VALUE"}}`) 57 | - X-Boost Enabled (`inv.cfgAcXboost` -> `{"moduleType": 0, "operateType": "TCP", "params": {"id": 66, "xboost": "VALUE"}}`) 58 | - AC Slow Charging (`inv.cfgAcChgModeFlg` -> `{"moduleType": 0, "operateType": "TCP", "params": {"id": 65, "workMode": "VALUE"}}`) 59 | - Auto Fan Speed (`inv.cfgFanMode` -> `{"moduleType": 0, "operateType": "TCP", "params": {"id": 73, "fanMode": "VALUE"}}`) 60 | 61 | *Sliders (numbers)* 62 | - Max Charge Level (`bmsMaster.maxChargeSoc` -> `{"moduleType": 0, "operateType": "TCP", "params": {"id": 49, "maxChgSoc": "VALUE"}}` [30 - 100]) 63 | 64 | *Selects* 65 | - Unit Timeout (`pd.standByMode` -> `{"moduleType": 0, "operateType": "TCP", "params": {"id": 33, "standByMode": "VALUE"}}` [Never (0), 30 min (30), 1 hr (60), 2 hr (120), 6 hr (360), 12 hr (720)]) 66 | - DC (12V) Timeout (`pd.carDelayOffMin` -> `{"moduleType": 0, "operateType": "TCP", "params": {"cmdSet": 32, "id": 84, "carDelayOffMin": "VALUE"}}` [Never (0), 2 hr (120), 4 hr (240), 6 hr (360), 12 hr (720), 24 hr (1440)]) 67 | - AC Timeout (`inv.cfgStandbyMin` -> `{"moduleType": 0, "operateType": "TCP", "params": {"id": 153, "standByMins": "VALUE"}}` [Never (0), 2 hr (120), 4 hr (240), 6 hr (360), 12 hr (720), 24 hr (1440)]) 68 | 69 | 70 | -------------------------------------------------------------------------------- /docs/devices/RIVER_2.md: -------------------------------------------------------------------------------- 1 | ## RIVER_2 2 | 3 | *Sensors* 4 | - Main Battery Level (`bms_bmsStatus.soc`) 5 | - Main Design Capacity (`bms_bmsStatus.designCap`) _(disabled)_ 6 | - Main Full Capacity (`bms_bmsStatus.fullCap`) _(disabled)_ 7 | - Main Remain Capacity (`bms_bmsStatus.remainCap`) _(disabled)_ 8 | - State of Health (`bms_bmsStatus.soh`) 9 | - Battery Level (`bms_emsStatus.lcdShowSoc`) 10 | - Battery Charging State (`bms_emsStatus.chgState`) 11 | - Total In Power (`pd.wattsInSum`) (energy: _[Device Name]_ Total In Energy) 12 | - Total Out Power (`pd.wattsOutSum`) (energy: _[Device Name]_ Total Out Energy) 13 | - Solar In Current (`inv.dcInAmp`) 14 | - Solar In Voltage (`inv.dcInVol`) 15 | - AC In Power (`inv.inputWatts`) (energy: _[Device Name]_ AC In Energy) 16 | - AC Out Power (`inv.outputWatts`) (energy: _[Device Name]_ AC Out Energy) 17 | - AC In Volts (`inv.acInVol`) 18 | - AC Out Volts (`inv.invOutVol`) 19 | - Type-C In Power (`pd.typecChaWatts`) 20 | - Solar In Power (`mppt.inWatts`) (energy: _[Device Name]_ Solar In Energy) 21 | - DC Out Power (`pd.carWatts`) 22 | - Type-C Out Power (`pd.typec1Watts`) 23 | - USB Out Power (`pd.usb1Watts`) 24 | - Charge Remaining Time (`bms_emsStatus.chgRemainTime`) 25 | - Discharge Remaining Time (`bms_emsStatus.dsgRemainTime`) 26 | - Remaining Time (`pd.remainTime`) 27 | - Inv Out Temperature (`inv.outTemp`) 28 | - Cycles (`bms_bmsStatus.cycles`) 29 | - Battery Temperature (`bms_bmsStatus.temp`) 30 | - Min Cell Temperature (`bms_bmsStatus.minCellTemp`) _(disabled)_ 31 | - Max Cell Temperature (`bms_bmsStatus.maxCellTemp`) _(disabled)_ 32 | - Battery Volts (`bms_bmsStatus.vol`) _(disabled)_ 33 | - Min Cell Volts (`bms_bmsStatus.minCellVol`) _(disabled)_ 34 | - Max Cell Volts (`bms_bmsStatus.maxCellVol`) _(disabled)_ 35 | - Status 36 | 37 | *Switches* 38 | - AC Enabled (`mppt.cfgAcEnabled` -> `{"moduleType": 5, "operateType": "acOutCfg", "params": {"enabled": "VALUE", "out_voltage": -1, "out_freq": 255, "xboost": 255}}`) 39 | - AC Always On (`pd.acAutoOutConfig` -> `{"moduleType": 1, "operateType": "acAutoOutConfig", "params": {"acAutoOutConfig": "VALUE", "minAcOutSoc": 5}}`) 40 | - X-Boost Enabled (`mppt.cfgAcXboost` -> `{"moduleType": 5, "operateType": "acOutCfg", "params": {"enabled": 255, "out_voltage": -1, "out_freq": 255, "xboost": "VALUE"}}`) 41 | - DC (12V) Enabled (`pd.carState` -> `{"moduleType": 5, "operateType": "mpptCar", "params": {"enabled": "VALUE"}}`) 42 | - Backup Reserve Enabled (`pd.watchIsConfig` -> `{"moduleType": 1, "operateType": "watthConfig", "params": {"isConfig": "VALUE", "bpPowerSoc": 333300, "minDsgSoc": 0, "minChgSoc": 0}}`) 43 | 44 | *Sliders (numbers)* 45 | - Max Charge Level (`bms_emsStatus.maxChargeSoc` -> `{"moduleType": 2, "operateType": "upsConfig", "params": {"maxChgSoc": "VALUE"}}` [50 - 100]) 46 | - Min Discharge Level (`bms_emsStatus.minDsgSoc` -> `{"moduleType": 2, "operateType": "dsgCfg", "params": {"minDsgSoc": "VALUE"}}` [0 - 30]) 47 | - AC Charging Power (`mppt.cfgChgWatts` -> `{"moduleType": 5, "operateType": "acChgCfg", "params": {"chgWatts": "VALUE", "chgPauseFlag": 255}}` [100 - 360]) 48 | - Backup Reserve Level (`pd.bpPowerSoc` -> `{"moduleType": 1, "operateType": "watthConfig", "params": {"isConfig": 1, "bpPowerSoc": "VALUE", "minDsgSoc": 0, "minChgSoc": 0}}` [5 - 100]) 49 | 50 | *Selects* 51 | - DC (12V) Charge Current (`mppt.dcChgCurrent` -> `{"moduleType": 5, "operateType": "dcChgCfg", "params": {"dcChgCfg": "VALUE"}}` [4A (4000), 6A (6000), 8A (8000)]) 52 | - DC Mode (`mppt.cfgChgType` -> `{"moduleType": 5, "operateType": "chaType", "params": {"chaType": "VALUE"}}` [Auto (0), Solar Recharging (1), Car Recharging (2)]) 53 | - Screen Timeout (`mppt.scrStandbyMin` -> `{"moduleType": 5, "operateType": "lcdCfg", "params": {"brighLevel": 255, "delayOff": "VALUE"}}` [Never (0), 10 sec (10), 30 sec (30), 1 min (60), 5 min (300), 30 min (1800)]) 54 | - Unit Timeout (`mppt.powStandbyMin` -> `{"moduleType": 5, "operateType": "standby", "params": {"standbyMins": "VALUE"}}` [Never (0), 30 min (30), 1 hr (60), 2 hr (120), 4 hr (240), 6 hr (360), 12 hr (720), 24 hr (1440)]) 55 | - AC Timeout (`mppt.acStandbyMins` -> `{"moduleType": 5, "operateType": "acStandby", "params": {"standbyMins": "VALUE"}}` [Never (0), 30 min (30), 1 hr (60), 2 hr (120), 4 hr (240), 6 hr (360), 12 hr (720), 24 hr (1440)]) 56 | 57 | 58 | -------------------------------------------------------------------------------- /docs/devices/RIVER_2-Public.md: -------------------------------------------------------------------------------- 1 | ## RIVER_2 2 | 3 | *Sensors* 4 | - Main Battery Level (`bms_bmsStatus.soc`) 5 | - Main Design Capacity (`bms_bmsStatus.designCap`) _(disabled)_ 6 | - Main Full Capacity (`bms_bmsStatus.fullCap`) _(disabled)_ 7 | - Main Remain Capacity (`bms_bmsStatus.remainCap`) _(disabled)_ 8 | - State of Health (`bms_bmsStatus.soh`) 9 | - Battery Level (`bms_emsStatus.lcdShowSoc`) 10 | - Battery Charging State (`bms_emsStatus.chgState`) 11 | - Total In Power (`pd.wattsInSum`) (energy: _[Device Name]_ Total In Energy) 12 | - Total Out Power (`pd.wattsOutSum`) (energy: _[Device Name]_ Total Out Energy) 13 | - Solar In Current (`inv.dcInAmp`) 14 | - Solar In Voltage (`inv.dcInVol`) 15 | - AC In Power (`inv.inputWatts`) (energy: _[Device Name]_ AC In Energy) 16 | - AC Out Power (`inv.outputWatts`) (energy: _[Device Name]_ AC Out Energy) 17 | - AC In Volts (`inv.acInVol`) 18 | - AC Out Volts (`inv.invOutVol`) 19 | - Type-C In Power (`pd.typecChaWatts`) 20 | - Solar In Power (`mppt.inWatts`) (energy: _[Device Name]_ Solar In Energy) 21 | - DC Out Power (`pd.carWatts`) 22 | - Type-C Out Power (`pd.typec1Watts`) 23 | - USB Out Power (`pd.usb1Watts`) 24 | - Charge Remaining Time (`bms_emsStatus.chgRemainTime`) 25 | - Discharge Remaining Time (`bms_emsStatus.dsgRemainTime`) 26 | - Remaining Time (`pd.remainTime`) 27 | - Inv Out Temperature (`inv.outTemp`) 28 | - Cycles (`bms_bmsStatus.cycles`) 29 | - Battery Temperature (`bms_bmsStatus.temp`) 30 | - Min Cell Temperature (`bms_bmsStatus.minCellTemp`) _(disabled)_ 31 | - Max Cell Temperature (`bms_bmsStatus.maxCellTemp`) _(disabled)_ 32 | - Battery Volts (`bms_bmsStatus.vol`) _(disabled)_ 33 | - Min Cell Volts (`bms_bmsStatus.minCellVol`) _(disabled)_ 34 | - Max Cell Volts (`bms_bmsStatus.maxCellVol`) _(disabled)_ 35 | - Status 36 | 37 | *Switches* 38 | - AC Enabled (`mppt.cfgAcEnabled` -> `{"moduleType": 5, "operateType": "acOutCfg", "params": {"enabled": "VALUE", "out_voltage": -1, "out_freq": 255, "xboost": 255}}`) 39 | - AC Always On (`pd.acAutoOutConfig` -> `{"moduleType": 1, "operateType": "acAutoOutConfig", "params": {"acAutoOutConfig": "VALUE", "minAcOutSoc": 5}}`) 40 | - X-Boost Enabled (`mppt.cfgAcXboost` -> `{"moduleType": 5, "operateType": "acOutCfg", "params": {"enabled": 255, "out_voltage": -1, "out_freq": 255, "xboost": "VALUE"}}`) 41 | - DC (12V) Enabled (`pd.carState` -> `{"moduleType": 5, "operateType": "mpptCar", "params": {"enabled": "VALUE"}}`) 42 | - Backup Reserve Enabled (`pd.watchIsConfig` -> `{"moduleType": 1, "operateType": "watthConfig", "params": {"isConfig": "VALUE", "bpPowerSoc": 333300, "minDsgSoc": 0, "minChgSoc": 0}}`) 43 | 44 | *Sliders (numbers)* 45 | - Max Charge Level (`bms_emsStatus.maxChargeSoc` -> `{"moduleType": 2, "operateType": "upsConfig", "params": {"maxChgSoc": "VALUE"}}` [50 - 100]) 46 | - Min Discharge Level (`bms_emsStatus.minDsgSoc` -> `{"moduleType": 2, "operateType": "dsgCfg", "params": {"minDsgSoc": "VALUE"}}` [0 - 30]) 47 | - AC Charging Power (`mppt.cfgChgWatts` -> `{"moduleType": 5, "operateType": "acChgCfg", "params": {"chgWatts": "VALUE", "chgPauseFlag": 255}}` [100 - 360]) 48 | - Backup Reserve Level (`pd.bpPowerSoc` -> `{"moduleType": 1, "operateType": "watthConfig", "params": {"isConfig": 1, "bpPowerSoc": "VALUE", "minDsgSoc": 0, "minChgSoc": 0}}` [5 - 100]) 49 | 50 | *Selects* 51 | - DC (12V) Charge Current (`mppt.dcChgCurrent` -> `{"moduleType": 5, "operateType": "dcChgCfg", "params": {"dcChgCfg": "VALUE"}}` [4A (4000), 6A (6000), 8A (8000)]) 52 | - DC Mode (`mppt.cfgChgType` -> `{"moduleType": 5, "operateType": "chaType", "params": {"chaType": "VALUE"}}` [Auto (0), Solar Recharging (1), Car Recharging (2)]) 53 | - Screen Timeout (`mppt.scrStandbyMin` -> `{"moduleType": 5, "operateType": "lcdCfg", "params": {"brighLevel": 255, "delayOff": "VALUE"}}` [Never (0), 10 sec (10), 30 sec (30), 1 min (60), 5 min (300), 30 min (1800)]) 54 | - Unit Timeout (`mppt.powStandbyMin` -> `{"moduleType": 5, "operateType": "standby", "params": {"standbyMins": "VALUE"}}` [Never (0), 30 min (30), 1 hr (60), 2 hr (120), 4 hr (240), 6 hr (360), 12 hr (720), 24 hr (1440)]) 55 | - AC Timeout (`mppt.acStandbyMins` -> `{"moduleType": 5, "operateType": "acStandby", "params": {"standbyMins": "VALUE"}}` [Never (0), 30 min (30), 1 hr (60), 2 hr (120), 4 hr (240), 6 hr (360), 12 hr (720), 24 hr (1440)]) 56 | 57 | 58 | -------------------------------------------------------------------------------- /docs/devices/RIVER_2_MAX.md: -------------------------------------------------------------------------------- 1 | ## RIVER_2_MAX 2 | 3 | *Sensors* 4 | - Main Battery Level (`bms_bmsStatus.soc`) 5 | - Main Design Capacity (`bms_bmsStatus.designCap`) _(disabled)_ 6 | - Main Full Capacity (`bms_bmsStatus.fullCap`) _(disabled)_ 7 | - Main Remain Capacity (`bms_bmsStatus.remainCap`) _(disabled)_ 8 | - State of Health (`bms_bmsStatus.soh`) 9 | - Battery Level (`bms_emsStatus.lcdShowSoc`) 10 | - Battery Charging State (`bms_emsStatus.chgState`) 11 | - Total In Power (`pd.wattsInSum`) (energy: _[Device Name]_ Total In Energy) 12 | - Total Out Power (`pd.wattsOutSum`) (energy: _[Device Name]_ Total Out Energy) 13 | - Solar In Current (`inv.dcInAmp`) 14 | - Solar In Voltage (`inv.dcInVol`) 15 | - AC In Power (`inv.inputWatts`) (energy: _[Device Name]_ AC In Energy) 16 | - AC Out Power (`inv.outputWatts`) (energy: _[Device Name]_ AC Out Energy) 17 | - AC In Volts (`inv.acInVol`) 18 | - AC Out Volts (`inv.invOutVol`) 19 | - Type-C In Power (`pd.typecChaWatts`) 20 | - Solar In Power (`mppt.inWatts`) (energy: _[Device Name]_ Solar In Energy) 21 | - DC Out Power (`pd.carWatts`) 22 | - Type-C Out Power (`pd.typec1Watts`) 23 | - USB Out Power (`pd.usb1Watts`) 24 | - Charge Remaining Time (`bms_emsStatus.chgRemainTime`) 25 | - Discharge Remaining Time (`bms_emsStatus.dsgRemainTime`) 26 | - Remaining Time (`pd.remainTime`) 27 | - Inv Out Temperature (`inv.outTemp`) 28 | - Cycles (`bms_bmsStatus.cycles`) 29 | - Battery Temperature (`bms_bmsStatus.temp`) 30 | - Min Cell Temperature (`bms_bmsStatus.minCellTemp`) _(disabled)_ 31 | - Max Cell Temperature (`bms_bmsStatus.maxCellTemp`) _(disabled)_ 32 | - Battery Volts (`bms_bmsStatus.vol`) _(disabled)_ 33 | - Min Cell Volts (`bms_bmsStatus.minCellVol`) _(disabled)_ 34 | - Max Cell Volts (`bms_bmsStatus.maxCellVol`) _(disabled)_ 35 | - Status 36 | 37 | *Switches* 38 | - AC Enabled (`mppt.cfgAcEnabled` -> `{"moduleType": 5, "operateType": "acOutCfg", "params": {"enabled": "VALUE", "out_voltage": -1, "out_freq": 255, "xboost": 255}}`) 39 | - AC Always On (`pd.acAutoOutConfig` -> `{"moduleType": 1, "operateType": "acAutoOutConfig", "params": {"acAutoOutConfig": "VALUE", "minAcOutSoc": 5}}`) 40 | - X-Boost Enabled (`mppt.cfgAcXboost` -> `{"moduleType": 5, "operateType": "acOutCfg", "params": {"enabled": 255, "out_voltage": -1, "out_freq": 255, "xboost": "VALUE"}}`) 41 | - DC (12V) Enabled (`pd.carState` -> `{"moduleType": 5, "operateType": "mpptCar", "params": {"enabled": "VALUE"}}`) 42 | - Backup Reserve Enabled (`pd.watchIsConfig` -> `{"moduleType": 1, "operateType": "watthConfig", "params": {"isConfig": "VALUE", "bpPowerSoc": 333300, "minDsgSoc": 0, "minChgSoc": 0}}`) 43 | 44 | *Sliders (numbers)* 45 | - Max Charge Level (`bms_emsStatus.maxChargeSoc` -> `{"moduleType": 2, "operateType": "upsConfig", "params": {"maxChgSoc": "VALUE"}}` [50 - 100]) 46 | - Min Discharge Level (`bms_emsStatus.minDsgSoc` -> `{"moduleType": 2, "operateType": "dsgCfg", "params": {"minDsgSoc": "VALUE"}}` [0 - 30]) 47 | - AC Charging Power (`mppt.cfgChgWatts` -> `{"moduleType": 5, "operateType": "acChgCfg", "params": {"chgWatts": "VALUE", "chgPauseFlag": 255}}` [50 - 660]) 48 | - Backup Reserve Level (`pd.bpPowerSoc` -> `{"moduleType": 1, "operateType": "watthConfig", "params": {"isConfig": 1, "bpPowerSoc": "VALUE", "minDsgSoc": 0, "minChgSoc": 0}}` [5 - 100]) 49 | 50 | *Selects* 51 | - DC (12V) Charge Current (`mppt.dcChgCurrent` -> `{"moduleType": 5, "operateType": "dcChgCfg", "params": {"dcChgCfg": "VALUE"}}` [4A (4000), 6A (6000), 8A (8000)]) 52 | - DC Mode (`mppt.cfgChgType` -> `{"moduleType": 5, "operateType": "chaType", "params": {"chaType": "VALUE"}}` [Auto (0), Solar Recharging (1), Car Recharging (2)]) 53 | - Screen Timeout (`mppt.scrStandbyMin` -> `{"moduleType": 5, "operateType": "lcdCfg", "params": {"brighLevel": 255, "delayOff": "VALUE"}}` [Never (0), 10 sec (10), 30 sec (30), 1 min (60), 5 min (300), 30 min (1800)]) 54 | - Unit Timeout (`mppt.powStandbyMin` -> `{"moduleType": 5, "operateType": "standby", "params": {"standbyMins": "VALUE"}}` [Never (0), 30 min (30), 1 hr (60), 2 hr (120), 4 hr (240), 6 hr (360), 12 hr (720), 24 hr (1440)]) 55 | - AC Timeout (`mppt.acStandbyMins` -> `{"moduleType": 5, "operateType": "acStandby", "params": {"standbyMins": "VALUE"}}` [Never (0), 30 min (30), 1 hr (60), 2 hr (120), 4 hr (240), 6 hr (360), 12 hr (720), 24 hr (1440)]) 56 | 57 | 58 | -------------------------------------------------------------------------------- /docs/devices/RIVER_2_Max-Public.md: -------------------------------------------------------------------------------- 1 | ## RIVER_2_Max 2 | 3 | *Sensors* 4 | - Main Battery Level (`bms_bmsStatus.soc`) 5 | - Main Design Capacity (`bms_bmsStatus.designCap`) _(disabled)_ 6 | - Main Full Capacity (`bms_bmsStatus.fullCap`) _(disabled)_ 7 | - Main Remain Capacity (`bms_bmsStatus.remainCap`) _(disabled)_ 8 | - State of Health (`bms_bmsStatus.soh`) 9 | - Battery Level (`bms_emsStatus.lcdShowSoc`) 10 | - Battery Charging State (`bms_emsStatus.chgState`) 11 | - Total In Power (`pd.wattsInSum`) (energy: _[Device Name]_ Total In Energy) 12 | - Total Out Power (`pd.wattsOutSum`) (energy: _[Device Name]_ Total Out Energy) 13 | - Solar In Current (`inv.dcInAmp`) 14 | - Solar In Voltage (`inv.dcInVol`) 15 | - AC In Power (`inv.inputWatts`) (energy: _[Device Name]_ AC In Energy) 16 | - AC Out Power (`inv.outputWatts`) (energy: _[Device Name]_ AC Out Energy) 17 | - AC In Volts (`inv.acInVol`) 18 | - AC Out Volts (`inv.invOutVol`) 19 | - Type-C In Power (`pd.typecChaWatts`) 20 | - Solar In Power (`mppt.inWatts`) (energy: _[Device Name]_ Solar In Energy) 21 | - DC Out Power (`pd.carWatts`) 22 | - Type-C Out Power (`pd.typec1Watts`) 23 | - USB Out Power (`pd.usb1Watts`) 24 | - Charge Remaining Time (`bms_emsStatus.chgRemainTime`) 25 | - Discharge Remaining Time (`bms_emsStatus.dsgRemainTime`) 26 | - Remaining Time (`pd.remainTime`) 27 | - Inv Out Temperature (`inv.outTemp`) 28 | - Cycles (`bms_bmsStatus.cycles`) 29 | - Battery Temperature (`bms_bmsStatus.temp`) 30 | - Min Cell Temperature (`bms_bmsStatus.minCellTemp`) _(disabled)_ 31 | - Max Cell Temperature (`bms_bmsStatus.maxCellTemp`) _(disabled)_ 32 | - Battery Volts (`bms_bmsStatus.vol`) _(disabled)_ 33 | - Min Cell Volts (`bms_bmsStatus.minCellVol`) _(disabled)_ 34 | - Max Cell Volts (`bms_bmsStatus.maxCellVol`) _(disabled)_ 35 | - Status 36 | 37 | *Switches* 38 | - AC Enabled (`mppt.cfgAcEnabled` -> `{"moduleType": 5, "operateType": "acOutCfg", "params": {"enabled": "VALUE", "out_voltage": -1, "out_freq": 255, "xboost": 255}}`) 39 | - AC Always On (`pd.acAutoOutConfig` -> `{"moduleType": 1, "operateType": "acAutoOutConfig", "params": {"acAutoOutConfig": "VALUE", "minAcOutSoc": 5}}`) 40 | - X-Boost Enabled (`mppt.cfgAcXboost` -> `{"moduleType": 5, "operateType": "acOutCfg", "params": {"enabled": 255, "out_voltage": -1, "out_freq": 255, "xboost": "VALUE"}}`) 41 | - DC (12V) Enabled (`pd.carState` -> `{"moduleType": 5, "operateType": "mpptCar", "params": {"enabled": "VALUE"}}`) 42 | - Backup Reserve Enabled (`pd.watchIsConfig` -> `{"moduleType": 1, "operateType": "watthConfig", "params": {"isConfig": "VALUE", "bpPowerSoc": 333300, "minDsgSoc": 0, "minChgSoc": 0}}`) 43 | 44 | *Sliders (numbers)* 45 | - Max Charge Level (`bms_emsStatus.maxChargeSoc` -> `{"moduleType": 2, "operateType": "upsConfig", "params": {"maxChgSoc": "VALUE"}}` [50 - 100]) 46 | - Min Discharge Level (`bms_emsStatus.minDsgSoc` -> `{"moduleType": 2, "operateType": "dsgCfg", "params": {"minDsgSoc": "VALUE"}}` [0 - 30]) 47 | - AC Charging Power (`mppt.cfgChgWatts` -> `{"moduleType": 5, "operateType": "acChgCfg", "params": {"chgWatts": "VALUE", "chgPauseFlag": 255}}` [50 - 660]) 48 | - Backup Reserve Level (`pd.bpPowerSoc` -> `{"moduleType": 1, "operateType": "watthConfig", "params": {"isConfig": 1, "bpPowerSoc": "VALUE", "minDsgSoc": 0, "minChgSoc": 0}}` [5 - 100]) 49 | 50 | *Selects* 51 | - DC (12V) Charge Current (`mppt.dcChgCurrent` -> `{"moduleType": 5, "operateType": "dcChgCfg", "params": {"dcChgCfg": "VALUE"}}` [4A (4000), 6A (6000), 8A (8000)]) 52 | - DC Mode (`mppt.cfgChgType` -> `{"moduleType": 5, "operateType": "chaType", "params": {"chaType": "VALUE"}}` [Auto (0), Solar Recharging (1), Car Recharging (2)]) 53 | - Screen Timeout (`mppt.scrStandbyMin` -> `{"moduleType": 5, "operateType": "lcdCfg", "params": {"brighLevel": 255, "delayOff": "VALUE"}}` [Never (0), 10 sec (10), 30 sec (30), 1 min (60), 5 min (300), 30 min (1800)]) 54 | - Unit Timeout (`mppt.powStandbyMin` -> `{"moduleType": 5, "operateType": "standby", "params": {"standbyMins": "VALUE"}}` [Never (0), 30 min (30), 1 hr (60), 2 hr (120), 4 hr (240), 6 hr (360), 12 hr (720), 24 hr (1440)]) 55 | - AC Timeout (`mppt.acStandbyMins` -> `{"moduleType": 5, "operateType": "acStandby", "params": {"standbyMins": "VALUE"}}` [Never (0), 30 min (30), 1 hr (60), 2 hr (120), 4 hr (240), 6 hr (360), 12 hr (720), 24 hr (1440)]) 56 | 57 | 58 | -------------------------------------------------------------------------------- /custom_components/ecoflow_cloud/devices/internal/proto/ef_smartmeter.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | message SmartMeterRuntimePropertyUpload { 4 | optional int32 display_property_full_upload_period = 293; 5 | optional int32 display_property_incremental_upload_period = 294; 6 | optional int32 runtime_property_full_upload_period = 295; 7 | optional int32 runtime_property_incremental_upload_period = 296; 8 | } 9 | 10 | message SmartMeterDisplayPropertyUpload { 11 | optional int32 utc_timezone = 133; 12 | optional string utc_timezone_id = 134; 13 | optional uint32 utc_set_mode = 135; //bool 14 | optional float totalPower = 515; 15 | 16 | optional float unknown618 = 618; 17 | optional uint32 unknown619 = 619; //bool? 18 | 19 | repeated string unknown627 = 627; 20 | repeated string unknown728 = 728; 21 | 22 | optional uint32 unknown729 = 729; 23 | optional uint32 unknown732 = 732; 24 | optional uint32 unknown733 = 733; 25 | optional uint32 unknown762 = 762; 26 | optional uint32 unknown763 = 763; 27 | optional uint32 unknown764 = 764; 28 | 29 | optional float voltageL3 = 771; 30 | optional float powerL3 = 772; 31 | optional SmartMeterEnergyArray energy = 773; 32 | optional float currentL1 = 784; // ?? 33 | optional float voltageL1 = 956; 34 | optional float voltageL2 = 957; 35 | optional float currentL3 = 958; // ?? 36 | optional float currentL2 = 959; // ?? 37 | optional float powerL1 = 962; 38 | optional float powerL2 = 963; 39 | //optional uint32 unknown = 984; 40 | } 41 | 42 | message SmartMeterEnergyArray { 43 | optional float energyL1daily = 1; //Nettoverbrauch L1 44 | optional float energyL2daily = 2; //Nettoverbrauch L2 45 | optional float energyL3daily = 3; //Nettoverbrauch L3 46 | optional float lifeTimeEnergyConsumption = 4; // Lebenszeit Verbrauch 47 | optional float lifeTimeEnergyDelivery = 6; // Lebenszeit Einspeisung 48 | optional float netEnergyConsumption = 7; // Nettoverbrauch 49 | } 50 | 51 | message SmartMeterSetMessage { 52 | repeated SmartMeterSetHeader msg = 1; 53 | } 54 | 55 | message SmartMeterSetValue { 56 | optional int32 value = 1; 57 | optional int32 value2 = 2; 58 | } 59 | 60 | message SmartMeterSetHeader { 61 | optional bytes pdata = 1; 62 | optional int32 src = 2; 63 | optional int32 dest = 3; 64 | optional int32 d_src = 4; 65 | optional int32 d_dest = 5; 66 | optional int32 enc_type = 6; 67 | optional int32 check_type = 7; 68 | optional int32 cmd_func = 8; 69 | optional int32 cmd_id = 9; 70 | optional int32 data_len = 10; 71 | optional int32 need_ack = 11; 72 | optional int32 is_ack = 12; 73 | optional int32 seq = 14; 74 | optional int32 product_id = 15; 75 | optional int32 version = 16; 76 | optional int32 payload_ver = 17; 77 | optional int32 time_snap = 18; 78 | optional int32 is_rw_cmd = 19; 79 | optional int32 is_queue = 20; 80 | optional int32 ack_type = 21; 81 | optional string code = 22; 82 | optional string from_ = 23; 83 | optional string module_sn = 24; 84 | optional string device_sn = 25; 85 | } 86 | 87 | message SmartMeterSentDisplayPropertyUpload { 88 | SmartMeterSetHeader3 header = 1; 89 | } 90 | 91 | message SmartMeterSentRuntimePropertyUpload { 92 | SmartMeterSetHeader4 header = 1; 93 | } 94 | 95 | message SmartMeterSetHeader4 { 96 | optional bytes pdata = 1; 97 | optional int32 src = 2; 98 | optional int32 dest = 3; 99 | optional int32 d_src = 4; 100 | optional int32 d_dest = 5; 101 | optional int32 cmd_func = 8; 102 | optional int32 cmd_id = 9; 103 | optional int32 data_len = 10; 104 | optional int32 need_ack = 11; 105 | optional int32 is_ack = 12; 106 | optional int32 seq = 14; 107 | optional int32 product_id = 15; 108 | optional int32 version = 16; 109 | optional int32 payload_ver = 17; 110 | } 111 | 112 | message SmartMeterSetHeader3 { 113 | optional bytes pdata = 1; 114 | optional int32 src = 2; 115 | optional int32 dest = 3; 116 | optional int32 d_src = 4; 117 | optional int32 d_dest = 5; 118 | optional int32 cmd_func = 8; 119 | optional int32 cmd_id = 9; 120 | optional int32 data_len = 10; 121 | optional int32 need_ack = 11; 122 | optional int32 is_ack = 12; 123 | optional int32 seq = 14; 124 | optional int32 product_id = 15; 125 | optional int32 version = 16; 126 | optional int32 payload_ver = 17; 127 | } 128 | -------------------------------------------------------------------------------- /custom_components/ecoflow_cloud/devices/data_holder.py: -------------------------------------------------------------------------------- 1 | import logging 2 | from collections.abc import Callable 3 | from typing import Any, TypeVar 4 | 5 | import json 6 | import jsonpath_ng.ext as jp 7 | from homeassistant.util import dt 8 | 9 | _LOGGER = logging.getLogger(__name__) 10 | 11 | _T = TypeVar("_T") 12 | 13 | 14 | class BoundFifoList(list): 15 | def __init__(self, maxlen=20) -> None: 16 | super().__init__() 17 | self.maxlen = maxlen 18 | 19 | def append(self, __object: _T) -> None: 20 | super().insert(0, __object) 21 | while len(self) >= self.maxlen: 22 | self.pop() 23 | 24 | 25 | class EcoflowDataHolder: 26 | def __init__( 27 | self, 28 | extract_quota_message: Callable[[dict[str, Any]], dict[str, Any]], 29 | module_sn: str | None = None, 30 | collect_raw: bool = False, 31 | ): 32 | self.__collect_raw = collect_raw 33 | self.extract_quota_message = extract_quota_message 34 | self.set = BoundFifoList[dict[str, Any]]() 35 | self.set_reply = BoundFifoList[dict[str, Any]]() 36 | self.set_reply_time = dt.utcnow().replace( 37 | year=2000, month=1, day=1, hour=0, minute=0, second=0 38 | ) 39 | 40 | self.module_sn = module_sn 41 | 42 | self.get = BoundFifoList[dict[str, Any]]() 43 | self.get_reply = BoundFifoList[dict[str, Any]]() 44 | self.get_reply_time = dt.utcnow().replace( 45 | year=2000, month=1, day=1, hour=0, minute=0, second=0 46 | ) 47 | 48 | self.params = dict[str, Any]() 49 | self.params_time = dt.utcnow().replace( 50 | year=2000, month=1, day=1, hour=0, minute=0, second=0 51 | ) 52 | 53 | self.status = dict[str, Any]() 54 | self.status_time = dt.utcnow().replace( 55 | year=2000, month=1, day=1, hour=0, minute=0, second=0 56 | ) 57 | 58 | self.raw_data = BoundFifoList[dict[str, Any]]() 59 | 60 | def last_received_time(self): 61 | return max( 62 | self.status_time, 63 | self.params_time, 64 | # 1. get_reply can receive '"message": "The device is not online" 65 | # 2. if device is online - get_reply message will update params, so param_time will be updated as well 66 | # , self.get_reply_time, self.set_reply_time 67 | ) 68 | 69 | def add_set_message(self, msg: dict[str, Any]): 70 | self.set.append(msg) 71 | 72 | def add_set_reply_message(self, msg: dict[str, Any]): 73 | self.set_reply.append(msg) 74 | self.set_reply_time = dt.utcnow() 75 | 76 | def add_get_message(self, msg: dict[str, Any]): 77 | self.get.append(msg) 78 | 79 | def add_get_reply_message(self, msg: dict[str, Any]): 80 | try: 81 | result = self.extract_quota_message(msg) 82 | except Exception as error: 83 | _LOGGER.warning("Error extracting quota message: %s", error) 84 | result = None 85 | 86 | if result is not None: 87 | self.update_data(result) 88 | 89 | self.get_reply.append(msg) 90 | self.get_reply_time = dt.utcnow() 91 | 92 | def update_to_target_state(self, target_state: dict[str, Any]): 93 | # key can be xpath! 94 | for key, value in target_state.items(): 95 | jp.parse(key).update(self.params, value) 96 | 97 | self.params_time = dt.utcnow() 98 | 99 | def update_status(self, raw: dict[str, Any]): 100 | if raw is None or "params" not in raw or "status" not in raw["params"]: 101 | _LOGGER.warning("No status in raw: %s", json.dumps(raw)) 102 | return 103 | self.status.update({"status": int(raw["params"]["status"])}) 104 | self.status_time = dt.utcnow() 105 | 106 | def update_data(self, raw: dict[str, Any]): 107 | if raw is not None: 108 | self.__add_raw_data(raw) 109 | try: 110 | if self.module_sn is not None: 111 | if "moduleSn" not in raw: 112 | return 113 | if raw["moduleSn"] != self.module_sn: 114 | return 115 | if "params" in raw: 116 | self.params.update(raw["params"]) 117 | self.params_time = dt.utcnow() 118 | 119 | except Exception as error: 120 | _LOGGER.error("Error updating data: %s", error) 121 | 122 | def __add_raw_data(self, raw: dict[str, Any]): 123 | if self.__collect_raw: 124 | self.raw_data.append(raw) 125 | -------------------------------------------------------------------------------- /docs/devices/DELTA_PRO_3.md: -------------------------------------------------------------------------------- 1 | ## DELTA_PRO_3 2 | 3 | *Sensors* 4 | - Main Battery Level (`bms_batt_soc`) 5 | - Main Design Capacity (`bms_design_cap`) _(disabled)_ 6 | - Main Full Capacity (`bms_full_cap_mah`) _(disabled)_ 7 | - Main Remain Capacity (`bms_remain_cap_mah`) _(disabled)_ 8 | - State of Health (`bms_batt_soh`) 9 | - Cycles (`cycles`) 10 | - Battery Volts (`bms_batt_vol`) _(disabled)_ 11 | - Min Cell Volts (`bms_min_cell_vol`) _(disabled)_ 12 | - Max Cell Volts (`bms_max_cell_vol`) _(disabled)_ 13 | - Main Battery Current (`bms_batt_amp`) _(disabled)_ 14 | - Max Cell Temperature (`bms_max_cell_temp`) _(disabled)_ 15 | - Min Cell Temperature (`bms_min_cell_temp`) _(disabled)_ 16 | - Battery Temperature (`bms_max_mos_temp`) 17 | - Charge Remaining Time (`bms_chg_rem_time`) 18 | - Discharge Remaining Time (`bms_dsg_rem_time`) 19 | - Battery Level (`cms_batt_soc`) 20 | - Total In Power (`pow_in_sum_w`) 21 | - Total Out Power (`pow_out_sum_w`) 22 | - AC In Power (`pow_get_ac_in`) 23 | - AC Out Power (`pow_get_ac`) 24 | - AC HV Output Power (`pow_get_ac_hv_out`) 25 | - AC LV Output Power (`pow_get_ac_lv_out`) 26 | - AC In Volts (`plug_in_info_ac_in_vol`) 27 | - AC In Current (`plug_in_info_ac_in_amp`) 28 | - 12V DC Output Power (`pow_get_12v`) 29 | - 24V DC Output Power (`pow_get_24v`) 30 | - 12V DC Output Voltage (`pow_get_12v_vol`) 31 | - 24V DC Output Voltage (`pow_get_24v_vol`) 32 | - Solar High Voltage Input Power (`pow_get_pv_h`) 33 | - Solar Low Voltage Input Power (`pow_get_pv_l`) 34 | - Solar HV Input Voltage (`pow_get_pv_h_vol`) 35 | - Solar LV Input Voltage (`pow_get_pv_l_vol`) 36 | - Solar HV Input Current (`pow_get_pv_h_amp`) 37 | - Solar LV Input Current (`pow_get_pv_l_amp`) 38 | - USB QC (1) Out Power (`pow_get_qcusb1`) 39 | - USB QC (2) Out Power (`pow_get_qcusb2`) 40 | - Type-C (1) Out Power (`pow_get_typec1`) 41 | - Type-C (2) Out Power (`pow_get_typec2`) 42 | - 5P8 Power I/O Port Power (`pow_get_5p8`) 43 | - 4P8 Extra Battery Port 1 Power (`pow_get_4p8_1`) 44 | - 4P8 Extra Battery Port 2 Power (`pow_get_4p8_2`) 45 | - AC Output Frequency (`ac_out_freq`) 46 | - Max Charge SOC Setting (`cms_max_chg_soc`) 47 | - Min Discharge SOC Setting (`cms_min_dsg_soc`) 48 | - Total Charge Energy (`accuChgEnergy`) 49 | - Total Discharge Energy (`accuDsgEnergy`) 50 | - Status 51 | 52 | *Switches* 53 | - Beeper (`en_beep` -> `{"moduleType": 0, "operateType": "TCP", "params": {"id": 38, "enBeep": "VALUE"}}`) 54 | - AC HV Output Enabled (`cfg_hv_ac_out_open` -> `{"moduleType": 0, "operateType": "TCP", "params": {"id": 66, "cfgHvAcOutOpen": "VALUE"}}`) 55 | - AC LV Output Enabled (`cfg_lv_ac_out_open` -> `{"moduleType": 0, "operateType": "TCP", "params": {"id": 66, "cfgLvAcOutOpen": "VALUE"}}`) 56 | - 12V DC Output Enabled (`cfg_dc_12v_out_open` -> `{"moduleType": 0, "operateType": "TCP", "params": {"id": 81, "cfgDc12vOutOpen": "VALUE"}}`) 57 | - 24V DC Output Enabled (`cfg_dc_24v_out_open` -> `{"moduleType": 0, "operateType": "TCP", "params": {"id": 81, "cfgDc24vOutOpen": "VALUE"}}`) 58 | - X-Boost Enabled (`xboost_en` -> `{"moduleType": 0, "operateType": "TCP", "params": {"id": 66, "xboostEn": "VALUE"}}`) 59 | - AC Energy Saving Enabled (`ac_energy_saving_open` -> `{"moduleType": 0, "operateType": "TCP", "params": {"id": 95, "acEnergySavingOpen": "VALUE"}}`) 60 | - GFCI Protection Enabled (`llc_gfci_flag` -> `{"moduleType": 0, "operateType": "TCP", "params": {"id": 153, "llcGFCIFlag": "VALUE"}}`) 61 | 62 | *Sliders (numbers)* 63 | - Max Charge Level (`cms_max_chg_soc` -> `{"moduleType": 0, "operateType": "TCP", "params": {"id": 49, "cmsMaxChgSoc": "VALUE"}}` [50 - 100]) 64 | - Min Discharge Level (`cms_min_dsg_soc` -> `{"moduleType": 0, "operateType": "TCP", "params": {"id": 51, "cmsMinDsgSoc": "VALUE"}}` [0 - 30]) 65 | - AC Charging Power (`plug_in_info_ac_in_chg_pow_max` -> `{"moduleType": 0, "operateType": "TCP", "params": {"id": 69, "plugInInfoAcInChgPowMax": "VALUE"}}` [200 - 3000]) 66 | 67 | *Selects* 68 | - Screen Timeout (`screen_off_time` -> `{"moduleType": 0, "operateType": "TCP", "params": {"screenOffTime": "VALUE", "id": 39}}` [Never (0), 10 sec (10), 30 sec (30), 1 min (60), 5 min (300), 30 min (1800)]) 69 | - AC Timeout (`ac_standby_time` -> `{"moduleType": 0, "operateType": "TCP", "params": {"acStandbyTime": "VALUE", "id": 10}}` [Never (0), 30 min (30), 1 hr (60), 2 hr (120), 4 hr (240), 6 hr (360), 12 hr (720), 24 hr (1440)]) 70 | - DC Timeout (`dc_standby_time` -> `{"moduleType": 0, "operateType": "TCP", "params": {"dcStandbyTime": "VALUE", "id": 33}}` [Never (0), 30 min (30), 1 hr (60), 2 hr (120), 6 hr (360), 12 hr (720)]) 71 | - AC Output Type (`plug_in_info_ac_out_type` -> `{"moduleType": 0, "operateType": "TCP", "params": {"plugInInfoAcOutType": "VALUE", "id": 59}}` [HV+LV (0), HV Only (1), LV Only (2)]) 72 | 73 | 74 | -------------------------------------------------------------------------------- /custom_components/ecoflow_cloud/devices/registry.py: -------------------------------------------------------------------------------- 1 | from collections import OrderedDict 2 | from typing import Type 3 | 4 | from custom_components.ecoflow_cloud.devices import BaseDevice, DiagnosticDevice 5 | 6 | from .internal import ( 7 | delta2 as internal_delta2, 8 | delta2_max as internal_delta2_max, 9 | delta3 as internal_delta3, 10 | delta_max as internal_delta_max, 11 | delta_mini as internal_delta_mini, 12 | delta_pro as internal_delta_pro, 13 | delta_pro_3 as internal_delta_pro_3, 14 | glacier as internal_glacier, 15 | powerstream as internal_powerstream, 16 | river2 as internal_river2, 17 | river2_max as internal_river2_max, 18 | river2_pro as internal_river2_pro, 19 | river3 as internal_river3, 20 | river_max as internal_river_max, 21 | river_mini as internal_river_mini, 22 | river_pro as internal_river_pro, 23 | smart_meter as internal_smart_meter, 24 | stream_ac as internal_stream_ac, 25 | wave2 as internal_wave2, 26 | ) 27 | from .public import ( 28 | delta2 as public_delta2, 29 | delta2_max as public_delta2_max, 30 | delta3 as public_delta3, 31 | delta_max as public_delta_max, 32 | delta_pro as public_delta_pro, 33 | delta_pro_3 as public_delta_pro_3, 34 | delta_pro_ultra as public_delta_pro_ultra, 35 | powerkit as public_powerkit, 36 | powerstream as public_powerstream, 37 | river2 as public_river2, 38 | river2_max as public_river2_max, 39 | river2_pro as public_river2_pro, 40 | smart_home_panel as public_smart_home_panel, 41 | smart_home_panel_2 as public_smart_home_panel_2, 42 | smart_meter as public_smart_meter, 43 | smart_plug as public_smart_plug, 44 | stream_ac as public_stream_ac, 45 | stream_microinverter as public_stream_microinverter, 46 | wave2 as public_wave2, 47 | powerocean as public_powerocean, 48 | ) 49 | 50 | devices: OrderedDict[str, Type[BaseDevice]] = OrderedDict[str, Type[BaseDevice]]( 51 | { 52 | "DELTA_2": internal_delta2.Delta2, 53 | "DELTA_3": internal_delta3.Delta3, 54 | "RIVER_2": internal_river2.River2, 55 | "RIVER_2_MAX": internal_river2_max.River2Max, 56 | "RIVER_2_PRO": internal_river2_pro.River2Pro, 57 | "RIVER_3": internal_river3.River3, 58 | "DELTA_PRO": internal_delta_pro.DeltaPro, 59 | "DELTA_PRO_3": internal_delta_pro_3.DeltaPro3, 60 | "RIVER_MAX": internal_river_max.RiverMax, 61 | "RIVER_PRO": internal_river_pro.RiverPro, 62 | "RIVER_MINI": internal_river_mini.RiverMini, 63 | "DELTA_MINI": internal_delta_mini.DeltaMini, 64 | "DELTA_MAX": internal_delta_max.DeltaMax, 65 | "DELTA_2_MAX": internal_delta2_max.Delta2Max, 66 | "POWERSTREAM": internal_powerstream.PowerStream, 67 | "GLACIER": internal_glacier.Glacier, 68 | "WAVE_2": internal_wave2.Wave2, 69 | "SMART_METER": internal_smart_meter.SmartMeter, 70 | "STREAM_AC": internal_stream_ac.StreamAC, 71 | "STREAM_PRO": internal_stream_ac.StreamAC, 72 | "STREAM_ULTRA": internal_stream_ac.StreamAC, 73 | "DIAGNOSTIC": DiagnosticDevice, 74 | } 75 | ) 76 | 77 | device_by_product: OrderedDict[str, Type[BaseDevice]] = OrderedDict[ 78 | str, Type[BaseDevice] 79 | ]( 80 | { 81 | "DELTA Max": public_delta_max.DeltaMax, 82 | "DELTA Pro": public_delta_pro.DeltaPro, 83 | "DELTA Pro Ultra": public_delta_pro_ultra.DeltaProUltra, 84 | "DELTA 2": public_delta2.Delta2, 85 | "DELTA 2 Max": public_delta2_max.Delta2Max, 86 | "DELTA 3": public_delta3.Delta3, 87 | "RIVER 2": public_river2.River2, 88 | "RIVER 2 Max": public_river2_max.River2Max, 89 | "RIVER 2 Pro": public_river2_pro.River2Pro, 90 | "Smart Plug": public_smart_plug.SmartPlug, 91 | "PowerStream": public_powerstream.PowerStream, 92 | "WAVE 2": public_wave2.Wave2, 93 | "Delta Pro 3": public_delta_pro_3.DeltaPro3, 94 | "Power Kits": public_powerkit.PowerKit, 95 | "Smart Meter": public_smart_meter.SmartMeter, 96 | "Stream AC": public_stream_ac.StreamAC, 97 | "Stream PRO": public_stream_ac.StreamAC, 98 | "Stream Ultra": public_stream_ac.StreamAC, 99 | "Stream Microinverter" : public_stream_microinverter.StreamMicroinveter, 100 | "Smart Home Panel": public_smart_home_panel.SmartHomePanel, 101 | "Smart Home Panel 2": public_smart_home_panel_2.SmartHomePanel2, 102 | "Power Ocean": public_powerocean.PowerOcean, 103 | "Diagnostic": DiagnosticDevice, 104 | } 105 | ) 106 | 107 | device_support_sub_devices = ["Power Kits"] 108 | -------------------------------------------------------------------------------- /docs/devices/POWERSTREAM.md: -------------------------------------------------------------------------------- 1 | ## POWERSTREAM 2 | 3 | *Sensors* 4 | - ESP Temperature (`20_1.espTempsensor`) 5 | - Solar 1 Watts (`20_1.pv1InputWatts`) 6 | - Solar 1 Input Potential (`20_1.pv1InputVolt`) 7 | - Solar 1 Op Potential (`20_1.pv1OpVolt`) 8 | - Solar 1 Current (`20_1.pv1InputCur`) 9 | - Solar 1 Temperature (`20_1.pv1Temp`) 10 | - Solar 1 Relay Status (`20_1.pv1RelayStatus`) 11 | - Solar 1 Error Code (`20_1.pv1ErrCode`) _(disabled)_ 12 | - Solar 1 Warning Code (`20_1.pv1WarnCode`) _(disabled)_ 13 | - Solar 1 Status (`20_1.pv1Statue`) _(disabled)_ 14 | - Solar 2 Watts (`20_1.pv2InputWatts`) 15 | - Solar 2 Input Potential (`20_1.pv2InputVolt`) 16 | - Solar 2 Op Potential (`20_1.pv2OpVolt`) 17 | - Solar 2 Current (`20_1.pv2InputCur`) 18 | - Solar 2 Temperature (`20_1.pv2Temp`) 19 | - Solar 2 Relay Status (`20_1.pv2RelayStatus`) 20 | - Solar 2 Error Code (`20_1.pv2ErrCode`) _(disabled)_ 21 | - Solar 2 Warning Code (`20_1.pv2WarningCode`) _(disabled)_ 22 | - Solar 2 Status (`20_1.pv2Statue`) _(disabled)_ 23 | - Battery Type (`20_1.bpType`) _(disabled)_ 24 | - Battery Charge (`20_1.batSoc`) 25 | - Battery Input Watts (`20_1.batInputWatts`) 26 | - Battery Input Potential (`20_1.batInputVolt`) 27 | - Battery Op Potential (`20_1.batOpVolt`) 28 | - Battery Input Current (`20_1.batInputCur`) 29 | - Battery Temperature (`20_1.batTemp`) 30 | - Charge Time (`20_1.chgRemainTime`) 31 | - Discharge Time (`20_1.dsgRemainTime`) 32 | - Battery Error Code (`20_1.batErrCode`) _(disabled)_ 33 | - Battery Warning Code (`20_1.batWarningCode`) _(disabled)_ 34 | - Battery Status (`20_1.batStatue`) _(disabled)_ 35 | - LLC Input Potential (`20_1.llcInputVolt`) _(disabled)_ 36 | - LLC Op Potential (`20_1.llcOpVolt`) _(disabled)_ 37 | - LLC Temperature (`20_1.llcTemp`) 38 | - LLC Error Code (`20_1.llcErrCode`) _(disabled)_ 39 | - LLC Warning Code (`20_1.llcWarningCode`) _(disabled)_ 40 | - LLC Status (`20_1.llcStatue`) _(disabled)_ 41 | - Inverter On/Off Status (`20_1.invOnOff`) 42 | - Inverter Output Watts (`20_1.invOutputWatts`) 43 | - Inverter Output Potential (`20_1.invInputVolt`) _(disabled)_ 44 | - Inverter Op Potential (`20_1.invOpVolt`) 45 | - Inverter Output Current (`20_1.invOutputCur`) 46 | - Inverter Frequency (`20_1.invFreq`) 47 | - Inverter Temperature (`20_1.invTemp`) 48 | - Inverter Relay Status (`20_1.invRelayStatus`) 49 | - Inverter Error Code (`20_1.invErrCode`) _(disabled)_ 50 | - Inverter Warning Code (`20_1.invWarnCode`) _(disabled)_ 51 | - Inverter Status (`20_1.invStatue`) _(disabled)_ 52 | - Other Loads (`20_1.permanentWatts`) 53 | - Smart Plug Loads (`20_1.dynamicWatts`) 54 | - Rated Power (`20_1.ratedPower`) 55 | - Lower Battery Limit (`20_1.lowerLimit`) _(disabled)_ 56 | - Upper Battery Limit (`20_1.upperLimit`) _(disabled)_ 57 | - Wireless Error Code (`20_1.wirelessErrCode`) _(disabled)_ 58 | - Wireless Warning Code (`20_1.wirelessWarnCode`) _(disabled)_ 59 | - LED Brightness (`20_1.invBrightness`) _(disabled)_ 60 | - Heartbeat Frequency (`20_1.heartbeatFrequency`) _(disabled)_ 61 | - PV1 Today Energy Total (`254_32.watthPv1`) 62 | - PV2 Today Energy Total (`254_32.watthPv2`) 63 | - From Battery Today Energy Total (`254_32.watthFromBattery`) 64 | - To Battery Today Energy Total (`254_32.watthToBattery`) 65 | - To Smart Plugs Today Energy Total (`254_32.watthToSmartPlugs`) 66 | - Status 67 | 68 | *Switches* 69 | - Feed-in Control (`20_1.feedProtect` -> `{"PowerStreamSendHeaderMsg": {"msg": [{"pdata": {"PowerStreamSetValue": {"value": 6666}}, "src": 32, "dest": 53, "d_src": 1, "d_dest": 1, "check_type": 3, "cmd_func": 20, "cmd_id": 143, "data_len": 3, "need_ack": 1, "version": 19, "payload_ver": 1, "from_": "HomeAssistant", "device_sn": "SN"}]}}`) 70 | 71 | *Sliders (numbers)* 72 | - Max Charge Level (`20_1.upperLimit` -> `{"PowerStreamSendHeaderMsg": {"msg": [{"pdata": {"PowerStreamBatUpperPack": {"upper_limit": 6666}}, "src": 32, "dest": 53, "d_src": 1, "d_dest": 1, "check_type": 3, "cmd_func": 20, "cmd_id": 133, "data_len": 3, "need_ack": 1, "version": 19, "payload_ver": 1, "from_": "HomeAssistant", "device_sn": "SN"}]}}` [50 - 100]) 73 | - Min Discharge Level (`20_1.lowerLimit` -> `{"PowerStreamSendHeaderMsg": {"msg": [{"pdata": {"PowerStreamBatLowerPack": {"lower_limit": 6666}}, "src": 32, "dest": 53, "d_src": 1, "d_dest": 1, "check_type": 3, "cmd_func": 20, "cmd_id": 132, "data_len": 3, "need_ack": 1, "version": 19, "payload_ver": 1, "from_": "HomeAssistant", "device_sn": "SN"}]}}` [0 - 30]) 74 | 75 | *Selects* 76 | - Power supply mode (`20_1.supplyPriority` -> `{"PowerStreamSendHeaderMsg": {"msg": [{"pdata": {"PowerStreamSupplyPriorityPack": {"supply_priority": 6666}}, "src": 32, "dest": 53, "d_src": 1, "d_dest": 1, "check_type": 3, "cmd_func": 20, "cmd_id": 130, "data_len": 3, "need_ack": 1, "version": 19, "payload_ver": 1, "from_": "HomeAssistant", "device_sn": "SN"}]}}` [Prioritize power supply (0), Prioritize power storage (1)]) 77 | 78 | 79 | -------------------------------------------------------------------------------- /custom_components/ecoflow_cloud/devices/public/smart_meter.py: -------------------------------------------------------------------------------- 1 | from typing import Sequence 2 | from ...api import EcoflowApiClient 3 | from ...sensor import QuotaStatusSensorEntity 4 | from ...devices import const, BaseDevice 5 | from .data_bridge import to_plain 6 | from custom_components.ecoflow_cloud.entities import BaseSensorEntity, BaseNumberEntity, BaseSwitchEntity, \ 7 | BaseSelectEntity 8 | from custom_components.ecoflow_cloud.sensor import MiscSensorEntity, WattsSensorEntity, InAmpSensorEntity, VoltSensorEntity, \ 9 | EnergySensorEntity, MiscBinarySensorEntity 10 | 11 | class SmartMeter(BaseDevice): 12 | 13 | def sensors(self, client: EcoflowApiClient) -> Sequence[BaseSensorEntity]: 14 | timezoneEntity = MiscSensorEntity(client, self, "utcTimezone", const.UTC_TIMEZONE, False) 15 | timezoneEntity.attr("utcTimezoneId", const.UTC_TIMEZONE_ID, "Unknown") 16 | return [ 17 | WattsSensorEntity(client, self, "powGetSysGrid", const.SMART_METER_POWER_GLOBAL), 18 | 19 | WattsSensorEntity(client, self, "gridConnectionPowerL1", const.SMART_METER_POWER_L1, False), 20 | WattsSensorEntity(client, self, "gridConnectionPowerL2", const.SMART_METER_POWER_L2, False), 21 | WattsSensorEntity(client, self, "gridConnectionPowerL3", const.SMART_METER_POWER_L3, False), 22 | 23 | InAmpSensorEntity(client, self, "gridConnectionAmpL1", const.SMART_METER_IN_AMPS_L1, False), 24 | InAmpSensorEntity(client, self, "gridConnectionAmpL2", const.SMART_METER_IN_AMPS_L2, False), 25 | InAmpSensorEntity(client, self, "gridConnectionAmpL3", const.SMART_METER_IN_AMPS_L3, False), 26 | 27 | VoltSensorEntity(client, self, "gridConnectionVolL1", const.SMART_METER_VOLT_L1, False), 28 | VoltSensorEntity(client, self, "gridConnectionVolL2", const.SMART_METER_VOLT_L2, False), 29 | VoltSensorEntity(client, self, "gridConnectionVolL3", const.SMART_METER_VOLT_L3, False), 30 | 31 | MiscBinarySensorEntity(client, self, "gridConnectionFlagL1", const.SMART_METER_FLAG_L1, False), 32 | MiscBinarySensorEntity(client, self, "gridConnectionFlagL2", const.SMART_METER_FLAG_L2, False), 33 | MiscBinarySensorEntity(client, self, "gridConnectionFlagL3", const.SMART_METER_FLAG_L3, False), 34 | 35 | EnergySensorEntity(client, self, "gridConnectionDataRecord.todayActiveL1", const.SMART_METER_RECORD_TODAY_ACTIVE_L1,False), 36 | EnergySensorEntity(client, self, "gridConnectionDataRecord.todayActiveL2", const.SMART_METER_RECORD_TODAY_ACTIVE_L2, False), 37 | EnergySensorEntity(client, self, "gridConnectionDataRecord.todayActiveL3", const.SMART_METER_RECORD_TODAY_ACTIVE_L3, False), 38 | 39 | EnergySensorEntity(client, self, "gridConnectionDataRecord.todayActive", const.SMART_METER_RECORD_ACTIVE_TODAY), 40 | EnergySensorEntity(client, self, "gridConnectionDataRecord.totalActiveEnergy", const.SMART_METER_RECORD_NET_ENERGY_CONSUMPTION), 41 | EnergySensorEntity(client, self, "gridConnectionDataRecord.totalReactiveEnergy", const.SMART_METER_RECORD_LIFETIME_ENERGY_DELIVERY), 42 | 43 | # Configurable? 44 | timezoneEntity, 45 | # Configurable? 46 | MiscSensorEntity(client, self, "gridConnectionPowerFactor", 47 | const.SMART_METER_GRID_CONNECTION_POWER_FACTOR, False), 48 | MiscSensorEntity(client, self, "gridConnectionSta", const.SMART_METER_GRID_CONNECTION_STATE, False), 49 | # Configurable? 50 | MiscSensorEntity(client, self, "countryCode", const.COUNTRY_CODE, False), 51 | # Configurable? 52 | MiscSensorEntity(client, self, "townCode", const.TOWN_CODE, False), 53 | # Configurable? 54 | MiscSensorEntity(client, self, "systemGroupId", const.SYSTEM_GROUP_ID, False), 55 | 56 | # Configurable? 57 | MiscBinarySensorEntity(client, self, "factoryModeEnable", const.FACTORY_MODE, False, 58 | diagnostic=True), 59 | # Configurable? 60 | MiscBinarySensorEntity(client, self, "debugModeEnable", const.DEBUG_MODE, False, diagnostic=True), 61 | 62 | self._status_sensor(client), 63 | ] 64 | 65 | def numbers(self, client: EcoflowApiClient) -> Sequence[BaseNumberEntity]: 66 | return [] 67 | 68 | def switches(self, client: EcoflowApiClient) -> Sequence[BaseSwitchEntity]: 69 | return [] 70 | 71 | def selects(self, client: EcoflowApiClient) -> Sequence[BaseSelectEntity]: 72 | return [] 73 | 74 | def _prepare_data(self, raw_data) -> dict[str, any]: 75 | res = super()._prepare_data(raw_data) 76 | res = to_plain(res) 77 | return res 78 | 79 | def _status_sensor(self, client: EcoflowApiClient) -> QuotaStatusSensorEntity: 80 | return QuotaStatusSensorEntity(client, self) 81 | 82 | 83 | -------------------------------------------------------------------------------- /custom_components/ecoflow_cloud/devices/public/smart_home_panel.py: -------------------------------------------------------------------------------- 1 | from homeassistant.helpers.entity import EntityCategory 2 | 3 | from ...api import EcoflowApiClient 4 | from ...entities import ( 5 | BaseNumberEntity, 6 | BaseSelectEntity, 7 | BaseSensorEntity, 8 | BaseSwitchEntity, 9 | ) 10 | from ...number import ( 11 | MaxBatteryLevelEntity, 12 | MinBatteryLevelEntity, 13 | ) 14 | from ...sensor import ( 15 | LevelSensorEntity, 16 | MiscBinarySensorEntity, 17 | RemainSensorEntity, 18 | TempSensorEntity, 19 | InWattsSensorEntity, 20 | OutWattsSensorEntity, 21 | InEnergySensorEntity, 22 | OutEnergySensorEntity, 23 | ) 24 | from ...switch import EnabledEntity 25 | from .. import BaseDevice, const 26 | 27 | 28 | class SmartHomePanel(BaseDevice): 29 | def sensors(self, client: EcoflowApiClient) -> list[BaseSensorEntity]: 30 | return [ 31 | MiscBinarySensorEntity(client, self, "heartbeat.gridSta", const.POWER_GRID) 32 | .with_icon("mdi:transmission-tower"), 33 | 34 | LevelSensorEntity(client, self, "heartbeat.backupBatPer", const.COMBINED_BATTERY_LEVEL) 35 | .attr("heartbeat.energyInfos[0].batteryPercentage", const.MAIN_BATTERY_LEVEL, 0), 36 | RemainSensorEntity(client, self, "heartbeat.backupChaTime", const.REMAINING_TIME) 37 | .attr("heartbeat.energyInfos[0].chargeTime", const.MAIN_CHARGE_REMAINING_TIME, 0) 38 | .attr("heartbeat.energyInfos[0].dischargeTime", const.MAIN_DISCHARGE_REMAINING_TIME, 0), 39 | 40 | TempSensorEntity(client, self, "heartbeat.energyInfos[0].emsBatTemp", const.MAIN_BATTERY_TEMP), 41 | InWattsSensorEntity(client, self, "heartbeat.energyInfos[0].lcdInputWatts", const.MAIN_BATTERY_IN_POWER) 42 | .with_energy().with_icon("mdi:transmission-tower"), 43 | OutWattsSensorEntity(client, self, "heartbeat.energyInfos[0].outputPower", const.MAIN_BATTERY_OUT_POWER) 44 | .with_energy().with_icon("mdi:home-battery"), 45 | InEnergySensorEntity(client, self, "heartbeat.gridDayWatth", const.POWER_GRID_TODAY), 46 | OutEnergySensorEntity(client, self, "heartbeat.backupDayWatth", const.BATTERY_TODAY), 47 | ] 48 | 49 | def numbers(self, client: EcoflowApiClient) -> list[BaseNumberEntity]: 50 | return [ 51 | MinBatteryLevelEntity( 52 | client, self, "'backupChaDiscCfg.discLower'", const.MIN_DISCHARGE_LEVEL, 0, 30, 53 | lambda value, params: { 54 | "operateType": "TCP", 55 | "params": { 56 | "cmdSet": 11, 57 | "id": 29, 58 | "discLower": value, 59 | "forceChargeHigh": int(params.get("heartbeat.backupChaDiscCfg.forceChargeHigh", 100)), 60 | }, 61 | }, 62 | ), 63 | MaxBatteryLevelEntity( 64 | client, self, "'backupChaDiscCfg.forceChargeHigh'", const.MAX_CHARGE_LEVEL, 50, 100, 65 | lambda value, params: { 66 | "operateType": "TCP", 67 | "params": { 68 | "cmdSet": 11, 69 | "id": 29, 70 | "forceChargeHigh": value, 71 | "discLower": int(params.get("backupChaDiscCfg.discLower", 0)), 72 | }, 73 | }, 74 | ), 75 | ] 76 | 77 | def switches(self, client: EcoflowApiClient) -> list[BaseSwitchEntity]: 78 | return [ 79 | EnabledEntity( 80 | client, self, "'epsModeInfo.eps'", const.EPS_MODE, 81 | lambda value: { 82 | "operateType": "TCP", 83 | "params": {"cmdSet": 11, "id": 24, "eps": int(value)}, 84 | }, 85 | ).with_category(EntityCategory.CONFIG).with_icon("mdi:power-plug-battery"), 86 | EnabledEntity( 87 | client, self, "heartbeat.backupCmdChCtrlInfos[0].ctrlSta", const.MAIN_BATTERY_CHARGE, 88 | lambda value: { 89 | "operateType": "TCP", 90 | "params": { 91 | "cmdSet": 11, 92 | "id": 17, 93 | "sta": 2 if value else 0, 94 | "ctrlMode": 1 if value else 0, 95 | "ch": 10 96 | }, 97 | }, 98 | enableValue=2, 99 | disableValue=0, 100 | ).with_category(EntityCategory.CONFIG).with_icon("mdi:battery-charging"), 101 | ] 102 | 103 | def selects(self, client: EcoflowApiClient) -> list[BaseSelectEntity]: 104 | return [] 105 | 106 | def flat_json(self): 107 | return False 108 | -------------------------------------------------------------------------------- /docs/devices/Delta_Pro_3-Public.md: -------------------------------------------------------------------------------- 1 | ## Delta_Pro_3 2 | 3 | *Sensors* 4 | - Main Battery Level (`bmsBattSoc`) 5 | - Main Design Capacity (`bmsDesignCap`) _(disabled)_ 6 | - Charging/Discharging State (`cmsChgDsgState`) _(disabled)_ 7 | - BMS Run State (`cmsBmsRunState`) _(disabled)_ 8 | - Battery Level (`cmsBattSoc`) 9 | - Max Cell Temperature (`bmsMaxCellTemp`) _(disabled)_ 10 | - Min Cell Temperature (`bmsMinCellTemp`) _(disabled)_ 11 | - Charge Remaining Time (`bmsChgRemTime`) 12 | - Discharge Remaining Time (`bmsDsgRemTime`) 13 | - Total Charging Time (`cmsChgRemTime`) 14 | - Total Discharging Time (`cmsDsgRemTime`) 15 | - Total In Power (`powInSumW`) (energy: _[Device Name]_ Total In Energy) 16 | - Total Out Power (`powOutSumW`) (energy: _[Device Name]_ Total Out Energy) 17 | - AC In Power (`powGetAcIn`) 18 | - Real-time grid power (`powGetAcHvOut`) 19 | - AC Out Power (`powGetAc`) 20 | - 12V DC Output Power (`powGet12v`) 21 | - 24V DC Output Power (`powGet24v`) 22 | - Real-time low-voltage AC output power (`powGetAcLvOut`) 23 | - Real-time power of the low-voltage AC output port (`powGetAcLvTt30Out`) 24 | - Solar High Voltage Input Power (`powGetPvH`) 25 | - Solar Low Voltage Input Power (`powGetPvL`) 26 | - USB QC (1) Out Power (`powGetQcusb1`) 27 | - USB QC (2) Out Power (`powGetQcusb2`) 28 | - Type-C (1) Out Power (`powGetTypec1`) 29 | - Type-C (2) Out Power (`powGetTypec2`) 30 | - 5P8 Power I/O Port Power (`powGet5p8`) 31 | - 4P8 Extra Battery Port 1 Power (`powGet4p81`) _(auto)_ 32 | - 4P8 Extra Battery Port 2 Power (`powGet4p82`) _(auto)_ 33 | - AC Input Frequency (`plugInInfoAcInFeq`) 34 | - Status 35 | 36 | *Switches* 37 | - Beeper (`enBeep` -> `{"sn": "SN", "cmdId": 17, "dirDest": 1, "dirSrc": 1, "cmdFunc": 254, "dest": 2, "params": {"cfgBeepEn": "VALUE"}}`) 38 | - AC HV Output Enabled (`cfgHvAcOutOpen` -> `{"sn": "SN", "cmdId": 17, "dirDest": 1, "dirSrc": 1, "cmdFunc": 254, "dest": 2, "params": {"cfgHvAcOutOpen": "VALUE"}}`) 39 | - AC LV Output Enabled (`cfgLvAcOutOpen` -> `{"sn": "SN", "cmdId": 17, "dirDest": 1, "dirSrc": 1, "cmdFunc": 254, "dest": 2, "params": {"cfgLvAcOutOpen": "VALUE"}}`) 40 | - 12V DC Output Enabled (`cfgDc12vOutOpen` -> `{"sn": "SN", "cmdId": 17, "dirDest": 1, "dirSrc": 1, "cmdFunc": 254, "dest": 2, "params": {"cfgDc12vOutOpen": "VALUE"}}`) 41 | - 24V DC Output Enabled (`cfgDc24vOutOpen` -> `{"sn": "SN", "cmdId": 17, "dirDest": 1, "dirSrc": 1, "cmdFunc": 254, "dest": 2, "params": {"cfgDc24vOutOpen": "VALUE"}}`) 42 | - X-Boost Enabled (`xboostEn` -> `{"sn": "SN", "cmdId": 17, "dirDest": 1, "dirSrc": 1, "cmdFunc": 254, "dest": 2, "params": {"cfgXboostEn": "VALUE"}}`) 43 | - AC Energy Saving Enabled (`acEnergySavingOpen` -> `{"sn": "SN", "cmdId": 17, "dirDest": 1, "dirSrc": 1, "cmdFunc": 254, "dest": 2, "params": {"cfgAcEnergySavingOpen": "VALUE"}}`) 44 | - Smart Generator Auto Start/Stop (`cmsOilSelfStart` -> `{"sn": "SN", "cmdId": 17, "dirDest": 1, "dirSrc": 1, "cmdFunc": 254, "dest": 2, "params": {"cfgCmsOilSelfStart": "VALUE"}}`) 45 | 46 | *Sliders (numbers)* 47 | - Max Charge Level (`cmsMaxChgSoc` -> `{"sn": "SN", "cmdId": 17, "dirDest": 1, "dirSrc": 1, "cmdFunc": 254, "dest": 2, "params": {"cfgMaxChgSoc": "VALUE"}}` [50 - 100]) 48 | - Min Discharge Level (`cmsMinDsgSoc` -> `{"sn": "SN", "cmdId": 17, "dirDest": 1, "dirSrc": 1, "cmdFunc": 254, "dest": 2, "params": {"cfgMinDsgSoc": "VALUE"}}` [0 - 30]) 49 | - Smart Generator Start SOC (`cmsOilOnSoc` -> `{"sn": "SN", "cmdId": 17, "dirDest": 1, "dirSrc": 1, "cmdFunc": 254, "dest": 2, "params": {"cfgCmsOilOnSoc": "VALUE"}}` [0 - 100]) 50 | - Smart Generator Stop SOC (`cmsOilOffSoc` -> `{"sn": "SN", "cmdId": 17, "dirDest": 1, "dirSrc": 1, "cmdFunc": 254, "dest": 2, "params": {"cfgCmsOilOffSoc": "VALUE"}}` [0 - 100]) 51 | - AC Charging Power (`cfgPlugInInfoAcInChgPowMax` -> `{"sn": "SN", "cmdId": 17, "dirDest": 1, "dirSrc": 1, "cmdFunc": 254, "dest": 2, "params": {"cfgPlugInInfoAcInChgPowMax": "VALUE"}}` [400 - 2900]) 52 | 53 | *Selects* 54 | - Screen Timeout (`screenOffTime` -> `{"sn": "SN", "cmdId": 17, "dirDest": 1, "dirSrc": 1, "cmdFunc": 254, "dest": 2, "params": {"cfgScreenOffTime": "VALUE"}}` [Never (0), 10 sec (10), 30 sec (30), 1 min (60), 5 min (300), 30 min (1800)]) 55 | - AC Timeout (`acStandbyTime` -> `{"sn": "SN", "cmdId": 17, "dirDest": 1, "dirSrc": 1, "cmdFunc": 254, "dest": 2, "params": {"cfgAcStandbyTime": "VALUE"}}` [Never (0), 30 min (30), 1 hr (60), 2 hr (120), 4 hr (240), 6 hr (360), 12 hr (720), 24 hr (1440)]) 56 | - DC Timeout (`dcStandbyTime` -> `{"sn": "SN", "cmdId": 17, "dirDest": 1, "dirSrc": 1, "cmdFunc": 254, "dest": 2, "params": {"cfgDcStandbyTime": "VALUE"}}` [Never (0), 30 min (30), 1 hr (60), 2 hr (120), 6 hr (360), 12 hr (720)]) 57 | - Bluetooth Timeout (`bleStandbyTime` -> `{"sn": "SN", "cmdId": 17, "dirDest": 1, "dirSrc": 1, "cmdFunc": 254, "dest": 2, "params": {"cfgBleStandbyTime": "VALUE"}}` [Never (0), 30 min (30), 1 hr (60), 2 hr (120), 6 hr (360), 12 hr (720)]) 58 | - Device Timeout (`devStandbyTime` -> `{"sn": "SN", "cmdId": 17, "dirDest": 1, "dirSrc": 1, "cmdFunc": 254, "dest": 2, "params": {"cfgDevStandbyTime": "VALUE"}}` [Never (0), 30 min (30), 1 hr (60), 2 hr (120), 6 hr (360), 12 hr (720)]) 59 | - AC Output Type (`plugInInfoAcOutType` -> `{"sn": "SN", "cmdId": 17, "dirDest": 1, "dirSrc": 1, "cmdFunc": 254, "dest": 2, "params": {"cfgPlugInInfoAcOutType": "VALUE"}}` [HV+LV (0), HV Only (1), LV Only (2)]) 60 | 61 | 62 | -------------------------------------------------------------------------------- /docs/devices/DELTA_MAX.md: -------------------------------------------------------------------------------- 1 | ## DELTA_MAX 2 | 3 | *Sensors* 4 | - Main Battery Level (`bmsMaster.soc`) 5 | - Main Battery Level (Precise) (`bmsMaster.f32ShowSoc`) _(disabled)_ 6 | - Main Design Capacity (`bmsMaster.designCap`) _(disabled)_ 7 | - Main Full Capacity (`bmsMaster.fullCap`) _(disabled)_ 8 | - Main Remain Capacity (`bmsMaster.remainCap`) _(disabled)_ 9 | - State of Health (`bmsMaster.soh`) 10 | - Battery Level (`ems.lcdShowSoc`) 11 | - Battery Level (Precise) (`ems.f32LcdShowSoc`) _(disabled)_ 12 | - Total In Power (`pd.wattsInSum`) 13 | - Total Out Power (`pd.wattsOutSum`) 14 | - Main Battery Current (`bmsMaster.amp`) 15 | - AC In Power (`inv.inputWatts`) 16 | - AC Out Power (`inv.outputWatts`) 17 | - AC In Volts (`inv.acInVol`) 18 | - AC Out Volts (`inv.invOutVol`) 19 | - Solar In Power (`mppt.inWatts`) 20 | - Solar In Voltage (`mppt.inVol`) 21 | - Solar In Current (`mppt.inAmp`) 22 | - DC Out Power (`mppt.outWatts`) 23 | - DC Out Voltage (`mppt.outVol`) 24 | - Type-C (1) Out Power (`pd.typec1Watts`) 25 | - Type-C (2) Out Power (`pd.typec2Watts`) 26 | - USB (1) Out Power (`pd.usb1Watts`) 27 | - USB (2) Out Power (`pd.usb2Watts`) 28 | - USB QC (1) Out Power (`pd.qcUsb1Watts`) 29 | - USB QC (2) Out Power (`pd.qcUsb2Watts`) 30 | - Charge Remaining Time (`ems.chgRemainTime`) 31 | - Discharge Remaining Time (`ems.dsgRemainTime`) 32 | - Inv Out Temperature (`inv.outTemp`) 33 | - Cycles (`bmsMaster.cycles`) 34 | - Battery Temperature (`bmsMaster.temp`) 35 | - Min Cell Temperature (`bmsMaster.minCellTemp`) _(disabled)_ 36 | - Max Cell Temperature (`bmsMaster.maxCellTemp`) _(disabled)_ 37 | - Battery Volts (`bmsMaster.vol`) _(disabled)_ 38 | - Min Cell Volts (`bmsMaster.minCellVol`) _(disabled)_ 39 | - Max Cell Volts (`bmsMaster.maxCellVol`) _(disabled)_ 40 | - Solar In Energy (`pd.chgSunPower`) 41 | - Battery Charge Energy from AC (`pd.chgPowerAc`) 42 | - Battery Charge Energy from DC (`pd.chgPowerDc`) 43 | - Battery Discharge Energy to AC (`pd.dsgPowerAc`) 44 | - Battery Discharge Energy to DC (`pd.dsgPowerDc`) 45 | - Slave 1 Battery Level (`bmsSlave1.soc`) _(auto)_ 46 | - Slave 1 Battery Level (Precise) (`bmsSlave1.f32ShowSoc`) _(disabled)_ 47 | - Slave 1 Design Capacity (`bmsSlave1.designCap`) _(disabled)_ 48 | - Slave 1 Full Capacity (`bmsSlave1.fullCap`) _(disabled)_ 49 | - Slave 1 Remain Capacity (`bmsSlave1.remainCap`) _(disabled)_ 50 | - Slave 1 State of Health (`bmsSlave1.soh`) 51 | - Slave 1 Battery Temperature (`bmsSlave1.temp`) _(auto)_ 52 | - Slave 1 In Power (`bmsSlave1.inputWatts`) _(auto)_ 53 | - Slave 1 Out Power (`bmsSlave1.outputWatts`) _(auto)_ 54 | - Slave 2 Battery Level (`bmsSlave2.soc`) _(auto)_ 55 | - Slave 2 Battery Level (Precise) (`bmsSlave2.f32ShowSoc`) _(disabled)_ 56 | - Slave 2 Design Capacity (`bmsSlave2.designCap`) _(disabled)_ 57 | - Slave 2 Full Capacity (`bmsSlave2.fullCap`) _(disabled)_ 58 | - Slave 2 Remain Capacity (`bmsSlave2.remainCap`) _(disabled)_ 59 | - Slave 2 State of Health (`bmsSlave2.soh`) 60 | - Slave 1 Battery Volts (`bmsSlave1.vol`) _(disabled)_ 61 | - Slave 1 Min Cell Volts (`bmsSlave1.minCellVol`) _(disabled)_ 62 | - Slave 1 Max Cell Volts (`bmsSlave1.maxCellVol`) _(disabled)_ 63 | - Slave 1 Battery Current (`bmsSlave1.amp`) _(disabled)_ 64 | - Slave 2 Battery Volts (`bmsSlave2.vol`) _(disabled)_ 65 | - Slave 2 Min Cell Volts (`bmsSlave2.minCellVol`) _(disabled)_ 66 | - Slave 2 Max Cell Volts (`bmsSlave2.maxCellVol`) _(disabled)_ 67 | - Slave 2 Battery Current (`bmsSlave2.amp`) _(disabled)_ 68 | - Slave 2 Battery Temperature (`bmsSlave2.temp`) _(auto)_ 69 | - Slave 2 In Power (`bmsSlave2.inputWatts`) _(auto)_ 70 | - Slave 2 Out Power (`bmsSlave2.outputWatts`) _(auto)_ 71 | - Slave 1 Cycles (`bmsSlave1.cycles`) _(disabled)_ 72 | - Slave 2 Cycles (`bmsSlave2.cycles`) _(disabled)_ 73 | - Status 74 | 75 | *Switches* 76 | - Beeper (`pd.beepState` -> `{"moduleType": 5, "operateType": "TCP", "params": {"id": 38, "enabled": "VALUE"}}`) 77 | - USB Enabled (`pd.dcOutState` -> `{"moduleType": 0, "operateType": "TCP", "params": {"enabled": "VALUE", "id": 34}}`) 78 | - AC Always On (`pd.acAutoOnCfg` -> `{"moduleType": 1, "operateType": "acAutoOn", "params": {"cfg": "VALUE"}}`) 79 | - Prio Solar Charging (`pd.pvChgPrioSet` -> `{"moduleType": 1, "operateType": "pvChangePrio", "params": {"pvChangeSet": "VALUE"}}`) 80 | - AC Enabled (`inv.cfgAcEnabled` -> `{"moduleType": 0, "operateType": "TCP", "params": {"enabled": "VALUE", "id": 66}}`) 81 | - X-Boost Enabled (`inv.cfgAcXboost` -> `{"moduleType": 5, "operateType": "TCP", "params": {"id": 66, "xboost": "VALUE"}}`) 82 | - DC (12V) Enabled (`mppt.carState` -> `{"moduleType": 0, "operateType": "TCP", "params": {"enabled": "VALUE", "id": 81}}`) 83 | 84 | *Sliders (numbers)* 85 | - Max Charge Level (`ems.maxChargeSoc` -> `{"moduleType": 2, "operateType": "TCP", "params": {"id": 49, "maxChgSoc": "VALUE"}}` [50 - 100]) 86 | - Min Discharge Level (`ems.minDsgSoc` -> `{"moduleType": 2, "operateType": "TCP", "params": {"id": 51, "minDsgSoc": "VALUE"}}` [0 - 30]) 87 | - Generator Auto Start Level (`ems.minOpenOilEbSoc` -> `{"moduleType": 2, "operateType": "TCP", "params": {"id": 52, "openOilSoc": "VALUE"}}` [0 - 30]) 88 | - Generator Auto Stop Level (`ems.maxCloseOilEbSoc` -> `{"moduleType": 2, "operateType": "TCP", "params": {"id": 53, "closeOilSoc": "VALUE"}}` [50 - 100]) 89 | - AC Charging Power (`inv.cfgSlowChgWatts` -> `{"moduleType": 0, "operateType": "TCP", "params": {"slowChgPower": "VALUE", "id": 69}}` [100 - 2000]) 90 | 91 | *Selects* 92 | 93 | 94 | -------------------------------------------------------------------------------- /docs/devices/DELTA_Max-Public.md: -------------------------------------------------------------------------------- 1 | ## DELTA_Max 2 | 3 | *Sensors* 4 | - Main Battery Level (`bmsMaster.soc`) 5 | - Main Battery Level (Precise) (`bmsMaster.f32ShowSoc`) _(disabled)_ 6 | - Main Design Capacity (`bmsMaster.designCap`) _(disabled)_ 7 | - Main Full Capacity (`bmsMaster.fullCap`) _(disabled)_ 8 | - Main Remain Capacity (`bmsMaster.remainCap`) _(disabled)_ 9 | - State of Health (`bmsMaster.soh`) 10 | - Battery Level (`ems.lcdShowSoc`) 11 | - Battery Level (Precise) (`ems.f32LcdShowSoc`) _(disabled)_ 12 | - Total In Power (`pd.wattsInSum`) 13 | - Total Out Power (`pd.wattsOutSum`) 14 | - Main Battery Current (`bmsMaster.amp`) 15 | - AC In Power (`inv.inputWatts`) 16 | - AC Out Power (`inv.outputWatts`) 17 | - AC In Volts (`inv.acInVol`) 18 | - AC Out Volts (`inv.invOutVol`) 19 | - Solar In Power (`mppt.inWatts`) 20 | - Solar In Voltage (`mppt.inVol`) 21 | - Solar In Current (`mppt.inAmp`) 22 | - DC Out Power (`mppt.outWatts`) 23 | - DC Out Voltage (`mppt.outVol`) 24 | - Type-C (1) Out Power (`pd.typec1Watts`) 25 | - Type-C (2) Out Power (`pd.typec2Watts`) 26 | - USB (1) Out Power (`pd.usb1Watts`) 27 | - USB (2) Out Power (`pd.usb2Watts`) 28 | - USB QC (1) Out Power (`pd.qcUsb1Watts`) 29 | - USB QC (2) Out Power (`pd.qcUsb2Watts`) 30 | - Charge Remaining Time (`ems.chgRemainTime`) 31 | - Discharge Remaining Time (`ems.dsgRemainTime`) 32 | - Inv Out Temperature (`inv.outTemp`) 33 | - Cycles (`bmsMaster.cycles`) 34 | - Battery Temperature (`bmsMaster.temp`) 35 | - Min Cell Temperature (`bmsMaster.minCellTemp`) _(disabled)_ 36 | - Max Cell Temperature (`bmsMaster.maxCellTemp`) _(disabled)_ 37 | - Battery Volts (`bmsMaster.vol`) _(disabled)_ 38 | - Min Cell Volts (`bmsMaster.minCellVol`) _(disabled)_ 39 | - Max Cell Volts (`bmsMaster.maxCellVol`) _(disabled)_ 40 | - Solar In Energy (`pd.chgSunPower`) 41 | - Battery Charge Energy from AC (`pd.chgPowerAc`) 42 | - Battery Charge Energy from DC (`pd.chgPowerDc`) 43 | - Battery Discharge Energy to AC (`pd.dsgPowerAc`) 44 | - Battery Discharge Energy to DC (`pd.dsgPowerDc`) 45 | - Slave 1 Battery Level (`bmsSlave1.soc`) _(auto)_ 46 | - Slave 1 Battery Level (Precise) (`bmsSlave1.f32ShowSoc`) _(disabled)_ 47 | - Slave 1 Design Capacity (`bmsSlave1.designCap`) _(disabled)_ 48 | - Slave 1 Full Capacity (`bmsSlave1.fullCap`) _(disabled)_ 49 | - Slave 1 Remain Capacity (`bmsSlave1.remainCap`) _(disabled)_ 50 | - Slave 1 State of Health (`bmsSlave1.soh`) 51 | - Slave 1 Battery Temperature (`bmsSlave1.temp`) _(auto)_ 52 | - Slave 1 In Power (`bmsSlave1.inputWatts`) _(auto)_ 53 | - Slave 1 Out Power (`bmsSlave1.outputWatts`) _(auto)_ 54 | - Slave 2 Battery Level (`bmsSlave2.soc`) _(auto)_ 55 | - Slave 2 Battery Level (Precise) (`bmsSlave2.f32ShowSoc`) _(disabled)_ 56 | - Slave 2 Design Capacity (`bmsSlave2.designCap`) _(disabled)_ 57 | - Slave 2 Full Capacity (`bmsSlave2.fullCap`) _(disabled)_ 58 | - Slave 2 Remain Capacity (`bmsSlave2.remainCap`) _(disabled)_ 59 | - Slave 2 State of Health (`bmsSlave2.soh`) 60 | - Slave 1 Battery Volts (`bmsSlave1.vol`) _(disabled)_ 61 | - Slave 1 Min Cell Volts (`bmsSlave1.minCellVol`) _(disabled)_ 62 | - Slave 1 Max Cell Volts (`bmsSlave1.maxCellVol`) _(disabled)_ 63 | - Slave 1 Battery Current (`bmsSlave1.amp`) _(disabled)_ 64 | - Slave 2 Battery Volts (`bmsSlave2.vol`) _(disabled)_ 65 | - Slave 2 Min Cell Volts (`bmsSlave2.minCellVol`) _(disabled)_ 66 | - Slave 2 Max Cell Volts (`bmsSlave2.maxCellVol`) _(disabled)_ 67 | - Slave 2 Battery Current (`bmsSlave2.amp`) _(disabled)_ 68 | - Slave 2 Battery Temperature (`bmsSlave2.temp`) _(auto)_ 69 | - Slave 2 In Power (`bmsSlave2.inputWatts`) _(auto)_ 70 | - Slave 2 Out Power (`bmsSlave2.outputWatts`) _(auto)_ 71 | - Slave 1 Cycles (`bmsSlave1.cycles`) _(disabled)_ 72 | - Slave 2 Cycles (`bmsSlave2.cycles`) _(disabled)_ 73 | - Status 74 | 75 | *Switches* 76 | - Beeper (`pd.beepState` -> `{"moduleType": 5, "operateType": "TCP", "params": {"id": 38, "enabled": "VALUE"}}`) 77 | - USB Enabled (`pd.dcOutState` -> `{"moduleType": 0, "operateType": "TCP", "params": {"enabled": "VALUE", "id": 34}}`) 78 | - AC Always On (`pd.acAutoOnCfg` -> `{"moduleType": 1, "operateType": "acAutoOn", "params": {"cfg": "VALUE"}}`) 79 | - Prio Solar Charging (`pd.pvChgPrioSet` -> `{"moduleType": 1, "operateType": "pvChangePrio", "params": {"pvChangeSet": "VALUE"}}`) 80 | - AC Enabled (`inv.cfgAcEnabled` -> `{"moduleType": 0, "operateType": "TCP", "params": {"enabled": "VALUE", "id": 66}}`) 81 | - X-Boost Enabled (`inv.cfgAcXboost` -> `{"moduleType": 5, "operateType": "TCP", "params": {"id": 66, "xboost": "VALUE"}}`) 82 | - DC (12V) Enabled (`mppt.carState` -> `{"moduleType": 0, "operateType": "TCP", "params": {"enabled": "VALUE", "id": 81}}`) 83 | 84 | *Sliders (numbers)* 85 | - Max Charge Level (`ems.maxChargeSoc` -> `{"moduleType": 2, "operateType": "TCP", "params": {"id": 49, "maxChgSoc": "VALUE"}}` [50 - 100]) 86 | - Min Discharge Level (`ems.minDsgSoc` -> `{"moduleType": 2, "operateType": "TCP", "params": {"id": 51, "minDsgSoc": "VALUE"}}` [0 - 30]) 87 | - Generator Auto Start Level (`ems.minOpenOilEbSoc` -> `{"moduleType": 2, "operateType": "TCP", "params": {"id": 52, "openOilSoc": "VALUE"}}` [0 - 30]) 88 | - Generator Auto Stop Level (`ems.maxCloseOilEbSoc` -> `{"moduleType": 2, "operateType": "TCP", "params": {"id": 53, "closeOilSoc": "VALUE"}}` [50 - 100]) 89 | - AC Charging Power (`inv.cfgSlowChgWatts` -> `{"moduleType": 0, "operateType": "TCP", "params": {"slowChgPower": "VALUE", "id": 69}}` [100 - 2000]) 90 | 91 | *Selects* 92 | 93 | 94 | -------------------------------------------------------------------------------- /custom_components/ecoflow_cloud/number.py: -------------------------------------------------------------------------------- 1 | from typing import Any, Callable 2 | 3 | from homeassistant.components.number import NumberMode 4 | from homeassistant.components.sensor import SensorDeviceClass 5 | from homeassistant.config_entries import ConfigEntry 6 | from homeassistant.const import PERCENTAGE, UnitOfPower, UnitOfTemperature 7 | from homeassistant.core import HomeAssistant 8 | from homeassistant.helpers.entity_platform import AddEntitiesCallback 9 | 10 | from . import ECOFLOW_DOMAIN 11 | from .api import EcoflowApiClient, Message 12 | from .devices import BaseDevice 13 | from .entities import BaseNumberEntity 14 | 15 | 16 | async def async_setup_entry( 17 | hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback 18 | ): 19 | client: EcoflowApiClient = hass.data[ECOFLOW_DOMAIN][entry.entry_id] 20 | for sn, device in client.devices.items(): 21 | async_add_entities(device.numbers(client)) 22 | 23 | 24 | class ValueUpdateEntity(BaseNumberEntity): 25 | _attr_native_step = 1 26 | _attr_mode = NumberMode.SLIDER 27 | 28 | async def async_set_native_value(self, value: float): 29 | if self._command: 30 | ival = int(value) 31 | self.send_set_message(ival, self.command_dict(ival)) 32 | 33 | 34 | class ChargingPowerEntity(ValueUpdateEntity): 35 | _attr_icon = "mdi:transmission-tower-import" 36 | _attr_native_unit_of_measurement = UnitOfPower.WATT 37 | _attr_device_class = SensorDeviceClass.POWER 38 | 39 | def __init__( 40 | self, 41 | client: EcoflowApiClient, 42 | device: BaseDevice, 43 | mqtt_key: str, 44 | title: str, 45 | min_value: int, 46 | max_value: int, 47 | command: Callable[[int], dict[str, Any] | Message] 48 | | Callable[[int, dict[str, Any]], dict[str, Any] | Message] 49 | | None, 50 | enabled: bool = True, 51 | auto_enable: bool = False, 52 | ): 53 | super().__init__( 54 | client, 55 | device, 56 | mqtt_key, 57 | title, 58 | min_value, 59 | max_value, 60 | command, 61 | enabled, 62 | auto_enable, 63 | ) 64 | self._attr_native_step = self._device.charging_power_step() 65 | 66 | 67 | class DeciChargingPowerEntity(ChargingPowerEntity): 68 | _attr_mode = NumberMode.BOX 69 | 70 | def _update_value(self, val: Any) -> bool: 71 | return super()._update_value(int(val) / 10) 72 | 73 | async def async_set_native_value(self, value: float): 74 | if self._command: 75 | ival = int(value * 10) 76 | self.send_set_message(ival, self.command_dict(ival)) 77 | 78 | 79 | class AcChargingPowerInAmpereEntity(ValueUpdateEntity): 80 | _attr_mode = NumberMode.BOX 81 | _attr_native_step = 1 82 | 83 | def _update_value(self, val: Any) -> bool: 84 | return super()._update_value(int(val)) 85 | 86 | async def async_set_native_value(self, value: int): 87 | if self._command: 88 | self.send_set_message(value, self.command_dict(value)) 89 | 90 | 91 | class MinMaxLevelEntity(ValueUpdateEntity): 92 | def __init__( 93 | self, 94 | client: EcoflowApiClient, 95 | device: BaseDevice, 96 | mqtt_key: str, 97 | title: str, 98 | min_value: int, 99 | max_value: int, 100 | command: Callable[[int], dict[str, Any] | Message] 101 | | Callable[[int, dict[str, Any]], dict[str, Any] | Message] 102 | | None, 103 | ): 104 | super().__init__( 105 | client, device, mqtt_key, title, min_value, max_value, command, True, False 106 | ) 107 | 108 | 109 | class BrightnessLevelEntity(MinMaxLevelEntity): 110 | _attr_icon = "mdi:brightness-6" 111 | _attr_native_unit_of_measurement = PERCENTAGE 112 | 113 | 114 | class BatteryBackupLevel(MinMaxLevelEntity): 115 | _attr_icon = "mdi:battery-charging-90" 116 | _attr_native_unit_of_measurement = PERCENTAGE 117 | _gap_min = 5 118 | 119 | def __init__( 120 | self, 121 | client: EcoflowApiClient, 122 | device: BaseDevice, 123 | mqtt_key: str, 124 | title: str, 125 | min_value: int, 126 | max_value: int, 127 | min_key: str, 128 | max_key: str, 129 | gap_min: int, 130 | command: Callable[[int], dict[str, Any]] | None, 131 | ): 132 | super().__init__(client, device, mqtt_key, title, min_value, max_value, command) 133 | self._min_key = min_key 134 | self._max_key = max_key 135 | self._gap_min = gap_min 136 | 137 | def _updated(self, data: dict[str, Any]): 138 | if self._min_key in data: 139 | self._attr_native_min_value = int(data[self._min_key]) + self._gap_min # min + 5% 140 | if self._max_key in data: 141 | self._attr_native_max_value = int(data[self._max_key]) 142 | super()._updated(data) 143 | 144 | 145 | class LevelEntity(ValueUpdateEntity): 146 | _attr_native_unit_of_measurement = PERCENTAGE 147 | 148 | 149 | class MinBatteryLevelEntity(LevelEntity): 150 | _attr_icon = "mdi:battery-charging-10" 151 | 152 | 153 | class MaxBatteryLevelEntity(LevelEntity): 154 | _attr_icon = "mdi:battery-charging-90" 155 | 156 | 157 | class MinGenStartLevelEntity(LevelEntity): 158 | _attr_icon = "mdi:engine" 159 | 160 | 161 | class MaxGenStopLevelEntity(LevelEntity): 162 | _attr_icon = "mdi:engine-off" 163 | 164 | 165 | class SetTempEntity(ValueUpdateEntity): 166 | _attr_native_unit_of_measurement = UnitOfTemperature.CELSIUS 167 | -------------------------------------------------------------------------------- /custom_components/ecoflow_cloud/devices/internal/wave2.py: -------------------------------------------------------------------------------- 1 | from homeassistant.components.switch import SwitchEntity 2 | 3 | from custom_components.ecoflow_cloud.api import EcoflowApiClient 4 | from custom_components.ecoflow_cloud.devices import const, BaseDevice 5 | from custom_components.ecoflow_cloud.entities import BaseSensorEntity, BaseNumberEntity, BaseSelectEntity 6 | from custom_components.ecoflow_cloud.number import SetTempEntity 7 | from custom_components.ecoflow_cloud.select import DictSelectEntity 8 | from custom_components.ecoflow_cloud.sensor import LevelSensorEntity, RemainSensorEntity, TempSensorEntity, \ 9 | WattsSensorEntity, MilliCelsiusSensorEntity, CapacitySensorEntity, QuotaStatusSensorEntity 10 | 11 | 12 | class Wave2(BaseDevice): 13 | def sensors(self, client: EcoflowApiClient) -> list[BaseSensorEntity]: 14 | return [ 15 | # Power and Battery Entities 16 | LevelSensorEntity(client, self, "bms.soc", const.MAIN_BATTERY_LEVEL) 17 | .attr("bms.remainCap", const.ATTR_REMAIN_CAPACITY, 0), 18 | CapacitySensorEntity(client, self, "bms.remainCap", const.MAIN_REMAIN_CAPACITY, False), 19 | 20 | TempSensorEntity(client, self, "bms.tmp", const.BATTERY_TEMP) 21 | .attr("bms.minCellTemp", const.ATTR_MIN_CELL_TEMP, 0) 22 | .attr("bms.maxCellTemp", const.ATTR_MAX_CELL_TEMP, 0), 23 | TempSensorEntity(client, self, "bms.minCellTmp", const.MIN_CELL_TEMP, False), 24 | TempSensorEntity(client, self, "bms.maxCellTmp", const.MAX_CELL_TEMP, False), 25 | 26 | RemainSensorEntity(client, self, "pd.batChgRemain", const.CHARGE_REMAINING_TIME), 27 | RemainSensorEntity(client, self, "pd.batDsgRemain", const.DISCHARGE_REMAINING_TIME), 28 | 29 | # heat pump 30 | MilliCelsiusSensorEntity(client, self, "pd.condTemp", "Condensation temperature", False), 31 | MilliCelsiusSensorEntity(client, self, "pd.heatEnv", "Return air temperature in condensation zone", False), 32 | MilliCelsiusSensorEntity(client, self, "pd.coolEnv", "Air outlet temperature", False), 33 | MilliCelsiusSensorEntity(client, self, "pd.evapTemp", "Evaporation temperature", False), 34 | MilliCelsiusSensorEntity(client, self, "pd.motorOutTemp", "Exhaust temperature", False), 35 | MilliCelsiusSensorEntity(client, self, "pd.airInTemp", "Evaporation zone return air temperature", False), 36 | 37 | TempSensorEntity(client, self, "pd.coolTemp", "Air outlet temperature", False), 38 | TempSensorEntity(client, self, "pd.envTemp", "Ambient temperature", False), 39 | 40 | # power (pd) 41 | WattsSensorEntity(client, self, "pd.mpptPwr", "PV input power"), 42 | WattsSensorEntity(client, self, "pd.batPwrOut", "Battery output power"), 43 | WattsSensorEntity(client, self, "pd.pvPower", "PV charging power"), 44 | WattsSensorEntity(client, self, "pd.acPwrIn", "AC input power"), 45 | WattsSensorEntity(client, self, "pd.psdrPower ", "Power supply power"), 46 | WattsSensorEntity(client, self, "pd.sysPowerWatts", "System power"), 47 | WattsSensorEntity(client, self, "pd.batPower ", "Battery power"), 48 | 49 | # power (motor) 50 | WattsSensorEntity(client, self, "motor.power", "Motor operating power"), 51 | 52 | # power (power) 53 | WattsSensorEntity(client, self, "power.batPwrOut", "Battery output power"), 54 | WattsSensorEntity(client, self, "power.acPwrI", "AC input power"), 55 | WattsSensorEntity(client, self, "power.mpptPwr ", "PV input power"), 56 | 57 | QuotaStatusSensorEntity(client, self) 58 | ] 59 | 60 | def numbers(self, client: EcoflowApiClient) -> list[BaseNumberEntity]: 61 | return [ 62 | SetTempEntity(client, self, "pd.setTemp", "Set Temperature", 0, 40, 63 | lambda value: {"moduleType": 1, "operateType": "setTemp", 64 | "sn": self.device_info.sn, 65 | "params": {"setTemp": int(value)}}), 66 | ] 67 | 68 | def selects(self, client: EcoflowApiClient) -> list[BaseSelectEntity]: 69 | return [ 70 | DictSelectEntity(client, self, "pd.fanValue", const.FAN_MODE, const.FAN_MODE_OPTIONS, 71 | lambda value: {"moduleType": 1, "operateType": "fanValue", 72 | "sn": self.device_info.sn, 73 | "params": {"fanValue": value}}), 74 | DictSelectEntity(client, self, "pd.mainMode", const.MAIN_MODE, const.MAIN_MODE_OPTIONS, 75 | lambda value: {"moduleType": 1, "operateType": "mainMode", 76 | "sn": self.device_info.sn, 77 | "params": {"mainMode": value}}), 78 | DictSelectEntity(client, self, "pd.powerMode", const.REMOTE_MODE, const.REMOTE_MODE_OPTIONS, 79 | lambda value: {"moduleType": 1, "operateType": "powerMode", 80 | "sn": self.device_info.sn, 81 | "params": {"powerMode": value}}), 82 | DictSelectEntity(client, self, "pd.subMode", const.POWER_SUB_MODE, const.POWER_SUB_MODE_OPTIONS, 83 | lambda value: {"moduleType": 1, "operateType": "subMode", 84 | "sn": self.device_info.sn, 85 | "params": {"subMode": value}}), 86 | ] 87 | 88 | def switches(self, client: EcoflowApiClient) -> list[SwitchEntity]: 89 | return [] 90 | -------------------------------------------------------------------------------- /docs/devices/DELTA_2.md: -------------------------------------------------------------------------------- 1 | ## DELTA_2 2 | 3 | *Sensors* 4 | - Main Battery Level (`bms_bmsStatus.soc`) 5 | - Main Design Capacity (`bms_bmsStatus.designCap`) _(disabled)_ 6 | - Main Full Capacity (`bms_bmsStatus.fullCap`) _(disabled)_ 7 | - Main Remain Capacity (`bms_bmsStatus.remainCap`) _(disabled)_ 8 | - State of Health (`bms_bmsStatus.soh`) 9 | - Battery Level (`bms_emsStatus.lcdShowSoc`) 10 | - Battery Charging State (`bms_emsStatus.chgState`) 11 | - Total In Power (`pd.wattsInSum`) (energy: _[Device Name]_ Total In Energy) 12 | - Total Out Power (`pd.wattsOutSum`) (energy: _[Device Name]_ Total Out Energy) 13 | - AC In Power (`inv.inputWatts`) (energy: _[Device Name]_ AC In Energy) 14 | - AC Out Power (`inv.outputWatts`) (energy: _[Device Name]_ AC Out Energy) 15 | - AC In Volts (`inv.acInVol`) 16 | - AC Out Volts (`inv.invOutVol`) 17 | - Solar In Power (`mppt.inWatts`) (energy: _[Device Name]_ Solar In Energy) 18 | - DC Out Power (`mppt.outWatts`) 19 | - Type-C (1) Out Power (`pd.typec1Watts`) 20 | - Type-C (2) Out Power (`pd.typec2Watts`) 21 | - USB (1) Out Power (`pd.usb1Watts`) 22 | - USB (2) Out Power (`pd.usb2Watts`) 23 | - USB QC (1) Out Power (`pd.qcUsb1Watts`) 24 | - USB QC (2) Out Power (`pd.qcUsb2Watts`) 25 | - Charge Remaining Time (`bms_emsStatus.chgRemainTime`) 26 | - Discharge Remaining Time (`bms_emsStatus.dsgRemainTime`) 27 | - Remaining Time (`pd.remainTime`) 28 | - Inv Out Temperature (`inv.outTemp`) 29 | - Cycles (`bms_bmsStatus.cycles`) 30 | - Battery Temperature (`bms_bmsStatus.temp`) 31 | - Min Cell Temperature (`bms_bmsStatus.minCellTemp`) _(disabled)_ 32 | - Max Cell Temperature (`bms_bmsStatus.maxCellTemp`) _(disabled)_ 33 | - Battery Volts (`bms_bmsStatus.vol`) _(disabled)_ 34 | - Min Cell Volts (`bms_bmsStatus.minCellVol`) _(disabled)_ 35 | - Max Cell Volts (`bms_bmsStatus.maxCellVol`) _(disabled)_ 36 | - Slave Battery Level (`bms_slave.soc`) _(auto)_ 37 | - Slave Design Capacity (`bms_slave.designCap`) _(disabled)_ 38 | - Slave Full Capacity (`bms_slave.fullCap`) _(disabled)_ 39 | - Slave Remain Capacity (`bms_slave.remainCap`) _(disabled)_ 40 | - Slave State of Health (`bms_slave.soh`) 41 | - Slave Battery Temperature (`bms_slave.temp`) _(auto)_ 42 | - Slave Min Cell Temperature (`bms_slave.minCellTemp`) _(disabled)_ 43 | - Slave Max Cell Temperature (`bms_slave.maxCellTemp`) _(disabled)_ 44 | - Slave Battery Volts (`bms_slave.vol`) _(disabled)_ 45 | - Slave Min Cell Volts (`bms_slave.minCellVol`) _(disabled)_ 46 | - Slave Max Cell Volts (`bms_slave.maxCellVol`) _(disabled)_ 47 | - Slave Cycles (`bms_slave.cycles`) _(auto)_ 48 | - Slave In Power (`bms_slave.inputWatts`) _(auto)_ 49 | - Slave Out Power (`bms_slave.outputWatts`) _(auto)_ 50 | - Status 51 | 52 | *Switches* 53 | - Beeper (`mppt.beepState` -> `{"moduleType": 5, "operateType": "quietMode", "params": {"enabled": "VALUE"}}`) 54 | - USB Enabled (`pd.dcOutState` -> `{"moduleType": 1, "operateType": "dcOutCfg", "params": {"enabled": "VALUE"}}`) 55 | - AC Always On (`pd.acAutoOutConfig` -> `{"moduleType": 1, "operateType": "acAutoOutConfig", "params": {"acAutoOutConfig": "VALUE", "minAcOutSoc": 5}}`) 56 | - Prio Solar Charging (`pd.pvChgPrioSet` -> `{"moduleType": 1, "operateType": "pvChangePrio", "params": {"pvChangeSet": "VALUE"}}`) 57 | - AC Enabled (`mppt.cfgAcEnabled` -> `{"moduleType": 5, "operateType": "acOutCfg", "params": {"enabled": "VALUE", "out_voltage": -1, "out_freq": 255, "xboost": 255}}`) 58 | - X-Boost Enabled (`mppt.cfgAcXboost` -> `{"moduleType": 5, "operateType": "acOutCfg", "params": {"enabled": 255, "out_voltage": -1, "out_freq": 255, "xboost": "VALUE"}}`) 59 | - DC (12V) Enabled (`pd.carState` -> `{"moduleType": 5, "operateType": "mpptCar", "params": {"enabled": "VALUE"}}`) 60 | - Backup Reserve Enabled (`pd.watchIsConfig` -> `{"moduleType": 1, "operateType": "watthConfig", "params": {"bpPowerSoc": 333300, "minChgSoc": 0, "isConfig": "VALUE", "minDsgSoc": 0}}`) 61 | 62 | *Sliders (numbers)* 63 | - Max Charge Level (`bms_emsStatus.maxChargeSoc` -> `{"moduleType": 2, "operateType": "upsConfig", "params": {"maxChgSoc": "VALUE"}}` [50 - 100]) 64 | - Min Discharge Level (`bms_emsStatus.minDsgSoc` -> `{"moduleType": 2, "operateType": "dsgCfg", "params": {"minDsgSoc": "VALUE"}}` [0 - 30]) 65 | - Backup Reserve Level (`pd.bpPowerSoc` -> `{"moduleType": 1, "operateType": "watthConfig", "params": {"isConfig": 1, "bpPowerSoc": "VALUE", "minDsgSoc": 0, "minChgSoc": 0}}` [5 - 100]) 66 | - Generator Auto Start Level (`bms_emsStatus.minOpenOilEb` -> `{"moduleType": 2, "operateType": "openOilSoc", "params": {"openOilSoc": "VALUE"}}` [0 - 30]) 67 | - Generator Auto Stop Level (`bms_emsStatus.maxCloseOilEb` -> `{"moduleType": 2, "operateType": "closeOilSoc", "params": {"closeOilSoc": "VALUE"}}` [50 - 100]) 68 | - AC Charging Power (`mppt.cfgChgWatts` -> `{"moduleType": 5, "operateType": "acChgCfg", "params": {"chgWatts": "VALUE", "chgPauseFlag": 255}}` [200 - 1200]) 69 | 70 | *Selects* 71 | - DC (12V) Charge Current (`mppt.dcChgCurrent` -> `{"moduleType": 5, "operateType": "dcChgCfg", "params": {"dcChgCfg": "VALUE"}}` [4A (4000), 6A (6000), 8A (8000)]) 72 | - Screen Timeout (`pd.lcdOffSec` -> `{"moduleType": 1, "operateType": "lcdCfg", "params": {"brighLevel": 255, "delayOff": "VALUE"}}` [Never (0), 10 sec (10), 30 sec (30), 1 min (60), 5 min (300), 30 min (1800)]) 73 | - Unit Timeout (`pd.standbyMin` -> `{"moduleType": 1, "operateType": "standbyTime", "params": {"standbyMin": "VALUE"}}` [Never (0), 30 min (30), 1 hr (60), 2 hr (120), 4 hr (240), 6 hr (360), 12 hr (720), 24 hr (1440)]) 74 | - AC Timeout (`mppt.acStandbyMins` -> `{"moduleType": 5, "operateType": "standbyTime", "params": {"standbyMins": "VALUE"}}` [Never (0), 30 min (30), 1 hr (60), 2 hr (120), 4 hr (240), 6 hr (360), 12 hr (720), 24 hr (1440)]) 75 | - DC (12V) Timeout (`mppt.carStandbyMin` -> `{"moduleType": 5, "operateType": "carStandby", "params": {"standbyMins": "VALUE"}}` [Never (0), 30 min (30), 1 hr (60), 2 hr (120), 4 hr (240), 6 hr (360), 12 hr (720), 24 hr (1440)]) 76 | 77 | 78 | -------------------------------------------------------------------------------- /custom_components/ecoflow_cloud/api/ecoflow_mqtt.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import ssl 3 | import time 4 | from _socket import SocketType 5 | from typing import Any 6 | 7 | from homeassistant.core import callback 8 | from paho.mqtt.client import MQTTMessage, PayloadType 9 | 10 | from ..devices import BaseDevice 11 | from . import EcoflowMqttInfo 12 | 13 | _LOGGER = logging.getLogger(__name__) 14 | 15 | 16 | class EcoflowMQTTClient: 17 | def __init__(self, mqtt_info: EcoflowMqttInfo, devices: dict[str, BaseDevice]): 18 | from ..devices import BaseDevice 19 | 20 | self.connected = False 21 | self.__mqtt_info = mqtt_info 22 | self.__devices: dict[str, BaseDevice] = devices 23 | 24 | from homeassistant.components.mqtt.async_client import AsyncMQTTClient 25 | 26 | self.__client: AsyncMQTTClient = AsyncMQTTClient( 27 | client_id=self.__mqtt_info.client_id, 28 | reconnect_on_failure=True, 29 | clean_session=True, 30 | ) 31 | 32 | # self.__client._connect_timeout = 15.0 33 | self.__client.setup() 34 | self.__client.username_pw_set( 35 | self.__mqtt_info.username, self.__mqtt_info.password 36 | ) 37 | self.__client.tls_set(certfile=None, keyfile=None, cert_reqs=ssl.CERT_REQUIRED) 38 | self.__client.tls_insecure_set(False) 39 | self.__client.on_connect = self._on_connect 40 | self.__client.on_disconnect = self._on_disconnect 41 | self.__client.on_message = self._on_message 42 | self.__client.on_socket_close = self._on_socket_close 43 | 44 | _LOGGER.info( 45 | f"Connecting to MQTT Broker {self.__mqtt_info.url}:{self.__mqtt_info.port} with client id {self.__mqtt_info.client_id} and username {self.__mqtt_info.username}" 46 | ) 47 | self.__client.connect(self.__mqtt_info.url, self.__mqtt_info.port, keepalive=15) 48 | self.__client.loop_start() 49 | 50 | def is_connected(self): 51 | return self.__client.is_connected() 52 | 53 | def reconnect(self) -> bool: 54 | try: 55 | _LOGGER.info( 56 | f"Re-connecting to MQTT Broker {self.__mqtt_info.url}:{self.__mqtt_info.port}" 57 | ) 58 | self.__client.loop_stop(True) 59 | self.__client.reconnect() 60 | self.__client.loop_start() 61 | return True 62 | except Exception as e: 63 | _LOGGER.error(e) 64 | return False 65 | 66 | @callback 67 | def _on_socket_close(self, client, userdata: Any, sock: SocketType) -> None: 68 | _LOGGER.error(f"Unexpected MQTT Socket disconnection : {str(sock)}") 69 | 70 | @callback 71 | def _on_connect(self, client, userdata, flags, rc): 72 | if rc == 0: 73 | self.connected = True 74 | target_topics = [(topic, 1) for topic in self.__target_topics()] 75 | self.__client.subscribe(target_topics) 76 | _LOGGER.info(f"Subscribed to MQTT topics {target_topics}") 77 | else: 78 | self.__log_with_reason("connect", client, userdata, rc) 79 | 80 | @callback 81 | def _on_disconnect(self, client, userdata, rc): 82 | if not self.connected: 83 | # from homeassistant/components/mqtt/client.py 84 | # This function is re-entrant and may be called multiple times 85 | # when there is a broken pipe error. 86 | return 87 | self.connected = False 88 | if rc != 0: 89 | self.__log_with_reason("disconnect", client, userdata, rc) 90 | time.sleep(5) 91 | 92 | @callback 93 | def _on_message(self, client, userdata, message: MQTTMessage): 94 | try: 95 | for sn, device in self.__devices.items(): 96 | if device.update_data(message.payload, message.topic): 97 | _LOGGER.debug( 98 | f"Message for {sn} and Topic {message.topic} : {message.payload}" 99 | ) 100 | except UnicodeDecodeError as error: 101 | _LOGGER.error( 102 | f"UnicodeDecodeError: {error}. Ignoring message and waiting for the next one." 103 | ) 104 | 105 | def stop(self): 106 | self.__client.unsubscribe(self.__target_topics()) 107 | self.__client.loop_stop() 108 | self.__client.disconnect() 109 | 110 | def __log_with_reason(self, action: str, client, userdata, rc): 111 | import paho.mqtt.client as mqtt_client 112 | 113 | _LOGGER.error( 114 | f"MQTT {action}: {mqtt_client.error_string(rc)} ({self.__mqtt_info.client_id}) - {userdata}" 115 | ) 116 | 117 | def publish(self, topic: str, message: PayloadType) -> None: 118 | try: 119 | info = self.__client.publish(topic, message, 1) 120 | _LOGGER.debug( 121 | "Sending " 122 | + str(message) 123 | + " :" 124 | + str(info) 125 | + "(" 126 | + str(info.is_published()) 127 | + ")" 128 | ) 129 | except RuntimeError as error: 130 | _LOGGER.error( 131 | error, "Error on topic " + topic + " and message " + str(message) 132 | ) 133 | except Exception as error: 134 | _LOGGER.debug( 135 | error, "Error on topic " + topic + " and message " + str(message) 136 | ) 137 | 138 | def __target_topics(self) -> list[str]: 139 | topics = [] 140 | for device in self.__devices.values(): 141 | for topic in device.device_info.topics(): 142 | topics.append(topic) 143 | # Remove duplicates that can occur when multiple devices have the same topic (for example sub devices) 144 | return list(set(topics)) 145 | -------------------------------------------------------------------------------- /docs/devices/DELTA_2-Public.md: -------------------------------------------------------------------------------- 1 | ## DELTA_2 2 | 3 | *Sensors* 4 | - Main Battery Level (`bms_bmsStatus.soc`) 5 | - Main Design Capacity (`bms_bmsStatus.designCap`) _(disabled)_ 6 | - Main Full Capacity (`bms_bmsStatus.fullCap`) _(disabled)_ 7 | - Main Remain Capacity (`bms_bmsStatus.remainCap`) _(disabled)_ 8 | - State of Health (`bms_bmsStatus.soh`) 9 | - Battery Level (`bms_emsStatus.lcdShowSoc`) 10 | - Battery Charging State (`bms_emsStatus.chgState`) 11 | - Total In Power (`pd.wattsInSum`) (energy: _[Device Name]_ Total In Energy) 12 | - Total Out Power (`pd.wattsOutSum`) (energy: _[Device Name]_ Total Out Energy) 13 | - AC In Power (`inv.inputWatts`) (energy: _[Device Name]_ AC In Energy) 14 | - AC Out Power (`inv.outputWatts`) (energy: _[Device Name]_ AC Out Energy) 15 | - AC In Volts (`inv.acInVol`) 16 | - AC Out Volts (`inv.invOutVol`) 17 | - Solar In Power (`mppt.inWatts`) (energy: _[Device Name]_ Solar In Energy) 18 | - DC Out Power (`mppt.outWatts`) 19 | - Type-C (1) Out Power (`pd.typec1Watts`) 20 | - Type-C (2) Out Power (`pd.typec2Watts`) 21 | - USB (1) Out Power (`pd.usb1Watts`) 22 | - USB (2) Out Power (`pd.usb2Watts`) 23 | - USB QC (1) Out Power (`pd.qcUsb1Watts`) 24 | - USB QC (2) Out Power (`pd.qcUsb2Watts`) 25 | - Charge Remaining Time (`bms_emsStatus.chgRemainTime`) 26 | - Discharge Remaining Time (`bms_emsStatus.dsgRemainTime`) 27 | - Remaining Time (`pd.remainTime`) 28 | - Inv Out Temperature (`inv.outTemp`) 29 | - Cycles (`bms_bmsStatus.cycles`) 30 | - Battery Temperature (`bms_bmsStatus.temp`) 31 | - Min Cell Temperature (`bms_bmsStatus.minCellTemp`) _(disabled)_ 32 | - Max Cell Temperature (`bms_bmsStatus.maxCellTemp`) _(disabled)_ 33 | - Battery Volts (`bms_bmsStatus.vol`) _(disabled)_ 34 | - Min Cell Volts (`bms_bmsStatus.minCellVol`) _(disabled)_ 35 | - Max Cell Volts (`bms_bmsStatus.maxCellVol`) _(disabled)_ 36 | - Slave Battery Level (`bms_slave.soc`) _(auto)_ 37 | - Slave Design Capacity (`bms_slave.designCap`) _(disabled)_ 38 | - Slave Full Capacity (`bms_slave.fullCap`) _(disabled)_ 39 | - Slave Remain Capacity (`bms_slave.remainCap`) _(disabled)_ 40 | - Slave State of Health (`bms_slave.soh`) 41 | - Slave Battery Temperature (`bms_slave.temp`) _(auto)_ 42 | - Slave Min Cell Temperature (`bms_slave.minCellTemp`) _(disabled)_ 43 | - Slave Max Cell Temperature (`bms_slave.maxCellTemp`) _(disabled)_ 44 | - Slave Battery Volts (`bms_slave.vol`) _(disabled)_ 45 | - Slave Min Cell Volts (`bms_slave.minCellVol`) _(disabled)_ 46 | - Slave Max Cell Volts (`bms_slave.maxCellVol`) _(disabled)_ 47 | - Slave Cycles (`bms_slave.cycles`) _(auto)_ 48 | - Slave In Power (`bms_slave.inputWatts`) _(auto)_ 49 | - Slave Out Power (`bms_slave.outputWatts`) _(auto)_ 50 | - Status 51 | 52 | *Switches* 53 | - Beeper (`mppt.beepState` -> `{"moduleType": 5, "operateType": "quietMode", "params": {"enabled": "VALUE"}}`) 54 | - USB Enabled (`pd.dcOutState` -> `{"moduleType": 1, "operateType": "dcOutCfg", "params": {"enabled": "VALUE"}}`) 55 | - AC Always On (`pd.acAutoOutConfig` -> `{"moduleType": 1, "operateType": "acAutoOutConfig", "params": {"acAutoOutConfig": "VALUE", "minAcOutSoc": 5}}`) 56 | - Prio Solar Charging (`pd.pvChgPrioSet` -> `{"moduleType": 1, "operateType": "pvChangePrio", "params": {"pvChangeSet": "VALUE"}}`) 57 | - AC Enabled (`mppt.cfgAcEnabled` -> `{"moduleType": 5, "operateType": "acOutCfg", "params": {"enabled": "VALUE", "out_voltage": -1, "out_freq": 255, "xboost": 255}}`) 58 | - X-Boost Enabled (`mppt.cfgAcXboost` -> `{"moduleType": 5, "operateType": "acOutCfg", "params": {"enabled": 255, "out_voltage": -1, "out_freq": 255, "xboost": "VALUE"}}`) 59 | - DC (12V) Enabled (`pd.carState` -> `{"moduleType": 5, "operateType": "mpptCar", "params": {"enabled": "VALUE"}}`) 60 | - Backup Reserve Enabled (`pd.watchIsConfig` -> `{"moduleType": 1, "operateType": "watthConfig", "params": {"bpPowerSoc": 333300, "minChgSoc": 0, "isConfig": "VALUE", "minDsgSoc": 0}}`) 61 | 62 | *Sliders (numbers)* 63 | - Max Charge Level (`bms_emsStatus.maxChargeSoc` -> `{"moduleType": 2, "operateType": "upsConfig", "params": {"maxChgSoc": "VALUE"}}` [50 - 100]) 64 | - Min Discharge Level (`bms_emsStatus.minDsgSoc` -> `{"moduleType": 2, "operateType": "dsgCfg", "params": {"minDsgSoc": "VALUE"}}` [0 - 30]) 65 | - Backup Reserve Level (`pd.bpPowerSoc` -> `{"moduleType": 1, "operateType": "watthConfig", "params": {"isConfig": 1, "bpPowerSoc": "VALUE", "minDsgSoc": 0, "minChgSoc": 0}}` [5 - 100]) 66 | - Generator Auto Start Level (`bms_emsStatus.minOpenOilEb` -> `{"moduleType": 2, "operateType": "openOilSoc", "params": {"openOilSoc": "VALUE"}}` [0 - 30]) 67 | - Generator Auto Stop Level (`bms_emsStatus.maxCloseOilEb` -> `{"moduleType": 2, "operateType": "closeOilSoc", "params": {"closeOilSoc": "VALUE"}}` [50 - 100]) 68 | - AC Charging Power (`mppt.cfgChgWatts` -> `{"moduleType": 5, "operateType": "acChgCfg", "params": {"chgWatts": "VALUE", "chgPauseFlag": 255}}` [200 - 1200]) 69 | 70 | *Selects* 71 | - DC (12V) Charge Current (`mppt.dcChgCurrent` -> `{"moduleType": 5, "operateType": "dcChgCfg", "params": {"dcChgCfg": "VALUE"}}` [4A (4000), 6A (6000), 8A (8000)]) 72 | - Screen Timeout (`pd.lcdOffSec` -> `{"moduleType": 1, "operateType": "lcdCfg", "params": {"brighLevel": 255, "delayOff": "VALUE"}}` [Never (0), 10 sec (10), 30 sec (30), 1 min (60), 5 min (300), 30 min (1800)]) 73 | - Unit Timeout (`pd.standbyMin` -> `{"moduleType": 1, "operateType": "standbyTime", "params": {"standbyMin": "VALUE"}}` [Never (0), 30 min (30), 1 hr (60), 2 hr (120), 4 hr (240), 6 hr (360), 12 hr (720), 24 hr (1440)]) 74 | - AC Timeout (`mppt.acStandbyMins` -> `{"moduleType": 5, "operateType": "standbyTime", "params": {"standbyMins": "VALUE"}}` [Never (0), 30 min (30), 1 hr (60), 2 hr (120), 4 hr (240), 6 hr (360), 12 hr (720), 24 hr (1440)]) 75 | - DC (12V) Timeout (`mppt.carStandbyMin` -> `{"moduleType": 5, "operateType": "carStandby", "params": {"standbyMins": "VALUE"}}` [Never (0), 30 min (30), 1 hr (60), 2 hr (120), 4 hr (240), 6 hr (360), 12 hr (720), 24 hr (1440)]) 76 | 77 | 78 | -------------------------------------------------------------------------------- /docs/devices/DELTA_Pro_Ultra-Public.md: -------------------------------------------------------------------------------- 1 | ## DELTA_Pro_Ultra 2 | 3 | *Sensors* 4 | - Status (Scheduled) 5 | - Remaining Time (`hs_yj751_pd_appshow_addr.remainTime`) 6 | - Battery level SOC (`hs_yj751_pd_appshow_addr.soc`) 7 | - Battery Count (`hs_yj751_pd_appshow_addr.bpNum`) 8 | - Wireless 4G Data Max (`hs_yj751_pd_appshow_addr.fullCombo`) _(disabled)_ 9 | - Wireless 4G Data Remaining (`hs_yj751_pd_appshow_addr.remainCombo`) _(disabled)_ 10 | - Wireless 4G Resgistered (`hs_yj751_pd_appshow_addr.wireless4gCon`) _(disabled)_ 11 | - Wireless 4G Error Code (`hs_yj751_pd_appshow_addr.wirlesss4gErrCode`) _(disabled)_ 12 | - Wireless 4G SIM ID (`hs_yj751_pd_appshow_addr.simIccid`) _(disabled)_ 13 | - Internet Connection Type (`hs_yj751_pd_appshow_addr.wireless4GSta`) _(disabled)_ 14 | - Error Code (`hs_yj751_pd_appshow_addr.sysErrCode`) 15 | - Total In Power (`hs_yj751_pd_appshow_addr.wattsInSum`) (energy: _[Device Name]_ Total In Energy) 16 | - Total Out Power (`hs_yj751_pd_appshow_addr.wattsOutSum`) (energy: _[Device Name]_ Total Out Energy) 17 | - Power I/O Port Input Power (`hs_yj751_pd_appshow_addr.inAc5p8Pwr`) (energy: _[Device Name]_ Energy I/O Port Input Energy) 18 | - Power I/O Port Input Current (`hs_yj751_pd_backend_addr.inAc5p8Amp`) _(disabled)_ 19 | - Power I/O Port Input Voltage (`hs_yj751_pd_backend_addr.inAc5p8Vol`) _(disabled)_ 20 | - Power I/O Port Output Power (`hs_yj751_pd_appshow_addr.outAc5p8Pwr`) (energy: _[Device Name]_ Energy I/O Port Output Energy) 21 | - Power I/O Port Output Current (`hs_yj751_pd_backend_addr.outAc5p8Amp`) _(disabled)_ 22 | - Power I/O Port Output Voltage (`hs_yj751_pd_backend_addr.outAc5p8Vol`) _(disabled)_ 23 | - Power I/O Port Input Type (`hs_yj751_pd_appshow_addr.access5p8InType`) 24 | - AC In Power (`hs_yj751_pd_appshow_addr.inAcC20Pwr`) (energy: _[Device Name]_ AC In Energy) 25 | - AC In Current (`hs_yj751_pd_backend_addr.inAcC20Amp`) _(disabled)_ 26 | - AC In Volts (`hs_yj751_pd_backend_addr.inAcC20Vol`) _(disabled)_ 27 | - USB (1) Out Power (`hs_yj751_pd_appshow_addr.outUsb1Pwr`) (energy: _[Device Name]_ USB (1) Out Energy) 28 | - USB (2) Out Power (`hs_yj751_pd_appshow_addr.outUsb2Pwr`) (energy: _[Device Name]_ USB (2) Out Energy) 29 | - Type-C (1) Out Power (`hs_yj751_pd_appshow_addr.outTypec1Pwr`) (energy: _[Device Name]_ Type-C (1) Out Energy) 30 | - Type-C (2) Out Power (`hs_yj751_pd_appshow_addr.outTypec2Pwr`) (energy: _[Device Name]_ Type-C (2) Out Energy) 31 | - Solar (1) In Power (`hs_yj751_pd_appshow_addr.inHvMpptPwr`) (energy: _[Device Name]_ Solar (1) In Energy) 32 | - Solar (1) In Amps (`hs_yj751_pd_backend_addr.inHvMpptAmp`) _(disabled)_ 33 | - Solar (1) In Volts (`hs_yj751_pd_backend_addr.inHvMpptVol`) _(disabled)_ 34 | - Solar (2) In Power (`hs_yj751_pd_appshow_addr.inLvMpptPwr`) (energy: _[Device Name]_ Solar (2) In Energy) 35 | - Solar (2) In Amps (`hs_yj751_pd_backend_addr.inLvMpptAmp`) _(disabled)_ 36 | - Solar (2) In Volts (`hs_yj751_pd_backend_addr.inLvMpptVol`) _(disabled)_ 37 | - AC (1) Out Power (`hs_yj751_pd_appshow_addr.outAcL11Pwr`) (energy: _[Device Name]_ AC (1) Out Energy) 38 | - AC (1) Out Current (`hs_yj751_pd_backend_addr.outAcL11Amp`) _(disabled)_ 39 | - AC (1) Out Voltage (`hs_yj751_pd_backend_addr.outAcL11Vol`) _(disabled)_ 40 | - AC (1) Out Frequency (`hs_yj751_pd_backend_addr.outAcL11Pf`) _(disabled)_ 41 | - AC (2) Out Power (`hs_yj751_pd_appshow_addr.outAcL12Pwr`) (energy: _[Device Name]_ AC (2) Out Energy) 42 | - AC (2) Out Current (`hs_yj751_pd_backend_addr.outAcL12Amp`) _(disabled)_ 43 | - AC (2) Out Voltage (`hs_yj751_pd_backend_addr.outAcL12Vol`) _(disabled)_ 44 | - AC (2) Out Frequency (`hs_yj751_pd_backend_addr.outAcL12Pf`) _(disabled)_ 45 | - AC (3) Out Power (`hs_yj751_pd_appshow_addr.outAcL21Pwr`) (energy: _[Device Name]_ AC (3) Out Energy) 46 | - AC (3) Out Current (`hs_yj751_pd_backend_addr.outAcL21Amp`) _(disabled)_ 47 | - AC (3) Out Voltage (`hs_yj751_pd_backend_addr.outAcL21Vol`) _(disabled)_ 48 | - AC (3) Out Frequency (`hs_yj751_pd_backend_addr.outAcL21Pf`) _(disabled)_ 49 | - AC (4) Out Power (`hs_yj751_pd_appshow_addr.outAcL22Pwr`) (energy: _[Device Name]_ AC (4) Out Energy) 50 | - AC (4) Out Current (`hs_yj751_pd_backend_addr.outAcL22Amp`) _(disabled)_ 51 | - AC (4) Out Voltage (`hs_yj751_pd_backend_addr.outAcL22Vol`) _(disabled)_ 52 | - AC (4) Out Frequency (`hs_yj751_pd_backend_addr.outAcL22Pf`) _(disabled)_ 53 | - AC (5) Out Power (`hs_yj751_pd_appshow_addr.outAcL14Pwr`) (energy: _[Device Name]_ AC (5) Out Energy) 54 | - AC (5) Out Current (`hs_yj751_pd_backend_addr.outAcL14Amp`) _(disabled)_ 55 | - AC (5) Out Voltage (`hs_yj751_pd_backend_addr.outAcL14Vol`) _(disabled)_ 56 | - AC (5) Out Frequency (`hs_yj751_pd_backend_addr.outAcL14Pf`) _(disabled)_ 57 | - AC (6) Out Power (`hs_yj751_pd_appshow_addr.outAcTtPwr`) (energy: _[Device Name]_ AC (6) Out Energy) 58 | - AC (6) Out Current (`hs_yj751_pd_backend_addr.outAcTtAmp`) _(disabled)_ 59 | - AC (6) Out Voltage (`hs_yj751_pd_backend_addr.outAcTtVol`) _(disabled)_ 60 | - AC (6) Out Frequency (`hs_yj751_pd_backend_addr.outAcTtPf`) _(disabled)_ 61 | - DC Anderson Out Power (`hs_yj751_pd_appshow_addr.outAdsPwr`) (energy: _[Device Name]_ DC Anderson Out Energy) 62 | 63 | *Switches* 64 | - Wireless 4G Enabled (`hs_yj751_pd_appshow_addr.wireless4gOn` -> `{"sn": "SN", "cmdCode": "YJ751_PD_4G_SWITCH_SET", "params": {"en4GOpen": "VALUE"}}`) 65 | - Battery Auto-Heating Enabled (`hs_yj751_pd_app_set_info_addr.bmsModeSet` -> `{"sn": "SN", "cmdCode": "YJ751_PD_BP_HEAT_SET", "params": {"enBpHeat": "VALUE"}}`) 66 | - DC Mode (`hs_yj751_pd_appshow_addr.showFlag.6` -> `{"sn": "SN", "cmdCode": "YJ751_PD_DC_SWITCH_SET", "params": {"enable": "VALUE"}}`) 67 | 68 | *Sliders (numbers)* 69 | - Min Discharge Level (`hs_yj751_pd_app_set_info_addr.dsgMinSoc` -> `{"sn": "SN", "cmdCode": "YJ751_PD_DSG_SOC_MIN_SET", "params": {"minDsgSoc": "VALUE"}}` [0 - 30]) 70 | - Max Charge Level (`hs_yj751_pd_app_set_info_addr.chgMaxSoc` -> `{"sn": "SN", "cmdCode": "YJ751_PD_CHG_SOC_MAX_SET", "params": {"maxChgSoc": "VALUE"}}` [50 - 100]) 71 | - AC Charging Power (`hs_yj751_pd_app_set_info_addr.chgC20SetWatts` -> `{"sn": "SN", "cmdCode": "YJ751_PD_AC_CHG_SET", "params": {"chgC20Watts": "VALUE"}}` [600 - 1800]) 72 | - Power I/O Port Charging Power (`hs_yj751_pd_app_set_info_addr.chg5p8SetWatts` -> `{"sn": "SN", "cmdCode": "YJ751_PD_AC_CHG_SET", "params": {"chg5p8Watts": "VALUE"}}` [600 - 7200]) 73 | 74 | *Selects* 75 | 76 | 77 | --------------------------------------------------------------------------------