Repository: rabits/ha-ef-ble
Pull request #6: Add support for River 3 devices, clean up sensor code
Author: login: GnoX
Labels: name: enhancement
description: New feature or request
Created: 2025-03-01T09:08:01Z | Merged: 2025-03-02T18:40:28Z

This PR adds basic support for River 3 adding 16 sensors. It also cleans up `sensor.py`  taking inspiration from [switchbot](https://github.com/home-assistant/core/blob/dev/homeassistant/components/switchbot/sensor.py#L30) integration.

Added sensors:
![image](https://github.com/user-attachments/assets/a59f76bc-53d5-47fd-b6df-13e95899e5e7)



Diff:
diff --git a/.github/workflows/validate-code-style.yaml b/.github/workflows/validate-code-style.yaml
index 80846b9c..9efc7c75 100644
--- a/.github/workflows/validate-code-style.yaml
+++ b/.github/workflows/validate-code-style.yaml
@@ -17,4 +17,4 @@ jobs:
       - run: python3 -m pip install black
 
       - name: Black style validation
-        run: black .
+        run: black --check .
diff --git a/README.md b/README.md
index 6f958ec0..4b6adaec 100644
--- a/README.md
+++ b/README.md
@@ -10,6 +10,7 @@ number of EcoFlow devices through bluetooth and monitor their status / control p
 Recognized devices:
 * Smart Home Panel 2 (EF-HD3####, FW Version: 4.0.0.122, WiFi Version: 2.0.1.20)
 * Delta Pro Ultra (EF-YJ####, FW Version: 5.0.0.25, WiFi Version: 2.0.2.4)
+* River 3, River 3 Plus (EF-R3####, FW Version: 1.0.0.0)
 
 **NOTICE**: this integration utilizes Bluetooth LE of the EF device, which is supporting just one
 connection at a time - so if you want to manage the device through BLE from your phone, you will
diff --git a/custom_components/ef_ble/binary_sensor.py b/custom_components/ef_ble/binary_sensor.py
index 33879fe6..4d3ba9e6 100644
--- a/custom_components/ef_ble/binary_sensor.py
+++ b/custom_components/ef_ble/binary_sensor.py
@@ -3,15 +3,12 @@
 import logging
 
 from homeassistant.components.binary_sensor import BinarySensorDeviceClass
-
 from homeassistant.const import EntityCategory
 from homeassistant.core import HomeAssistant
-from homeassistant.helpers.entity import Entity
 from homeassistant.helpers.entity_platform import AddEntitiesCallback
 
 from . import DeviceConfigEntry
-from .sensor import SensorBase
-from .const import DOMAIN
+from .sensor import EcoflowSensor
 
 _LOGGER = logging.getLogger(__name__)
 
@@ -26,21 +23,21 @@ async def async_setup_entry(
 
     new_sensors = []
     if hasattr(device, "error_happened"):
-        new_sensors.append(ErrorDetectedSensor(device))
+        new_sensors.append(ErrorDetectedSensor(device, "error_happened"))
 
     if new_sensors:
         async_add_entities(new_sensors)
 
 
-class ErrorDetectedSensor(SensorBase):
+class ErrorDetectedSensor(EcoflowSensor):
     """Represents that problem happened on device."""
 
     device_class = BinarySensorDeviceClass.PROBLEM
     _attr_entity_category = EntityCategory.DIAGNOSTIC
 
-    def __init__(self, device):
+    def __init__(self, device, sensor):
         """Initialize the sensor."""
-        super().__init__(device)
+        super().__init__(device, sensor)
 
         self._attr_unique_id = f"{self._device.name}_error"
         self._attr_name = "Error"
diff --git a/custom_components/ef_ble/config_flow.py b/custom_components/ef_ble/config_flow.py
index 60f4d6cd..1502cf2e 100644
--- a/custom_components/ef_ble/config_flow.py
+++ b/custom_components/ef_ble/config_flow.py
@@ -3,27 +3,24 @@
 from __future__ import annotations
 
 import logging
-
 from typing import Any
 
 import voluptuous as vol
-
 from homeassistant.components.bluetooth import (
     BluetoothServiceInfoBleak,
     async_discovered_service_info,
 )
 from homeassistant.config_entries import (
+    CONN_CLASS_LOCAL_PUSH,
     ConfigFlow,
     ConfigFlowResult,
     OptionsFlow,
-    CONN_CLASS_LOCAL_PUSH,
 )
 from homeassistant.const import CONF_ADDRESS
-from homeassistant.helpers import config_validation as cv
 from homeassistant.core import callback
 
 from . import eflib
-from .const import DOMAIN, CONF_USER_ID
+from .const import CONF_USER_ID, DOMAIN
 
 _LOGGER = logging.getLogger(__name__)
 
@@ -78,6 +75,7 @@ async def async_step_bluetooth_confirm(
             data_schema=vol.Schema(
                 {
                     vol.Required(CONF_USER_ID): str,
+                    vol.Required(CONF_ADDRESS, default=device.address): str,
                 }
             ),
         )
diff --git a/custom_components/ef_ble/eflib/commands.py b/custom_components/ef_ble/eflib/commands.py
new file mode 100644
index 00000000..3a64edf9
--- /dev/null
+++ b/custom_components/ef_ble/eflib/commands.py
@@ -0,0 +1,100 @@
+import asyncio
+from dataclasses import dataclass
+import logging
+import struct
+import time
+
+from .devicebase import DeviceBase
+from .packet import Packet
+from .pb import utc_sys_pb2_v4 as utc_sys_pb2
+
+_LOGGER = logging.getLogger(__name__)
+
+
+@dataclass
+class TimeCommands:
+    device: DeviceBase
+
+    async def sendUtcTime(self):
+        """Send UTC time as unix timestamp seconds through PB"""
+        _LOGGER.debug("%s: sendUtcTime", self.device.address)
+
+        utcs = utc_sys_pb2.SysUTCSync()
+        utcs.sys_utc_time = int(time.time())
+        payload = utcs.SerializeToString()
+        packet = Packet(0x21, 0x0B, 0x01, 0x55, payload, 0x01, 0x01, 0x13)
+
+        await self.device._conn.sendPacket(packet)
+
+    async def sendRTCRespond(self):
+        """Send RTC timestamp seconds and TZ as respond to device's request"""
+        _LOGGER.debug("%s: sendRTCRespond", self.device.address)
+
+        # Building payload
+        tz_offset = (
+            (time.timezone if (time.localtime().tm_isdst == 0) else time.altzone)
+            / 60
+            / 60
+            * -1
+        )
+        tz_maj = int(tz_offset)
+        tz_min = int((tz_offset - tz_maj) * 100)
+        time_sec = int(time.time())
+        payload = (
+            struct.pack("<L", time_sec)
+            + struct.pack("<b", tz_maj)
+            + struct.pack("<b", tz_min)
+        )
+
+        # Forming packet
+        packet = Packet(
+            0x21,
+            0x35,
+            0x01,
+            Packet.NET_BLE_COMMAND_CMD_SET_RET_TIME,
+            payload,
+            0x01,
+            0x01,
+            0x03,
+        )
+
+        await self.device._conn.sendPacket(packet)
+
+    async def sendRTCCheck(self):
+        """Send command to check RTC of the device"""
+        _LOGGER.debug("%s: sendRTCCheck", self.device.address)
+
+        # Building payload
+        tz_offset = (
+            (time.timezone if (time.localtime().tm_isdst == 0) else time.altzone)
+            / 60
+            / 60
+            * -1
+        )
+        tz_maj = int(tz_offset)
+        tz_min = int((tz_offset - tz_maj) * 100)
+        time_sec = int(time.time())
+        payload = (
+            struct.pack("<L", time_sec)
+            + struct.pack("<b", tz_maj)
+            + struct.pack("<b", tz_min)
+        )
+
+        # Forming packet
+        packet = Packet(
+            0x21,
+            0x35,
+            0x01,
+            Packet.NET_BLE_COMMAND_CMD_CHECK_RET_TIME,
+            payload,
+            0x01,
+            0x01,
+            0x03,
+        )
+
+        await self.device._conn.sendPacket(packet)
+
+    def async_send_all(self):
+        asyncio.create_task(self.sendUtcTime())
+        asyncio.create_task(self.sendRTCRespond())
+        asyncio.create_task(self.sendRTCCheck())
diff --git a/custom_components/ef_ble/eflib/device_properties.py b/custom_components/ef_ble/eflib/device_properties.py
new file mode 100644
index 00000000..4a25f032
--- /dev/null
+++ b/custom_components/ef_ble/eflib/device_properties.py
@@ -0,0 +1,227 @@
+import abc
+from collections.abc import Callable, Sequence
+from dataclasses import dataclass
+from typing import Any
+
+from google.protobuf.message import Message
+
+
+class UpdatableProps:
+    """
+    Mixin for augmenting device classes with advanced properties
+
+    If any property changed its value after calling ``update_fields``, attribute
+    ``updated`` is set to True and all updated field names are added to
+    ``updated_fields``.
+
+    Attributes
+    ----------
+    updated
+        Holds True if any fields are updated in ``update_fields``
+    updated_fields
+        List of field names that were updated after calling ``update_fields``
+    """
+
+    updated: bool = False
+    updated_fields: list[str] = []
+
+    _pb_field_names: list[str] = []
+    _pb_list_field_names: list[str] = []
+    _list_field_name_to_field: dict[str, "ProtobufListField"] = {}
+
+    def update_fields(self, message: Message) -> list[str]:
+        """
+        Update all defined fields and return names of updated fields
+
+        Parameters
+        ----------
+        message
+            Parsed protobuf message to assign to updated fields
+        """
+        self.updated = False
+        self.updated_fields = []
+
+        for field_name in self._pb_field_names:
+            setattr(self, field_name, message)
+
+        for list_field_name, field in self._list_field_name_to_field.items():
+            if not message.HasField(list_field_name):
+                continue
+
+            for item in field.get_list(getattr(message, list_field_name)):
+                for pb_list_field_name in self._pb_list_field_names:
+                    setattr(self, pb_list_field_name, item)
+
+        return self.updated_fields
+
+
+@dataclass(kw_only=True)
+class Field[T]:
+    """
+    Descriptor for updating values only if they changed
+
+    Using this field is basically the same as the following code:
+
+        class Device:
+            _field = None
+
+            @property
+            def field(self):
+                return self._field
+
+            def parse(self):
+                value = parse_value()
+                if value != self._field:
+                    self._field = value
+                    self.updated = True
+                    self.updated_fields.append("field")
+    """
+
+    def __set_name__(self, owner: type[UpdatableProps], name: str):
+        self.public_name = name
+        self.private_name = f"_{name}"
+
+    def __set__(self, instance: UpdatableProps, value: Any):
+        if not isinstance(instance, UpdatableProps):
+            raise TypeError(
+                f"Descriptor {self.__class__.__name__} can only be used on subclasses "
+                f"of {UpdatableProps.__name__}"
+            )
+
+        if value == getattr(instance, self.public_name):
+            return
+
+        setattr(instance, self.private_name, value)
+        instance.updated = True
+        instance.updated_fields.append(self.public_name)
+
+    def __get__(
+        self, instance: UpdatableProps, owner: type[UpdatableProps]
+    ) -> T | None:
+        return getattr(instance, self.private_name, None)
+
+
+@dataclass
+class ProtobufField[T](Field[T]):
+    """
+    Descriptor for field that assigns value from a protobuf message
+
+    Setter first checks if message contains field named as value of `pb_field_name` and
+    assigns it if it does, otherwise skips assignment without error.
+
+    If value other than protocol buffer message is passed to setter, TypeError is
+    raised.
+
+    Usage::
+
+        class Device(UpdatableProps):
+            battery_level = ProtobufField[int]("soc")
+
+            def parse(self):
+                ...
+                message = protobuf_cls()
+                message.ParseFromString(payload)
+
+                self.update_fields(message)
+
+                for field in self.updated_fields:
+                    self.callback(field)
+
+    The code above defines field ``battery_level`` that retreives field ``soc`` from
+    provided parsed protobuf message. If the value in protobuf is different from the
+    current value, `updated_fields` will contain name of the updated field which can
+    be used to run callbacks only on updated values.
+
+    Attributes
+    ----------
+    pb_field_name
+        Name of field in protobuf message
+    transform_value
+        Callable that accepts raw value from protobuf message and returns transformed
+        value, by default returns raw value
+    """
+
+    pb_field_name: str
+    transform_value: Callable[[T], T] = lambda x: x
+
+    def __set_name__(self, owner: type[UpdatableProps], name: str):
+        super().__set_name__(owner, name)
+
+        owner._pb_field_names.append(self.public_name)
+
+    def __set__(self, instance: UpdatableProps, value: Any):
+        if not isinstance(value, Message):
+            raise TypeError(
+                f"Can only set value from protobuf message but received: {value}"
+            )
+
+        if not value.HasField(self.pb_field_name):
+            return
+
+        value = self.transform_value(getattr(value, self.pb_field_name))
+        super().__set__(instance, value)
+
+
+@dataclass
+class ProtobufListField[T](Field[T], abc.ABC):
+    """
+    Abstract descriptor for repeated fields from protobuf message
+
+    This descriptor can be explained with the following snippet:
+
+        if not message.HasField(field.list_name):
+            continue
+
+        for item in field.get_list(getattr(message, field.list_name)):
+            if not field.should_update(message):
+                continue
+
+            value = field.get_item_value(message)
+            if value is None:
+                continue
+
+            setattr(self, field.public_name, item)
+
+    Attributes
+    ----------
+    pb_field_name
+        Name of compound field to get from parsed list
+    transform_value
+        Callable that accepts raw value for each item in repeated protobuf type and
+        returns transformed value, by default returns value without change
+    """
+
+    pb_field_name: str
+    transform_value: Callable[[T], T] = lambda x: x
+
+    @property
+    @abc.abstractmethod
+    def list_name(self) -> str:
+        """Top level protobuf message attribute name"""
+
+    def get_list(self, message: Any) -> Sequence[Message]:
+        """Get list from repeated message"""
+        return message
+
+    @abc.abstractmethod
+    def get_item_value(self, message: Message) -> T | None:
+        """Get final value from parsed list item"""
+
+    def should_update(self, message: Any) -> bool:
+        """Return True if field should be updated from passed in message"""
+        return False
+
+    def __set_name__(self, owner: type[UpdatableProps], name: str):
+        super().__set_name__(owner, name)
+        owner._list_field_name_to_field[self.list_name] = self
+        owner._pb_list_field_names.append(name)
+
+    def __set__(self, instance: UpdatableProps, value: Any):
+        if not self.should_update(value):
+            return
+
+        value = self.get_item_value(value)
+        if value is None:
+            return
+
+        super().__set__(instance, self.transform_value(value))
diff --git a/custom_components/ef_ble/eflib/devicebase.py b/custom_components/ef_ble/eflib/devicebase.py
index a22501a5..3a659806 100644
--- a/custom_components/ef_ble/eflib/devicebase.py
+++ b/custom_components/ef_ble/eflib/devicebase.py
@@ -103,7 +103,7 @@ async def waitDisconnected(self):
         await self._conn.waitDisconnected()
 
     def register_callback(
-        self, callback: Callable[[], None], propname: str | None
+        self, callback: Callable[[], None], propname: str | None = None
     ) -> None:
         """Register callback, called when Device changes state."""
         if propname is None:
@@ -114,7 +114,7 @@ def register_callback(
             ).union([callback])
 
     def remove_callback(
-        self, callback: Callable[[], None], propname: str | None
+        self, callback: Callable[[], None], propname: str | None = None
     ) -> None:
         """Remove previously registered callback."""
         if propname is None:
diff --git a/custom_components/ef_ble/eflib/devices/dpu.py b/custom_components/ef_ble/eflib/devices/dpu.py
index d766c4e8..9b6b22bd 100644
--- a/custom_components/ef_ble/eflib/devices/dpu.py
+++ b/custom_components/ef_ble/eflib/devices/dpu.py
@@ -73,7 +73,8 @@ def battery_level(self) -> int | None:
     async def data_parse(self, packet: Packet) -> bool:
         """Processing the incoming notifications from the device"""
         processed = False
-        updated = False
+        updated_props: list[str] = []
+
         if packet.src == 0x02 and packet.cmdSet == 0x02:
             if packet.cmdId == 0x01:  # Ping
                 await self._conn.replyPacket(packet)
@@ -87,33 +88,33 @@ async def data_parse(self, packet: Packet) -> bool:
                 if p.HasField("in_hv_mppt_pwr"):
                     if self._data_hv_solar_power != p.in_hv_mppt_pwr:
                         self._data_hv_solar_power = p.in_hv_mppt_pwr
-                        updated = True
+                        updated_props.append("hv_solar_power")
                 elif self._data_hv_solar_power != 0:
                     self._data_hv_solar_power = 0
-                    updated = True
+                    updated_props.append("hv_solar_power")
 
                 if p.HasField("in_lv_mppt_pwr"):
                     if self._data_lv_solar_power != p.in_lv_mppt_pwr:
                         self._data_lv_solar_power = p.in_lv_mppt_pwr
-                        updated = True
+                        updated_props.append("lv_solar_power")
                 elif self._data_lv_solar_power != 0:
                     self._data_lv_solar_power = 0
-                    updated = True
+                    updated_props.append("lv_solar_power")
 
                 if p.HasField("watts_in_sum"):
                     if self._data_input_power != p.watts_in_sum:
                         self._data_input_power = p.watts_in_sum
-                        updated = True
+                        updated_props.append("input_power")
 
                 if p.HasField("watts_out_sum"):
                     if self._data_output_power != p.watts_out_sum:
                         self._data_output_power = p.watts_out_sum
-                        updated = True
+                        updated_props.append("output_power")
 
                 if p.HasField("soc"):
                     if self._data_battery_level != p.soc:
                         self._data_battery_level = p.soc
-                        updated = True
+                        updated_props.append("battery_level")
 
                 processed = True
 
@@ -134,9 +135,8 @@ async def data_parse(self, packet: Packet) -> bool:
                 asyncio.create_task(self.sendRTCCheck())
             processed = True
 
-        if updated:
-            for callback in self._callbacks:
-                callback()
+        for prop_name in updated_props:
+            self.update_callback(prop_name)
 
         return processed
 
diff --git a/custom_components/ef_ble/eflib/devices/river3.py b/custom_components/ef_ble/eflib/devices/river3.py
new file mode 100644
index 00000000..a3b5a7d2
--- /dev/null
+++ b/custom_components/ef_ble/eflib/devices/river3.py
@@ -0,0 +1,123 @@
+from collections.abc import Sequence
+import logging
+from typing import Any
+
+from bleak.backends.device import BLEDevice
+from bleak.backends.scanner import AdvertisementData
+from google.protobuf.message import Message
+
+from ..commands import TimeCommands
+from ..device_properties import Field, ProtobufField, ProtobufListField, UpdatableProps
+from ..devicebase import DeviceBase
+from ..packet import Packet
+from ..pb import pr705_pb2
+
+_LOGGER = logging.getLogger(__name__)
+
+
+class _StatField[T](ProtobufListField[T]):
+    _stat_enum = pr705_pb2.STATISTICS_OBJECT  # type: ignore[attr-defined]
+
+    @property
+    def list_name(self):
+        return "display_statistics_sum"
+
+    def get_list(self, message: Any) -> Sequence[Message]:
+        return message.list_info
+
+    def should_update(self, message: Any) -> bool:
+        return self._stat_enum.Name(message.statistics_object) == self.pb_field_name
+
+    def get_item_value(self, message: Any) -> T | None:
+        return message.statistics_content
+
+
+def _out_power(x):
+    return -round(x, 2) if x != 0 else 0
+
+
+class Device(DeviceBase, UpdatableProps):
+    """River 3"""
+
+    SN_PREFIX = b"R6"
+    NAME_PREFIX = "EF-R3"
+
+    battery_level = ProtobufField[int]("bms_batt_soc")
+
+    ac_input_power = ProtobufField[float]("pow_get_ac_in")
+    ac_input_energy = _StatField[int]("STATISTICS_OBJECT_AC_IN_ENERGY")
+
+    ac_output_power = ProtobufField[float]("pow_get_ac_out", _out_power)
+    ac_output_energy = _StatField[int]("STATISTICS_OBJECT_AC_OUT_ENERGY")
+
+    input_power = ProtobufField[int]("pow_in_sum_w")
+    input_energy = Field[int]()
+
+    output_power = ProtobufField[int]("pow_out_sum_w")
+    output_energy = Field[int]()
+
+    dc_input_power = ProtobufField[float]("pow_get_pv")
+    dc_input_energy = _StatField[int]("STATISTICS_OBJECT_PV_IN_ENERGY")
+
+    dc12v_output_power = ProtobufField[float]("pow_get_12v")
+    dc12v_output_energy = _StatField[int]("STATISTICS_OBJECT_DC12V_OUT_ENERGY")
+
+    usbc_output_power = ProtobufField[float]("pow_get_typec1", _out_power)
+    usbc_output_energy = _StatField[int]("STATISTICS_OBJECT_TYPEC_OUT_ENERGY")
+
+    usba_output_power = ProtobufField[float]("pow_get_qcusb1", _out_power)
+    usba_output_energy = _StatField[int]("STATISTICS_OBJECT_USBA_OUT_ENERGY")
+
+    def __init__(
+        self, ble_dev: BLEDevice, adv_data: AdvertisementData, sn: str
+    ) -> None:
+        super().__init__(ble_dev, adv_data, sn)
+        self._time_commands = TimeCommands(self)
+
+    @staticmethod
+    def check(sn):
+        return sn.startswith(Device.SN_PREFIX)
+
+    async def packet_parse(self, data: bytes) -> Packet:
+        return Packet.fromBytes(data, is_xor=True)
+
+    async def data_parse(self, packet: Packet):
+        processed = False
+
+        if packet.src == 0x02 and packet.cmdSet == 0xFE and packet.cmdId == 0x15:
+            p = pr705_pb2.DisplayPropertyUpload()
+            p.ParseFromString(packet.payload)
+            _LOGGER.debug("%s: %s: Parsed data: %r", self.address, self.name, packet)
+            self.update_fields(p)
+            processed = True
+        elif (
+            packet.src == 0x35
+            and packet.cmdSet == 0x01
+            and packet.cmdId == Packet.NET_BLE_COMMAND_CMD_SET_RET_TIME
+        ):
+            # Device requested for time and timezone offset, so responding with that
+            # otherwise it will not be able to send us predictions and config data
+            if len(packet.payload) == 0:
+                self._time_commands.async_send_all()
+            processed = True
+
+        if self.ac_input_energy is not None and self.dc_input_energy is not None:
+            self.input_energy = self.ac_input_energy + self.dc_input_energy
+
+        if (
+            self.ac_output_energy is not None
+            and self.usba_output_energy is not None
+            and self.usbc_output_energy is not None
+            and self.dc12v_output_energy is not None
+        ):
+            self.output_energy = (
+                self.ac_output_energy
+                + self.usba_output_energy
+                + self.usbc_output_energy
+                + self.dc12v_output_energy
+            )
+
+        for field_name in self.updated_fields:
+            self.update_callback(field_name)
+
+        return processed
diff --git a/custom_components/ef_ble/eflib/devices/shp2.py b/custom_components/ef_ble/eflib/devices/shp2.py
index 7129e452..f07e7ce8 100644
--- a/custom_components/ef_ble/eflib/devices/shp2.py
+++ b/custom_components/ef_ble/eflib/devices/shp2.py
@@ -85,7 +85,7 @@ def error_happened(self) -> bool:
     async def data_parse(self, packet: Packet) -> bool:
         """Processing the incoming notifications from the device"""
         processed = False
-        updated = False
+        updated_fields = []
         if packet.src == 0x0B and packet.cmdSet == 0x0C:
             if (
                 packet.cmdId == 0x01
@@ -102,31 +102,31 @@ async def data_parse(self, packet: Packet) -> bool:
                     for i, w in enumerate(p.load_info.hall1_watt):
                         if self._data_circuit_power[i] != w:
                             self._data_circuit_power[i] = w
-                            updated = True
+                            updated_fields.append(f"circuit_power_{i}")
                     for i, a in enumerate(p.load_info.hall1_curr):
                         if self._data_circuit_current[i] != a:
                             self._data_circuit_current[i] = a
-                            updated = True
+                            updated_fields.append(f"circuit_current_{i}")
 
                 if p.HasField("watt_info"):
                     wi = p.watt_info
                     if wi.HasField("grid_watt"):
                         if self._data_grid_power != wi.grid_watt:
                             self._data_grid_power = wi.grid_watt
-                            updated = True
+                            updated_fields.append("grid_power")
                     elif self._data_grid_power != 0:
                         self._data_grid_power = 0
-                        updated = True
+                        updated_fields.append("grid_power")
 
                     for i, w in enumerate(wi.ch_watt):
                         if self._data_channel_power[i] != w:
                             self._data_channel_power[i] = w
-                            updated = True
+                            updated_fields.append(f"channel_power_{i}")
 
                     if wi.HasField("all_hall_watt"):
                         if self._data_in_use_power != wi.all_hall_watt:
                             self._data_in_use_power = wi.all_hall_watt
-                            updated = True
+                            updated_fields.append("in_use_power")
 
                 processed = True
 
@@ -155,7 +155,6 @@ async def data_parse(self, packet: Packet) -> bool:
                                     errors,
                                 )
                             self._data_error_count = len(errors)
-                            updated = True
 
                     if info.HasField("backup_bat_per"):
                         self.battery_level = info.backup_bat_per
@@ -195,9 +194,8 @@ async def data_parse(self, packet: Packet) -> bool:
             asyncio.create_task(self.setConfigFlag(True))
             processed = True
 
-        if updated:
-            for callback in self._callbacks:
-                callback()
+        for prop_name in updated_fields:
+            self.update_callback(prop_name)
 
         return processed
 
diff --git a/custom_components/ef_ble/eflib/encpacket.py b/custom_components/ef_ble/eflib/encpacket.py
index 93df1033..a3f1332c 100644
--- a/custom_components/ef_ble/eflib/encpacket.py
+++ b/custom_components/ef_ble/eflib/encpacket.py
@@ -8,7 +8,7 @@
 class EncPacket:
     """Outside wrapper of Packet that actually transferred through the BLE channel"""
 
-    PREFIX = b"\x5A\x5A"
+    PREFIX = b"\x5a\x5a"
 
     FRAME_TYPE_COMMAND = 0x00
     FRAME_TYPE_PROTOCOL = 0x01
diff --git a/custom_components/ef_ble/eflib/packet.py b/custom_components/ef_ble/eflib/packet.py
index 8aeb65f8..a248abf4 100644
--- a/custom_components/ef_ble/eflib/packet.py
+++ b/custom_components/ef_ble/eflib/packet.py
@@ -9,7 +9,7 @@
 class Packet:
     """Needed to parse and make the internal packet structure"""
 
-    PREFIX = b"\xAA"
+    PREFIX = b"\xaa"
 
     NET_BLE_COMMAND_CMD_CHECK_RET_TIME = 0x53
     NET_BLE_COMMAND_CMD_SET_RET_TIME = 0x52
diff --git a/custom_components/ef_ble/eflib/pb/pr705_pb2.py b/custom_components/ef_ble/eflib/pb/pr705_pb2.py
new file mode 100644
index 00000000..76b614be
--- /dev/null
+++ b/custom_components/ef_ble/eflib/pb/pr705_pb2.py
@@ -0,0 +1,139 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: pr705.proto
+"""Generated protocol buffer code."""
+from google.protobuf.internal import builder as _builder
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import symbol_database as _symbol_database
+
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(
+    b'\n\x0bpr705.proto"\x83\x02\n\tEventPush\x12\x16\n\tevent_ver\x18\x01 \x01(\rH\x00\x88\x01\x01\x12\x16\n\tevent_seq\x18\x02 \x01(\rH\x01\x88\x01\x01\x12&\n\nevent_item\x18\x03 \x03(\x0b\x32\x12.EventPush.LogItem\x1a\x81\x01\n\x07LogItem\x12\x16\n\tunix_time\x18\x01 \x01(\rH\x00\x88\x01\x01\x12\x0f\n\x02ms\x18\x02 \x01(\rH\x01\x88\x01\x01\x12\x15\n\x08\x65vent_no\x18\x03 \x01(\rH\x02\x88\x01\x01\x12\x14\n\x0c\x65vent_detail\x18\x04 \x03(\x02\x42\x0c\n\n_unix_timeB\x05\n\x03_msB\x0b\n\t_event_noB\x0c\n\n_event_verB\x0c\n\n_event_seq"\x80\x01\n\x08\x45ventAck\x12\x13\n\x06result\x18\x01 \x01(\rH\x00\x88\x01\x01\x12\x16\n\tevent_seq\x18\x02 \x01(\rH\x01\x88\x01\x01\x12\x1b\n\x0e\x65vent_item_num\x18\x03 \x01(\rH\x02\x88\x01\x01\x42\t\n\x07_resultB\x0c\n\n_event_seqB\x11\n\x0f_event_item_num"6\n\x0eReqTouStrategy\x12\x16\n\treq_state\x18\x01 \x01(\rH\x00\x88\x01\x01\x42\x0c\n\n_req_state"c\n\x07\x43\x66gBeep\x12\x1b\n\x0e\x62\x65\x65p_act_count\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x18\n\x0b\x62\x65\x65p_act_ms\x18\x02 \x01(\rH\x01\x88\x01\x01\x42\x11\n\x0f_beep_act_countB\x0e\n\x0c_beep_act_ms"\x86\x01\n\x10\x43\x66gAcOutAlwaysOn\x12\x1e\n\x11\x61\x63_always_on_flag\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12"\n\x15\x61\x63_always_on_mini_soc\x18\x02 \x01(\rH\x01\x88\x01\x01\x42\x14\n\x12_ac_always_on_flagB\x18\n\x16_ac_always_on_mini_soc"x\n\x16\x43\x66gBmsPowerOffWriteAck\x12\x1a\n\rbms_power_off\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12\x1c\n\x0f\x62ms_power_state\x18\x02 \x01(\rH\x01\x88\x01\x01\x42\x10\n\x0e_bms_power_offB\x12\n\x10_bms_power_state"\xe5\x01\n\x0f\x43\x66gBmsPushWrite\x12\x1f\n\x12\x62ms_heartbeap_open\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12\x1c\n\x0f\x62ms_health_open\x18\x02 \x01(\x08H\x01\x88\x01\x01\x12\x1f\n\x12\x62ms_heartbeap_freq\x18\x03 \x01(\rH\x02\x88\x01\x01\x12\x1c\n\x0f\x62ms_health_freq\x18\x04 \x01(\rH\x03\x88\x01\x01\x42\x15\n\x13_bms_heartbeap_openB\x12\n\x10_bms_health_openB\x15\n\x13_bms_heartbeap_freqB\x12\n\x10_bms_health_freq"~\n\x12\x43\x66gBmsPushWriteAck\x12\x1f\n\x12\x62ms_heartbeap_open\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12\x1c\n\x0f\x62ms_health_open\x18\x02 \x01(\x08H\x01\x88\x01\x01\x42\x15\n\x13_bms_heartbeap_openB\x12\n\x10_bms_health_open"\xd0\x02\n\x10SetTimeTaskWrite\x12\x17\n\ntask_index\x18\x01 \x01(\rH\x00\x88\x01\x01\x12\x15\n\x08is_valid\x18\x02 \x01(\x08H\x01\x88\x01\x01\x12\x13\n\x06is_cfg\x18\x03 \x01(\x08H\x02\x88\x01\x01\x12\x16\n\tis_enable\x18\x04 \x01(\x08H\x03\x88\x01\x01\x12\x1a\n\rconflict_flag\x18\x05 \x01(\rH\x04\x88\x01\x01\x12\x11\n\x04type\x18\x06 \x01(\rH\x05\x88\x01\x01\x12\x16\n\ttime_mode\x18\x07 \x01(\rH\x06\x88\x01\x01\x12\x17\n\ntime_param\x18\x08 \x01(\rH\x07\x88\x01\x01\x12\x12\n\ntime_table\x18\t \x03(\rB\r\n\x0b_task_indexB\x0b\n\t_is_validB\t\n\x07_is_cfgB\x0c\n\n_is_enableB\x10\n\x0e_conflict_flagB\x07\n\x05_typeB\x0c\n\n_time_modeB\r\n\x0b_time_param"s\n\x13SetTimeTaskWriteAck\x12\x17\n\ntask_index\x18\x01 \x01(\rH\x00\x88\x01\x01\x12\x11\n\x04type\x18\x02 \x01(\rH\x01\x88\x01\x01\x12\x10\n\x03sta\x18\x03 \x01(\rH\x02\x88\x01\x01\x42\r\n\x0b_task_indexB\x07\n\x05_typeB\x06\n\x04_sta"<\n\x14GetAllTimeTaskReadck\x12$\n\ttime_task\x18\x01 \x03(\x0b\x32\x11.SetTimeTaskWrite"\x87\x01\n\x0f\x43\x66gEnergyBackup\x12\x1d\n\x10\x65nergy_backup_en\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12$\n\x17\x65nergy_backup_start_soc\x18\x02 \x01(\rH\x01\x88\x01\x01\x42\x13\n\x11_energy_backup_enB\x1a\n\x18_energy_backup_start_soc"\x81\x01\n\x0f\x43\x66gAcHvAlwaysOn\x12\x1c\n\x0f\x61\x63_hv_always_on\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12"\n\x15\x61\x63_always_on_mini_soc\x18\x02 \x01(\rH\x01\x88\x01\x01\x42\x12\n\x10_ac_hv_always_onB\x18\n\x16_ac_always_on_mini_soc"\x81\x01\n\x0f\x43\x66gAcLvAlwaysOn\x12\x1c\n\x0f\x61\x63_lv_always_on\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12"\n\x15\x61\x63_always_on_mini_soc\x18\x02 \x01(\rH\x01\x88\x01\x01\x42\x12\n\x10_ac_lv_always_onB\x18\n\x16_ac_always_on_mini_soc"j\n\x0e\x43\x66gTouStrategy\x12\x1a\n\x12tou_hours_strategy\x18\x01 \x03(\r\x12"\n\x15tou_gird_chg_stop_soc\x18\x02 \x01(\rH\x00\x88\x01\x01\x42\x18\n\x16_tou_gird_chg_stop_soc"\x81\x02\n\x13\x43\x66gRj45CommcService\x12\x1f\n\x12RJ45_commc_timeout\x18\x01 \x01(\rH\x00\x88\x01\x01\x12\x30\n#RJ45_display_property_upload_period\x18\x02 \x01(\x05H\x01\x88\x01\x01\x12\x30\n#RJ45_runtime_property_upload_period\x18\x03 \x01(\x05H\x02\x88\x01\x01\x42\x15\n\x13_RJ45_commc_timeoutB&\n$_RJ45_display_property_upload_periodB&\n$_RJ45_runtime_property_upload_period"\xcf\x01\n\x0f\x43\x66gStormPattern\x12!\n\x14storm_pattern_enable\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12$\n\x17storm_pattern_open_flag\x18\x02 \x01(\x08H\x01\x88\x01\x01\x12#\n\x16storm_pattern_end_time\x18\x03 \x01(\rH\x02\x88\x01\x01\x42\x17\n\x15_storm_pattern_enableB\x1a\n\x18_storm_pattern_open_flagB\x19\n\x17_storm_pattern_end_time"\xbe\x01\n\x1a\x43\x66gGeneratorMpptHybridMode\x12*\n\x1dgenerator_pv_hybrid_mode_open\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12-\n generator_pv_hybrid_mode_soc_max\x18\x02 \x01(\rH\x01\x88\x01\x01\x42 \n\x1e_generator_pv_hybrid_mode_openB#\n!_generator_pv_hybrid_mode_soc_max"\xaa\x01\n\x14\x43\x66gGeneratorCareMode\x12%\n\x18generator_care_mode_open\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12+\n\x1egenerator_care_mode_start_time\x18\x02 \x01(\rH\x01\x88\x01\x01\x42\x1b\n\x19_generator_care_mode_openB!\n\x1f_generator_care_mode_start_time"\xe2\x01\n\x1c\x43\x66gEnergyStrategyOperateMode\x12&\n\x19operate_self_powered_open\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12#\n\x16operate_scheduled_open\x18\x02 \x01(\x08H\x01\x88\x01\x01\x12"\n\x15operate_tou_mode_open\x18\x03 \x01(\x08H\x02\x88\x01\x01\x42\x1c\n\x1a_operate_self_powered_openB\x19\n\x17_operate_scheduled_openB\x18\n\x16_operate_tou_mode_open"\xbf\x02\n\x1dInstallmentPaymentServeBelone\x12.\n\x0fserve_middlemen\x18\x01 \x01(\x0e\x32\x10.SERVE_MIDDLEMENH\x00\x88\x01\x01\x12R\n!installment_payment_overdue_limit\x18\x02 \x01(\x0e\x32".INSTALLMENT_PAYMENT_OVERDUE_LIMITH\x01\x88\x01\x01\x12\x42\n\x19installment_payment_state\x18\x03 \x01(\x0e\x32\x1a.INSTALLMENT_PAYMENT_STATEH\x02\x88\x01\x01\x42\x12\n\x10_serve_middlemenB$\n"_installment_payment_overdue_limitB\x1c\n\x1a_installment_payment_state"\xbb\x02\n\x17InstallmentPaymentServe\x12\x42\n\x19installment_payment_state\x18\x01 \x01(\x0e\x32\x1a.INSTALLMENT_PAYMENT_STATEH\x00\x88\x01\x01\x12/\n"installment_payment_start_utc_time\x18\x02 \x01(\rH\x01\x88\x01\x01\x12\x37\n*installment_payment_overdue_limit_utc_time\x18\x03 \x01(\rH\x02\x88\x01\x01\x42\x1c\n\x1a_installment_payment_stateB%\n#_installment_payment_start_utc_timeB-\n+_installment_payment_overdue_limit_utc_time"\x1d\n\x08ResvInfo\x12\x11\n\tresv_info\x18\x01 \x03(\r"c\n\x1dResetMiddlemenDeliverySetting\x12.\n\x0fserve_middlemen\x18\x01 \x01(\x0e\x32\x10.SERVE_MIDDLEMENH\x00\x88\x01\x01\x42\x12\n\x10_serve_middlemen"\x9a\x03\n\x14PropertyUploadPeriod\x12\x30\n#display_property_full_upload_period\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x37\n*display_property_incremental_upload_period\x18\x02 \x01(\x05H\x01\x88\x01\x01\x12\x30\n#runtime_property_full_upload_period\x18\x03 \x01(\x05H\x02\x88\x01\x01\x12\x37\n*runtime_property_incremental_upload_period\x18\x04 \x01(\x05H\x03\x88\x01\x01\x42&\n$_display_property_full_upload_periodB-\n+_display_property_incremental_upload_periodB&\n$_runtime_property_full_upload_periodB-\n+_runtime_property_incremental_upload_period"\xc6\x01\n\x0ePvDcChgSetting\x12*\n\rpv_plug_index\x18\x01 \x01(\x0e\x32\x0e.PV_PLUG_INDEXH\x00\x88\x01\x01\x12.\n\x0fpv_chg_vol_spec\x18\x02 \x01(\x0e\x32\x10.PV_CHG_VOL_SPECH\x01\x88\x01\x01\x12\x1d\n\x10pv_chg_amp_limit\x18\x03 \x01(\rH\x02\x88\x01\x01\x42\x10\n\x0e_pv_plug_indexB\x12\n\x10_pv_chg_vol_specB\x13\n\x11_pv_chg_amp_limit"8\n\x12PvDcChgSettingList\x12"\n\tlist_info\x18\x01 \x03(\x0b\x32\x0f.PvDcChgSetting"\xa2\x01\n\x0cPvChgMaxItem\x12\x1c\n\x0fpv_chg_vol_type\x18\x01 \x01(\rH\x00\x88\x01\x01\x12\x1b\n\x0epv_chg_amp_max\x18\x02 \x01(\rH\x01\x88\x01\x01\x12\x1c\n\x0fpv_chg_amp_mini\x18\x03 \x01(\rH\x02\x88\x01\x01\x42\x12\n\x10_pv_chg_vol_typeB\x11\n\x0f_pv_chg_amp_maxB\x12\n\x10_pv_chg_amp_mini"6\n\x0cPvChgMaxList\x12&\n\x0fpv_chg_max_item\x18\x01 \x03(\x0b\x32\r.PvChgMaxItem"\x92\x03\n\x0eTimeTaskItemV2\x12\x17\n\ntask_index\x18\x01 \x01(\rH\x00\x88\x01\x01\x12\x13\n\x06is_cfg\x18\x02 \x01(\x08H\x01\x88\x01\x01\x12\x16\n\tis_enable\x18\x03 \x01(\x08H\x02\x88\x01\x01\x12\x1a\n\rconflict_flag\x18\x04 \x01(\rH\x03\x88\x01\x01\x12\'\n\ttime_mode\x18\x05 \x01(\x0e\x32\x0f.TIME_TASK_MODEH\x04\x88\x01\x01\x12\x17\n\ntime_param\x18\x06 \x01(\rH\x05\x88\x01\x01\x12\x17\n\ntime_table\x18\x07 \x01(\rH\x06\x88\x01\x01\x12\'\n\ttask_type\x18\x08 \x01(\x0e\x32\x0f.TIME_TASK_TYPEH\x07\x88\x01\x01\x12\x17\n\ntask_param\x18\t \x01(\rH\x08\x88\x01\x01\x42\r\n\x0b_task_indexB\t\n\x07_is_cfgB\x0c\n\n_is_enableB\x10\n\x0e_conflict_flagB\x0c\n\n_time_modeB\r\n\x0b_time_paramB\r\n\x0b_time_tableB\x0c\n\n_task_typeB\r\n\x0b_task_param"8\n\x12TimeTaskItemV2List\x12"\n\ttime_task\x18\x01 \x03(\x0b\x32\x0f.TimeTaskItemV2"\x98\x01\n\x14StatisticsRecordItem\x12\x32\n\x11statistics_object\x18\x01 \x01(\x0e\x32\x12.STATISTICS_OBJECTH\x00\x88\x01\x01\x12\x1f\n\x12statistics_content\x18\x02 \x01(\rH\x01\x88\x01\x01\x42\x14\n\x12_statistics_objectB\x15\n\x13_statistics_content"G\n\x1b\x44isplayStatisticsRecordList\x12(\n\tlist_info\x18\x01 \x03(\x0b\x32\x15.StatisticsRecordItem"G\n\x1bRuntimeStatisticsRecordList\x12(\n\tlist_info\x18\x01 \x03(\x0b\x32\x15.StatisticsRecordItem"k\n\x11\x45rrcodeRecordItem\x12\x14\n\x07\x65rrcode\x18\x01 \x01(\rH\x00\x88\x01\x01\x12\x1e\n\x11\x65rrcode_timestamp\x18\x02 \x01(\rH\x01\x88\x01\x01\x42\n\n\x08_errcodeB\x14\n\x12_errcode_timestamp":\n\x11\x45rrcodeRecordList\x12%\n\tlist_info\x18\x01 \x03(\x0b\x32\x12.ErrcodeRecordItem"\x88\x02\n\x16WirelessCoordinateList\x12\x19\n\x0c\x63onnect_flag\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12\x15\n\x08\x64\x65v_type\x18\x02 \x01(\rH\x01\x88\x01\x01\x12\x17\n\ndev_detail\x18\x03 \x01(\rH\x02\x88\x01\x01\x12\x13\n\x06\x64\x65v_sn\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x19\n\x0c\x64\x65v_firm_ver\x18\x05 \x01(\rH\x04\x88\x01\x01\x12\x19\n\x0c\x64\x65v_err_code\x18\x06 \x01(\rH\x05\x88\x01\x01\x42\x0f\n\r_connect_flagB\x0b\n\t_dev_typeB\r\n\x0b_dev_detailB\t\n\x07_dev_snB\x0f\n\r_dev_firm_verB\x0f\n\r_dev_err_code"\xb7\x33\n\x0b\x43onfigWrite\x12\x1a\n\rcfg_power_off\x18\x03 \x01(\x08H\x00\x88\x01\x01\x12\x19\n\x0c\x63\x66g_power_on\x18\x04 \x01(\x08H\x01\x88\x01\x01\x12"\n\x15reset_factory_setting\x18\x05 \x01(\rH\x02\x88\x01\x01\x12\x19\n\x0c\x63\x66g_utc_time\x18\x06 \x01(\rH\x03\x88\x01\x01\x12\x1d\n\x10\x63\x66g_utc_timezone\x18\x07 \x01(\x05H\x04\x88\x01\x01\x12\x1f\n\x08\x63\x66g_beep\x18\x08 \x01(\x0b\x32\x08.CfgBeepH\x05\x88\x01\x01\x12\x18\n\x0b\x63\x66g_beep_en\x18\t \x01(\x08H\x06\x88\x01\x01\x12 \n\x13\x63\x66g_ac_standby_time\x18\n \x01(\rH\x07\x88\x01\x01\x12 \n\x13\x63\x66g_dc_standby_time\x18\x0b \x01(\rH\x08\x88\x01\x01\x12 \n\x13\x63\x66g_screen_off_time\x18\x0c \x01(\rH\t\x88\x01\x01\x12!\n\x14\x63\x66g_dev_standby_time\x18\r \x01(\rH\n\x88\x01\x01\x12\x1a\n\rcfg_lcd_light\x18\x0e \x01(\rH\x0b\x88\x01\x01\x12\x1f\n\x12\x63\x66g_hv_ac_out_open\x18\x0f \x01(\x08H\x0c\x88\x01\x01\x12\x1f\n\x12\x63\x66g_lv_ac_out_open\x18\x10 \x01(\x08H\r\x88\x01\x01\x12\x1c\n\x0f\x63\x66g_ac_out_freq\x18\x11 \x01(\rH\x0e\x88\x01\x01\x12 \n\x13\x63\x66g_dc_12v_out_open\x18\x12 \x01(\x08H\x0f\x88\x01\x01\x12\x19\n\x0c\x63\x66g_usb_open\x18\x13 \x01(\x08H\x10\x88\x01\x01\x12\x1c\n\x0f\x63\x66g_dc_out_open\x18\x14 \x01(\x08H\x11\x88\x01\x01\x12\x34\n\x14\x63\x66g_ac_out_always_on\x18\x17 \x01(\x0b\x32\x11.CfgAcOutAlwaysOnH\x12\x88\x01\x01\x12\x1a\n\rcfg_xboost_en\x18\x19 \x01(\x08H\x13\x88\x01\x01\x12#\n\x16\x63\x66g_bypass_out_disable\x18\x1a \x01(\x08H\x14\x88\x01\x01\x12\x1e\n\x11\x63\x66g_bms_power_off\x18\x1e \x01(\x08H\x15\x88\x01\x01\x12\x19\n\x0c\x63\x66g_soc_cali\x18\x1f \x01(\rH\x16\x88\x01\x01\x12+\n\x0c\x63\x66g_bms_push\x18  \x01(\x0b\x32\x10.CfgBmsPushWriteH\x17\x88\x01\x01\x12\x1c\n\x0f\x63\x66g_max_chg_soc\x18! \x01(\rH\x18\x88\x01\x01\x12\x1c\n\x0f\x63\x66g_min_dsg_soc\x18" \x01(\rH\x19\x88\x01\x01\x12-\n\rset_time_task\x18\' \x01(\x0b\x32\x11.SetTimeTaskWriteH\x1a\x88\x01\x01\x12\x30\n\x11\x63\x66g_energy_backup\x18+ \x01(\x0b\x32\x10.CfgEnergyBackupH\x1b\x88\x01\x01\x12-\n cfg_plug_in_info_pv_l_dc_amp_max\x18\x34 \x01(\rH\x1c\x88\x01\x01\x12-\n cfg_plug_in_info_pv_h_dc_amp_max\x18\x35 \x01(\rH\x1d\x88\x01\x01\x12/\n"cfg_plug_in_info_ac_in_chg_pow_max\x18\x36 \x01(\rH\x1e\x88\x01\x01\x12-\n cfg_plug_in_info_5p8_chg_pow_max\x18\x38 \x01(\rH\x1f\x88\x01\x01\x12#\n\x16\x63\x66g_cms_oil_self_start\x18: \x01(\x08H \x88\x01\x01\x12\x1f\n\x12\x63\x66g_cms_oil_on_soc\x18; \x01(\rH!\x88\x01\x01\x12 \n\x13\x63\x66g_cms_oil_off_soc\x18< \x01(\rH"\x88\x01\x01\x12\x1e\n\x11\x63\x66g_llc_GFCI_flag\x18= \x01(\x08H#\x88\x01\x01\x12\x32\n\x13\x63\x66g_ac_hv_always_on\x18> \x01(\x0b\x32\x10.CfgAcHvAlwaysOnH$\x88\x01\x01\x12\x32\n\x13\x63\x66g_ac_lv_always_on\x18? \x01(\x0b\x32\x10.CfgAcLvAlwaysOnH%\x88\x01\x01\x12.\n\x10\x63\x66g_tou_strategy\x18\x41 \x01(\x0b\x32\x0f.CfgTouStrategyH&\x88\x01\x01\x12!\n\x14\x63\x66g_ble_standby_time\x18\x42 \x01(\rH\'\x88\x01\x01\x12\x34\n\'cfg_display_property_full_upload_period\x18\x43 \x01(\x05H(\x88\x01\x01\x12;\n.cfg_display_property_incremental_upload_period\x18\x44 \x01(\x05H)\x88\x01\x01\x12\x34\n\'cfg_runtime_property_full_upload_period\x18\x45 \x01(\x05H*\x88\x01\x01\x12;\n.cfg_runtime_property_incremental_upload_period\x18\x46 \x01(\x05H+\x88\x01\x01\x12\x30\n#active_display_property_full_upload\x18G \x01(\x08H,\x88\x01\x01\x12\x30\n#active_runtime_property_full_upload\x18H \x01(\x08H-\x88\x01\x01\x12\x39\n\x16\x63\x66g_RJ45_commc_service\x18I \x01(\x0b\x32\x14.CfgRj45CommcServiceH.\x88\x01\x01\x12\x1c\n\x0f\x63\x66g_ac_out_open\x18L \x01(\x08H/\x88\x01\x01\x12$\n\x17\x63\x66g_generator_perf_mode\x18M \x01(\rH0\x88\x01\x01\x12&\n\x19\x63\x66g_generator_engine_open\x18N \x01(\rH1\x88\x01\x01\x12&\n\x19\x63\x66g_generator_out_pow_max\x18O \x01(\rH2\x88\x01\x01\x12)\n\x1c\x63\x66g_generator_ac_out_pow_max\x18P \x01(\rH3\x88\x01\x01\x12)\n\x1c\x63\x66g_generator_dc_out_pow_max\x18Q \x01(\rH4\x88\x01\x01\x12"\n\x15\x63\x66g_generator_self_on\x18R \x01(\x08H5\x88\x01\x01\x12,\n\x1freset_generator_maintence_state\x18S \x01(\x08H6\x88\x01\x01\x12)\n\x1c\x63\x66g_fuels_liquefied_gas_type\x18T \x01(\rH7\x88\x01\x01\x12)\n\x1c\x63\x66g_fuels_liquefied_gas_uint\x18U \x01(\rH8\x88\x01\x01\x12(\n\x1b\x63\x66g_fuels_liquefied_gas_val\x18V \x01(\x02H9\x88\x01\x01\x12+\n\x1e\x63\x66g_plug_in_info_pv_dc_amp_max\x18W \x01(\rH:\x88\x01\x01\x12\x1a\n\rcfg_ups_alram\x18X \x01(\x08H;\x88\x01\x01\x12\x19\n\x0c\x63\x66g_led_mode\x18Y \x01(\rH<\x88\x01\x01\x12\x1c\n\x0f\x63\x66g_pv_chg_type\x18Z \x01(\rH=\x88\x01\x01\x12 \n\x13\x63\x66g_low_power_alarm\x18[ \x01(\rH>\x88\x01\x01\x12\x30\n\x11\x63\x66g_storm_pattern\x18] \x01(\x0b\x32\x10.CfgStormPatternH?\x88\x01\x01\x12H\n\x1e\x63\x66g_generator_mppt_hybrid_mode\x18_ \x01(\x0b\x32\x1b.CfgGeneratorMpptHybridModeH@\x88\x01\x01\x12;\n\x17\x63\x66g_generator_care_mode\x18\x61 \x01(\x0b\x32\x15.CfgGeneratorCareModeHA\x88\x01\x01\x12&\n\x19\x63\x66g_ac_energy_saving_open\x18\x63 \x01(\x08HB\x88\x01\x01\x12&\n\x19\x63\x66g_multi_bp_chg_dsg_mode\x18\x64 \x01(\rHC\x88\x01\x01\x12#\n\x16\x63\x66g_backup_reverse_soc\x18\x66 \x01(\rHD\x88\x01\x01\x12L\n cfg_energy_strategy_operate_mode\x18j \x01(\x0b\x32\x1d.CfgEnergyStrategyOperateModeHE\x88\x01\x01\x12:\n\x17\x63\x66g_sp_charger_chg_mode\x18t \x01(\x0e\x32\x14.SP_CHARGER_CHG_MODEHF\x88\x01\x01\x12\x31\n$cfg_installment_payment_serve_enable\x18w \x01(\x08HG\x88\x01\x01\x12Q\n$cfg_installment_payment_serve_belone\x18x \x01(\x0b\x32\x1e.InstallmentPaymentServeBeloneHH\x88\x01\x01\x12\x44\n\x1d\x63\x66g_installment_payment_serve\x18y \x01(\x0b\x32\x18.InstallmentPaymentServeHI\x88\x01\x01\x12$\n\x17\x63\x66g_sp_charger_chg_open\x18z \x01(\x08HJ\x88\x01\x01\x12)\n\x1c\x63\x66g_sp_charger_chg_pow_limit\x18{ \x01(\x02HK\x88\x01\x01\x12M\n reset_middlemen_delivery_setting\x18| \x01(\x0b\x32\x1e.ResetMiddlemenDeliverySettingHL\x88\x01\x01\x12\x30\n\x12\x63\x66g_ac_in_chg_mode\x18} \x01(\x0e\x32\x0f.AC_IN_CHG_MODEHM\x88\x01\x01\x12\x33\n\x15\x63\x66g_pv_dc_chg_setting\x18~ \x01(\x0b\x32\x0f.PvDcChgSettingHN\x88\x01\x01\x12\x33\n\x15\x63\x66g_time_task_v2_item\x18\x7f \x01(\x0b\x32\x0f.TimeTaskItemV2HO\x88\x01\x01\x12*\n\x1c\x61\x63tive_selected_time_task_v2\x18\x80\x01 \x01(\rHP\x88\x01\x01\x12(\n\x1a\x63\x66g_generator_low_power_en\x18\x82\x01 \x01(\x08HQ\x88\x01\x01\x12/\n!cfg_generator_low_power_threshold\x18\x83\x01 \x01(\rHR\x88\x01\x01\x12*\n\x1c\x63\x66g_generator_lpg_monitor_en\x18\x84\x01 \x01(\x08HS\x88\x01\x01\x12.\n cfg_fuels_liquefied_gas_lpg_uint\x18\x85\x01 \x01(\rHT\x88\x01\x01\x12.\n cfg_fuels_liquefied_gas_lng_uint\x18\x86\x01 \x01(\rHU\x88\x01\x01\x12!\n\x13\x63\x66g_utc_timezone_id\x18\x87\x01 \x01(\tHV\x88\x01\x01\x12\x1e\n\x10\x63\x66g_utc_set_mode\x18\x88\x01 \x01(\x08HW\x88\x01\x01\x12\x31\n#cfg_sp_charger_car_batt_vol_setting\x18\x89\x01 \x01(\rHX\x88\x01\x01\x12)\n\x1b\x63\x66g_wireless_oil_self_start\x18\x8a\x01 \x01(\x08HY\x88\x01\x01\x12%\n\x17\x63\x66g_wireless_oil_on_soc\x18\x8b\x01 \x01(\rHZ\x88\x01\x01\x12&\n\x18\x63\x66g_wireless_oil_off_soc\x18\x8c\x01 \x01(\rH[\x88\x01\x01\x12)\n\x1b\x63\x66g_output_power_off_memory\x18\x8d\x01 \x01(\x08H\\\x88\x01\x01\x42\x10\n\x0e_cfg_power_offB\x0f\n\r_cfg_power_onB\x18\n\x16_reset_factory_settingB\x0f\n\r_cfg_utc_timeB\x13\n\x11_cfg_utc_timezoneB\x0b\n\t_cfg_beepB\x0e\n\x0c_cfg_beep_enB\x16\n\x14_cfg_ac_standby_timeB\x16\n\x14_cfg_dc_standby_timeB\x16\n\x14_cfg_screen_off_timeB\x17\n\x15_cfg_dev_standby_timeB\x10\n\x0e_cfg_lcd_lightB\x15\n\x13_cfg_hv_ac_out_openB\x15\n\x13_cfg_lv_ac_out_openB\x12\n\x10_cfg_ac_out_freqB\x16\n\x14_cfg_dc_12v_out_openB\x0f\n\r_cfg_usb_openB\x12\n\x10_cfg_dc_out_openB\x17\n\x15_cfg_ac_out_always_onB\x10\n\x0e_cfg_xboost_enB\x19\n\x17_cfg_bypass_out_disableB\x14\n\x12_cfg_bms_power_offB\x0f\n\r_cfg_soc_caliB\x0f\n\r_cfg_bms_pushB\x12\n\x10_cfg_max_chg_socB\x12\n\x10_cfg_min_dsg_socB\x10\n\x0e_set_time_taskB\x14\n\x12_cfg_energy_backupB#\n!_cfg_plug_in_info_pv_l_dc_amp_maxB#\n!_cfg_plug_in_info_pv_h_dc_amp_maxB%\n#_cfg_plug_in_info_ac_in_chg_pow_maxB#\n!_cfg_plug_in_info_5p8_chg_pow_maxB\x19\n\x17_cfg_cms_oil_self_startB\x15\n\x13_cfg_cms_oil_on_socB\x16\n\x14_cfg_cms_oil_off_socB\x14\n\x12_cfg_llc_GFCI_flagB\x16\n\x14_cfg_ac_hv_always_onB\x16\n\x14_cfg_ac_lv_always_onB\x13\n\x11_cfg_tou_strategyB\x17\n\x15_cfg_ble_standby_timeB*\n(_cfg_display_property_full_upload_periodB1\n/_cfg_display_property_incremental_upload_periodB*\n(_cfg_runtime_property_full_upload_periodB1\n/_cfg_runtime_property_incremental_upload_periodB&\n$_active_display_property_full_uploadB&\n$_active_runtime_property_full_uploadB\x19\n\x17_cfg_RJ45_commc_serviceB\x12\n\x10_cfg_ac_out_openB\x1a\n\x18_cfg_generator_perf_modeB\x1c\n\x1a_cfg_generator_engine_openB\x1c\n\x1a_cfg_generator_out_pow_maxB\x1f\n\x1d_cfg_generator_ac_out_pow_maxB\x1f\n\x1d_cfg_generator_dc_out_pow_maxB\x18\n\x16_cfg_generator_self_onB"\n _reset_generator_maintence_stateB\x1f\n\x1d_cfg_fuels_liquefied_gas_typeB\x1f\n\x1d_cfg_fuels_liquefied_gas_uintB\x1e\n\x1c_cfg_fuels_liquefied_gas_valB!\n\x1f_cfg_plug_in_info_pv_dc_amp_maxB\x10\n\x0e_cfg_ups_alramB\x0f\n\r_cfg_led_modeB\x12\n\x10_cfg_pv_chg_typeB\x16\n\x14_cfg_low_power_alarmB\x14\n\x12_cfg_storm_patternB!\n\x1f_cfg_generator_mppt_hybrid_modeB\x1a\n\x18_cfg_generator_care_modeB\x1c\n\x1a_cfg_ac_energy_saving_openB\x1c\n\x1a_cfg_multi_bp_chg_dsg_modeB\x19\n\x17_cfg_backup_reverse_socB#\n!_cfg_energy_strategy_operate_modeB\x1a\n\x18_cfg_sp_charger_chg_modeB\'\n%_cfg_installment_payment_serve_enableB\'\n%_cfg_installment_payment_serve_beloneB \n\x1e_cfg_installment_payment_serveB\x1a\n\x18_cfg_sp_charger_chg_openB\x1f\n\x1d_cfg_sp_charger_chg_pow_limitB#\n!_reset_middlemen_delivery_settingB\x15\n\x13_cfg_ac_in_chg_modeB\x18\n\x16_cfg_pv_dc_chg_settingB\x18\n\x16_cfg_time_task_v2_itemB\x1f\n\x1d_active_selected_time_task_v2B\x1d\n\x1b_cfg_generator_low_power_enB$\n"_cfg_generator_low_power_thresholdB\x1f\n\x1d_cfg_generator_lpg_monitor_enB#\n!_cfg_fuels_liquefied_gas_lpg_uintB#\n!_cfg_fuels_liquefied_gas_lng_uintB\x16\n\x14_cfg_utc_timezone_idB\x13\n\x11_cfg_utc_set_modeB&\n$_cfg_sp_charger_car_batt_vol_settingB\x1e\n\x1c_cfg_wireless_oil_self_startB\x1a\n\x18_cfg_wireless_oil_on_socB\x1b\n\x19_cfg_wireless_oil_off_socB\x1e\n\x1c_cfg_output_power_off_memory"\xa5\x34\n\x0e\x43onfigWriteAck\x12\x16\n\taction_id\x18\x01 \x01(\rH\x00\x88\x01\x01\x12\x16\n\tconfig_ok\x18\x02 \x01(\x08H\x01\x88\x01\x01\x12\x1a\n\rcfg_power_off\x18\x03 \x01(\x08H\x02\x88\x01\x01\x12\x19\n\x0c\x63\x66g_power_on\x18\x04 \x01(\x08H\x03\x88\x01\x01\x12"\n\x15reset_factory_setting\x18\x05 \x01(\rH\x04\x88\x01\x01\x12\x19\n\x0c\x63\x66g_utc_time\x18\x06 \x01(\rH\x05\x88\x01\x01\x12\x1d\n\x10\x63\x66g_utc_timezone\x18\x07 \x01(\x05H\x06\x88\x01\x01\x12\x1f\n\x08\x63\x66g_beep\x18\x08 \x01(\x0b\x32\x08.CfgBeepH\x07\x88\x01\x01\x12\x18\n\x0b\x63\x66g_beep_en\x18\t \x01(\x08H\x08\x88\x01\x01\x12 \n\x13\x63\x66g_ac_standby_time\x18\n \x01(\rH\t\x88\x01\x01\x12 \n\x13\x63\x66g_dc_standby_time\x18\x0b \x01(\rH\n\x88\x01\x01\x12 \n\x13\x63\x66g_screen_off_time\x18\x0c \x01(\rH\x0b\x88\x01\x01\x12!\n\x14\x63\x66g_dev_standby_time\x18\r \x01(\rH\x0c\x88\x01\x01\x12\x1a\n\rcfg_lcd_light\x18\x0e \x01(\rH\r\x88\x01\x01\x12\x1f\n\x12\x63\x66g_hv_ac_out_open\x18\x0f \x01(\x08H\x0e\x88\x01\x01\x12\x1f\n\x12\x63\x66g_lv_ac_out_open\x18\x10 \x01(\x08H\x0f\x88\x01\x01\x12\x1c\n\x0f\x63\x66g_ac_out_freq\x18\x11 \x01(\rH\x10\x88\x01\x01\x12 \n\x13\x63\x66g_dc_12v_out_open\x18\x12 \x01(\x08H\x11\x88\x01\x01\x12\x19\n\x0c\x63\x66g_usb_open\x18\x13 \x01(\x08H\x12\x88\x01\x01\x12\x1c\n\x0f\x63\x66g_dc_out_open\x18\x14 \x01(\x08H\x13\x88\x01\x01\x12\x34\n\x14\x63\x66g_ac_out_always_on\x18\x17 \x01(\x0b\x32\x11.CfgAcOutAlwaysOnH\x14\x88\x01\x01\x12\x1a\n\rcfg_xboost_en\x18\x19 \x01(\x08H\x15\x88\x01\x01\x12#\n\x16\x63\x66g_bypass_out_disable\x18\x1a \x01(\x08H\x16\x88\x01\x01\x12\x37\n\x11\x63\x66g_bms_power_off\x18\x1e \x01(\x0b\x32\x17.CfgBmsPowerOffWriteAckH\x17\x88\x01\x01\x12\x19\n\x0c\x63\x66g_soc_cali\x18\x1f \x01(\rH\x18\x88\x01\x01\x12.\n\x0c\x63\x66g_bms_push\x18  \x01(\x0b\x32\x13.CfgBmsPushWriteAckH\x19\x88\x01\x01\x12\x1c\n\x0f\x63\x66g_max_chg_soc\x18! \x01(\rH\x1a\x88\x01\x01\x12\x1c\n\x0f\x63\x66g_min_dsg_soc\x18" \x01(\rH\x1b\x88\x01\x01\x12\x30\n\rset_time_task\x18\' \x01(\x0b\x32\x14.SetTimeTaskWriteAckH\x1c\x88\x01\x01\x12\x30\n\x11\x63\x66g_energy_backup\x18+ \x01(\x0b\x32\x10.CfgEnergyBackupH\x1d\x88\x01\x01\x12-\n cfg_plug_in_info_pv_l_dc_amp_max\x18\x34 \x01(\rH\x1e\x88\x01\x01\x12-\n cfg_plug_in_info_pv_h_dc_amp_max\x18\x35 \x01(\rH\x1f\x88\x01\x01\x12/\n"cfg_plug_in_info_ac_in_chg_pow_max\x18\x36 \x01(\rH \x88\x01\x01\x12-\n cfg_plug_in_info_5p8_chg_pow_max\x18\x38 \x01(\rH!\x88\x01\x01\x12#\n\x16\x63\x66g_cms_oil_self_start\x18: \x01(\x08H"\x88\x01\x01\x12\x1f\n\x12\x63\x66g_cms_oil_on_soc\x18; \x01(\rH#\x88\x01\x01\x12 \n\x13\x63\x66g_cms_oil_off_soc\x18< \x01(\rH$\x88\x01\x01\x12\x1e\n\x11\x63\x66g_llc_GFCI_flag\x18= \x01(\x08H%\x88\x01\x01\x12\x32\n\x13\x63\x66g_ac_hv_always_on\x18> \x01(\x0b\x32\x10.CfgAcHvAlwaysOnH&\x88\x01\x01\x12\x32\n\x13\x63\x66g_ac_lv_always_on\x18? \x01(\x0b\x32\x10.CfgAcLvAlwaysOnH\'\x88\x01\x01\x12.\n\x10\x63\x66g_tou_strategy\x18\x41 \x01(\x0b\x32\x0f.CfgTouStrategyH(\x88\x01\x01\x12!\n\x14\x63\x66g_ble_standby_time\x18\x42 \x01(\rH)\x88\x01\x01\x12\x34\n\'cfg_display_property_full_upload_period\x18\x43 \x01(\x05H*\x88\x01\x01\x12;\n.cfg_display_property_incremental_upload_period\x18\x44 \x01(\x05H+\x88\x01\x01\x12\x34\n\'cfg_runtime_property_full_upload_period\x18\x45 \x01(\x05H,\x88\x01\x01\x12;\n.cfg_runtime_property_incremental_upload_period\x18\x46 \x01(\x05H-\x88\x01\x01\x12\x30\n#active_display_property_full_upload\x18G \x01(\x08H.\x88\x01\x01\x12\x30\n#active_runtime_property_full_upload\x18H \x01(\x08H/\x88\x01\x01\x12\x39\n\x16\x63\x66g_RJ45_commc_service\x18I \x01(\x0b\x32\x14.CfgRj45CommcServiceH0\x88\x01\x01\x12\x1c\n\x0f\x63\x66g_ac_out_open\x18L \x01(\x08H1\x88\x01\x01\x12$\n\x17\x63\x66g_generator_perf_mode\x18M \x01(\rH2\x88\x01\x01\x12&\n\x19\x63\x66g_generator_engine_open\x18N \x01(\rH3\x88\x01\x01\x12&\n\x19\x63\x66g_generator_out_pow_max\x18O \x01(\rH4\x88\x01\x01\x12)\n\x1c\x63\x66g_generator_ac_out_pow_max\x18P \x01(\rH5\x88\x01\x01\x12)\n\x1c\x63\x66g_generator_dc_out_pow_max\x18Q \x01(\rH6\x88\x01\x01\x12"\n\x15\x63\x66g_generator_self_on\x18R \x01(\x08H7\x88\x01\x01\x12,\n\x1freset_generator_maintence_state\x18S \x01(\x08H8\x88\x01\x01\x12)\n\x1c\x63\x66g_fuels_liquefied_gas_type\x18T \x01(\rH9\x88\x01\x01\x12)\n\x1c\x63\x66g_fuels_liquefied_gas_uint\x18U \x01(\rH:\x88\x01\x01\x12(\n\x1b\x63\x66g_fuels_liquefied_gas_val\x18V \x01(\x02H;\x88\x01\x01\x12+\n\x1e\x63\x66g_plug_in_info_pv_dc_amp_max\x18W \x01(\rH<\x88\x01\x01\x12\x1a\n\rcfg_ups_alram\x18X \x01(\x08H=\x88\x01\x01\x12\x19\n\x0c\x63\x66g_led_mode\x18Y \x01(\rH>\x88\x01\x01\x12\x1c\n\x0f\x63\x66g_pv_chg_type\x18Z \x01(\rH?\x88\x01\x01\x12 \n\x13\x63\x66g_low_power_alarm\x18[ \x01(\rH@\x88\x01\x01\x12\x30\n\x11\x63\x66g_storm_pattern\x18] \x01(\x0b\x32\x10.CfgStormPatternHA\x88\x01\x01\x12H\n\x1e\x63\x66g_generator_mppt_hybrid_mode\x18_ \x01(\x0b\x32\x1b.CfgGeneratorMpptHybridModeHB\x88\x01\x01\x12;\n\x17\x63\x66g_generator_care_mode\x18\x61 \x01(\x0b\x32\x15.CfgGeneratorCareModeHC\x88\x01\x01\x12&\n\x19\x63\x66g_ac_energy_saving_open\x18\x63 \x01(\x08HD\x88\x01\x01\x12&\n\x19\x63\x66g_multi_bp_chg_dsg_mode\x18\x64 \x01(\rHE\x88\x01\x01\x12#\n\x16\x63\x66g_backup_reverse_soc\x18\x66 \x01(\rHF\x88\x01\x01\x12L\n cfg_energy_strategy_operate_mode\x18j \x01(\x0b\x32\x1d.CfgEnergyStrategyOperateModeHG\x88\x01\x01\x12:\n\x17\x63\x66g_sp_charger_chg_mode\x18t \x01(\x0e\x32\x14.SP_CHARGER_CHG_MODEHH\x88\x01\x01\x12\x31\n$cfg_installment_payment_serve_enable\x18w \x01(\x08HI\x88\x01\x01\x12Q\n$cfg_installment_payment_serve_belone\x18x \x01(\x0b\x32\x1e.InstallmentPaymentServeBeloneHJ\x88\x01\x01\x12\x44\n\x1d\x63\x66g_installment_payment_serve\x18y \x01(\x0b\x32\x18.InstallmentPaymentServeHK\x88\x01\x01\x12$\n\x17\x63\x66g_sp_charger_chg_open\x18z \x01(\x08HL\x88\x01\x01\x12)\n\x1c\x63\x66g_sp_charger_chg_pow_limit\x18{ \x01(\x02HM\x88\x01\x01\x12M\n reset_middlemen_delivery_setting\x18| \x01(\x0b\x32\x1e.ResetMiddlemenDeliverySettingHN\x88\x01\x01\x12\x30\n\x12\x63\x66g_ac_in_chg_mode\x18} \x01(\x0e\x32\x0f.AC_IN_CHG_MODEHO\x88\x01\x01\x12\x33\n\x15\x63\x66g_pv_dc_chg_setting\x18~ \x01(\x0b\x32\x0f.PvDcChgSettingHP\x88\x01\x01\x12\x33\n\x15\x63\x66g_time_task_v2_item\x18\x7f \x01(\x0b\x32\x0f.TimeTaskItemV2HQ\x88\x01\x01\x12*\n\x1c\x61\x63tive_selected_time_task_v2\x18\x80\x01 \x01(\rHR\x88\x01\x01\x12(\n\x1a\x63\x66g_generator_low_power_en\x18\x82\x01 \x01(\x08HS\x88\x01\x01\x12/\n!cfg_generator_low_power_threshold\x18\x83\x01 \x01(\rHT\x88\x01\x01\x12*\n\x1c\x63\x66g_generator_lpg_monitor_en\x18\x84\x01 \x01(\x08HU\x88\x01\x01\x12.\n cfg_fuels_liquefied_gas_lpg_uint\x18\x85\x01 \x01(\rHV\x88\x01\x01\x12.\n cfg_fuels_liquefied_gas_lng_uint\x18\x86\x01 \x01(\rHW\x88\x01\x01\x12!\n\x13\x63\x66g_utc_timezone_id\x18\x87\x01 \x01(\tHX\x88\x01\x01\x12\x1e\n\x10\x63\x66g_utc_set_mode\x18\x88\x01 \x01(\x08HY\x88\x01\x01\x12\x31\n#cfg_sp_charger_car_batt_vol_setting\x18\x89\x01 \x01(\rHZ\x88\x01\x01\x12)\n\x1b\x63\x66g_wireless_oil_self_start\x18\x8a\x01 \x01(\x08H[\x88\x01\x01\x12%\n\x17\x63\x66g_wireless_oil_on_soc\x18\x8b\x01 \x01(\rH\\\x88\x01\x01\x12&\n\x18\x63\x66g_wireless_oil_off_soc\x18\x8c\x01 \x01(\rH]\x88\x01\x01\x12)\n\x1b\x63\x66g_output_power_off_memory\x18\x8d\x01 \x01(\x08H^\x88\x01\x01\x42\x0c\n\n_action_idB\x0c\n\n_config_okB\x10\n\x0e_cfg_power_offB\x0f\n\r_cfg_power_onB\x18\n\x16_reset_factory_settingB\x0f\n\r_cfg_utc_timeB\x13\n\x11_cfg_utc_timezoneB\x0b\n\t_cfg_beepB\x0e\n\x0c_cfg_beep_enB\x16\n\x14_cfg_ac_standby_timeB\x16\n\x14_cfg_dc_standby_timeB\x16\n\x14_cfg_screen_off_timeB\x17\n\x15_cfg_dev_standby_timeB\x10\n\x0e_cfg_lcd_lightB\x15\n\x13_cfg_hv_ac_out_openB\x15\n\x13_cfg_lv_ac_out_openB\x12\n\x10_cfg_ac_out_freqB\x16\n\x14_cfg_dc_12v_out_openB\x0f\n\r_cfg_usb_openB\x12\n\x10_cfg_dc_out_openB\x17\n\x15_cfg_ac_out_always_onB\x10\n\x0e_cfg_xboost_enB\x19\n\x17_cfg_bypass_out_disableB\x14\n\x12_cfg_bms_power_offB\x0f\n\r_cfg_soc_caliB\x0f\n\r_cfg_bms_pushB\x12\n\x10_cfg_max_chg_socB\x12\n\x10_cfg_min_dsg_socB\x10\n\x0e_set_time_taskB\x14\n\x12_cfg_energy_backupB#\n!_cfg_plug_in_info_pv_l_dc_amp_maxB#\n!_cfg_plug_in_info_pv_h_dc_amp_maxB%\n#_cfg_plug_in_info_ac_in_chg_pow_maxB#\n!_cfg_plug_in_info_5p8_chg_pow_maxB\x19\n\x17_cfg_cms_oil_self_startB\x15\n\x13_cfg_cms_oil_on_socB\x16\n\x14_cfg_cms_oil_off_socB\x14\n\x12_cfg_llc_GFCI_flagB\x16\n\x14_cfg_ac_hv_always_onB\x16\n\x14_cfg_ac_lv_always_onB\x13\n\x11_cfg_tou_strategyB\x17\n\x15_cfg_ble_standby_timeB*\n(_cfg_display_property_full_upload_periodB1\n/_cfg_display_property_incremental_upload_periodB*\n(_cfg_runtime_property_full_upload_periodB1\n/_cfg_runtime_property_incremental_upload_periodB&\n$_active_display_property_full_uploadB&\n$_active_runtime_property_full_uploadB\x19\n\x17_cfg_RJ45_commc_serviceB\x12\n\x10_cfg_ac_out_openB\x1a\n\x18_cfg_generator_perf_modeB\x1c\n\x1a_cfg_generator_engine_openB\x1c\n\x1a_cfg_generator_out_pow_maxB\x1f\n\x1d_cfg_generator_ac_out_pow_maxB\x1f\n\x1d_cfg_generator_dc_out_pow_maxB\x18\n\x16_cfg_generator_self_onB"\n _reset_generator_maintence_stateB\x1f\n\x1d_cfg_fuels_liquefied_gas_typeB\x1f\n\x1d_cfg_fuels_liquefied_gas_uintB\x1e\n\x1c_cfg_fuels_liquefied_gas_valB!\n\x1f_cfg_plug_in_info_pv_dc_amp_maxB\x10\n\x0e_cfg_ups_alramB\x0f\n\r_cfg_led_modeB\x12\n\x10_cfg_pv_chg_typeB\x16\n\x14_cfg_low_power_alarmB\x14\n\x12_cfg_storm_patternB!\n\x1f_cfg_generator_mppt_hybrid_modeB\x1a\n\x18_cfg_generator_care_modeB\x1c\n\x1a_cfg_ac_energy_saving_openB\x1c\n\x1a_cfg_multi_bp_chg_dsg_modeB\x19\n\x17_cfg_backup_reverse_socB#\n!_cfg_energy_strategy_operate_modeB\x1a\n\x18_cfg_sp_charger_chg_modeB\'\n%_cfg_installment_payment_serve_enableB\'\n%_cfg_installment_payment_serve_beloneB \n\x1e_cfg_installment_payment_serveB\x1a\n\x18_cfg_sp_charger_chg_openB\x1f\n\x1d_cfg_sp_charger_chg_pow_limitB#\n!_reset_middlemen_delivery_settingB\x15\n\x13_cfg_ac_in_chg_modeB\x18\n\x16_cfg_pv_dc_chg_settingB\x18\n\x16_cfg_time_task_v2_itemB\x1f\n\x1d_active_selected_time_task_v2B\x1d\n\x1b_cfg_generator_low_power_enB$\n"_cfg_generator_low_power_thresholdB\x1f\n\x1d_cfg_generator_lpg_monitor_enB#\n!_cfg_fuels_liquefied_gas_lpg_uintB#\n!_cfg_fuels_liquefied_gas_lng_uintB\x16\n\x14_cfg_utc_timezone_idB\x13\n\x11_cfg_utc_set_modeB&\n$_cfg_sp_charger_car_batt_vol_settingB\x1e\n\x1c_cfg_wireless_oil_self_startB\x1a\n\x18_cfg_wireless_oil_on_socB\x1b\n\x19_cfg_wireless_oil_off_socB\x1e\n\x1c_cfg_output_power_off_memory"\x1f\n\nConfigRead\x12\x11\n\taction_id\x18\x01 \x03(\r"\x94\x02\n\rConfigReadAck\x12\x19\n\x0c\x63\x66g_utc_time\x18\x06 \x01(\rH\x00\x88\x01\x01\x12\x1d\n\x10\x63\x66g_utc_timezone\x18\x07 \x01(\x05H\x01\x88\x01\x01\x12\x36\n\x12get_time_task_list\x18) \x01(\x0b\x32\x15.GetAllTimeTaskReadckH\x02\x88\x01\x01\x12\x39\n\x16read_time_task_v2_list\x18\x81\x01 \x01(\x0b\x32\x13.TimeTaskItemV2ListH\x03\x88\x01\x01\x42\x0f\n\r_cfg_utc_timeB\x13\n\x11_cfg_utc_timezoneB\x15\n\x13_get_time_task_listB\x19\n\x17_read_time_task_v2_list"\xa9\x92\x01\n\x15\x44isplayPropertyUpload\x12\x14\n\x07\x65rrcode\x18\x01 \x01(\rH\x00\x88\x01\x01\x12\x17\n\nsys_status\x18\x02 \x01(\rH\x01\x88\x01\x01\x12\x1d\n\x0f\x64\x65v_online_flag\x18\x82\x01 \x01(\x08H\x02\x88\x01\x01\x12\x1a\n\x0cutc_timezone\x18\x85\x01 \x01(\x05H\x03\x88\x01\x01\x12\x1d\n\x0futc_timezone_id\x18\x86\x01 \x01(\tH\x04\x88\x01\x01\x12\x1a\n\x0cutc_set_mode\x18\x87\x01 \x01(\x08H\x05\x88\x01\x01\x12\x1f\n\x11\x63ms_bms_run_state\x18\x93\x02 \x01(\rH\x06\x88\x01\x01\x12\x1a\n\x0c\x63ms_batt_soc\x18\x86\x02 \x01(\x02H\x07\x88\x01\x01\x12\x1a\n\x0c\x63ms_batt_soh\x18\x87\x02 \x01(\x02H\x08\x88\x01\x01\x12\x1f\n\x11\x63ms_chg_dsg_state\x18\x9a\x02 \x01(\rH\t\x88\x01\x01\x12\x1f\n\x11\x63ms_batt_full_cap\x18\x9f\x02 \x01(\rH\n\x88\x01\x01\x12!\n\x13\x63ms_batt_design_cap\x18\xa0\x02 \x01(\rH\x0b\x88\x01\x01\x12!\n\x13\x63ms_batt_remain_cap\x18\xa1\x02 \x01(\rH\x0c\x88\x01\x01\x12"\n\x14\x63ms_batt_full_energy\x18\xce\x03 \x01(\rH\r\x88\x01\x01\x12\x1e\n\x10\x63ms_dsg_rem_time\x18\x8c\x02 \x01(\rH\x0e\x88\x01\x01\x12\x1e\n\x10\x63ms_chg_rem_time\x18\x8d\x02 \x01(\rH\x0f\x88\x01\x01\x12"\n\x14\x63ms_batt_pow_out_max\x18\xcb\x03 \x01(\rH\x10\x88\x01\x01\x12!\n\x13\x63ms_batt_pow_in_max\x18\xcc\x03 \x01(\rH\x11\x88\x01\x01\x12\x1a\n\rcms_batt_temp\x18\x66 \x01(\x05H\x12\x88\x01\x01\x12\x1d\n\x0f\x63ms_max_chg_soc\x18\x8e\x02 \x01(\rH\x13\x88\x01\x01\x12\x1d\n\x0f\x63ms_min_dsg_soc\x18\x8f\x02 \x01(\rH\x14\x88\x01\x01\x12\x1a\n\x0c\x62ms_batt_soc\x18\xf2\x01 \x01(\x02H\x15\x88\x01\x01\x12\x1a\n\x0c\x62ms_batt_soh\x18\xf3\x01 \x01(\x02H\x16\x88\x01\x01\x12\x1f\n\x11\x62ms_chg_dsg_state\x18\x99\x02 \x01(\rH\x17\x88\x01\x01\x12\x1c\n\x0e\x62ms_design_cap\x18\xf8\x01 \x01(\rH\x18\x88\x01\x01\x12\x1e\n\x10\x62ms_dsg_rem_time\x18\xfe\x01 \x01(\rH\x19\x88\x01\x01\x12\x1e\n\x10\x62ms_chg_rem_time\x18\xff\x01 \x01(\rH\x1a\x88\x01\x01\x12\x1f\n\x11\x62ms_min_cell_temp\x18\x82\x02 \x01(\x05H\x1b\x88\x01\x01\x12\x1f\n\x11\x62ms_max_cell_temp\x18\x83\x02 \x01(\x05H\x1c\x88\x01\x01\x12\x1e\n\x10\x62ms_min_mos_temp\x18\x84\x02 \x01(\x05H\x1d\x88\x01\x01\x12\x1e\n\x10\x62ms_max_mos_temp\x18\x85\x02 \x01(\x05H\x1e\x88\x01\x01\x12\x1d\n\x0f\x64\x65v_sleep_state\x18\xd4\x01 \x01(\rH\x1f\x88\x01\x01\x12\x15\n\x07\x65n_beep\x18\xc3\x01 \x01(\x08H \x88\x01\x01\x12\x16\n\tlcd_light\x18\x05 \x01(\rH!\x88\x01\x01\x12\x19\n\x0b\x61\x63_out_open\x18\xaa\x02 \x01(\x08H"\x88\x01\x01\x12!\n\x14\x62tn_ac_out_lv_switch\x18H \x01(\x08H#\x88\x01\x01\x12!\n\x14\x62tn_ac_out_hv_switch\x18I \x01(\x08H$\x88\x01\x01\x12\x18\n\x0b\x64\x63_out_open\x18J \x01(\x08H%\x88\x01\x01\x12"\n\x15\x62tn_dc_12v_out_switch\x18K \x01(\x08H&\x88\x01\x01\x12\x1b\n\x0e\x62tn_usb_switch\x18L \x01(\x08H\'\x88\x01\x01\x12\x1d\n\x10\x64\x65v_standby_time\x18\x11 \x01(\rH(\x88\x01\x01\x12\x1c\n\x0fscreen_off_time\x18\x12 \x01(\rH)\x88\x01\x01\x12\x1c\n\x0f\x61\x63_standby_time\x18\x13 \x01(\rH*\x88\x01\x01\x12\x1c\n\x0f\x64\x63_standby_time\x18\x14 \x01(\rH+\x88\x01\x01\x12\x1e\n\x10\x62le_standby_time\x18\xa2\x02 \x01(\rH,\x88\x01\x01\x12\x17\n\tups_alram\x18\xe3\x02 \x01(\x08H-\x88\x01\x01\x12\x16\n\x08led_mode\x18\xe5\x02 \x01(\rH.\x88\x01\x01\x12\x1d\n\x0flow_power_alarm\x18\xe6\x02 \x01(\rH/\x88\x01\x01\x12\x1e\n\x10silence_chg_watt\x18\xe7\x02 \x01(\rH0\x88\x01\x01\x12\x19\n\x0b\x61\x63_out_freq\x18\xd3\x01 \x01(\rH1\x88\x01\x01\x12\x1c\n\x0ellc_hv_lv_flag\x18\xe3\x01 \x01(\rH2\x88\x01\x01\x12\x1e\n\x11\x61\x63_always_on_flag\x18\x16 \x01(\x08H3\x88\x01\x01\x12\x1d\n\x0f\x61\x63_hv_always_on\x18\x9b\x02 \x01(\x08H4\x88\x01\x01\x12\x1d\n\x0f\x61\x63_lv_always_on\x18\x9c\x02 \x01(\x08H5\x88\x01\x01\x12"\n\x15\x61\x63_always_on_mini_soc\x18\x17 \x01(\rH6\x88\x01\x01\x12\x16\n\txboost_en\x18\x19 \x01(\x08H7\x88\x01\x01\x12%\n\x17output_power_off_memory\x18\x93\x01 \x01(\x08H8\x88\x01\x01\x12 \n\x12\x66\x61st_charge_switch\x18\xb6\x01 \x01(\rH9\x88\x01\x01\x12\x1b\n\rllc_GFCI_flag\x18\xc8\x01 \x01(\x08H:\x88\x01\x01\x12#\n\x15\x61\x63_energy_saving_open\x18\xc7\x03 \x01(\x08H;\x88\x01\x01\x12 \n\x12\x62ypass_out_disable\x18\x92\x01 \x01(\x08H<\x88\x01\x01\x12\x38\n\x16pv_dc_chg_setting_list\x18} \x01(\x0b\x32\x13.PvDcChgSettingListH=\x88\x01\x01\x12\x19\n\x0bpv_chg_type\x18\x94\x01 \x01(\rH>\x88\x01\x01\x12 \n\x13\x65nergy_backup_state\x18\x06 \x01(\rH?\x88\x01\x01\x12$\n\x17\x65nergy_backup_start_soc\x18\x08 \x01(\rH@\x88\x01\x01\x12\x1d\n\x10\x65nergy_backup_en\x18\x07 \x01(\x08HA\x88\x01\x01\x12"\n\x14storm_pattern_enable\x18\xd3\x03 \x01(\x08HB\x88\x01\x01\x12%\n\x17storm_pattern_open_flag\x18\xd4\x03 \x01(\x08HC\x88\x01\x01\x12$\n\x16storm_pattern_end_time\x18\xd5\x03 \x01(\rHD\x88\x01\x01\x12\x32\n\x11time_task_current\x18\xdb\x01 \x01(\x0b\x32\x11.SetTimeTaskWriteHE\x88\x01\x01\x12\x37\n\x19\x63urrent_time_task_v2_item\x18~ \x01(\x0b\x32\x0f.TimeTaskItemV2HF\x88\x01\x01\x12%\n\x17time_task_conflict_flag\x18\x9d\x02 \x01(\rHG\x88\x01\x01\x12"\n\x14time_task_change_cnt\x18\x9e\x02 \x01(\rHH\x88\x01\x01\x12 \n\x12\x63ms_oil_self_start\x18\x92\x02 \x01(\x08HI\x88\x01\x01\x12\x1c\n\x0e\x63ms_oil_on_soc\x18\x90\x02 \x01(\rHJ\x88\x01\x01\x12\x1d\n\x0f\x63ms_oil_off_soc\x18\x91\x02 \x01(\rHK\x88\x01\x01\x12%\n\x17wireless_oil_self_start\x18\x8f\x01 \x01(\x08HL\x88\x01\x01\x12!\n\x13wireless_oil_on_soc\x18\x90\x01 \x01(\rHM\x88\x01\x01\x12"\n\x14wireless_oil_off_soc\x18\x91\x01 \x01(\rHN\x88\x01\x01\x12+\n\x1dgenerator_pv_hybrid_mode_open\x18\xc3\x03 \x01(\x08HO\x88\x01\x01\x12.\n generator_pv_hybrid_mode_soc_max\x18\xc4\x03 \x01(\rHP\x88\x01\x01\x12&\n\x18generator_care_mode_open\x18\xc5\x03 \x01(\x08HQ\x88\x01\x01\x12,\n\x1egenerator_care_mode_start_time\x18\xc6\x03 \x01(\rHR\x88\x01\x01\x12#\n\x15multi_bp_chg_dsg_mode\x18\xc8\x03 \x01(\rHS\x88\x01\x01\x12\x19\n\x0cpow_in_sum_w\x18\x03 \x01(\x02HT\x88\x01\x01\x12\x1a\n\rpow_out_sum_w\x18\x04 \x01(\x02HU\x88\x01\x01\x12\x1b\n\x0epow_get_qcusb1\x18\t \x01(\x02HV\x88\x01\x01\x12\x1b\n\x0epow_get_qcusb2\x18\n \x01(\x02HW\x88\x01\x01\x12\x1b\n\x0epow_get_typec1\x18\x0b \x01(\x02HX\x88\x01\x01\x12\x1b\n\x0epow_get_typec2\x18\x0c \x01(\x02HY\x88\x01\x01\x12\x19\n\x0cpow_get_pv_h\x18# \x01(\x02HZ\x88\x01\x01\x12\x19\n\x0cpow_get_pv_l\x18$ \x01(\x02H[\x88\x01\x01\x12\x18\n\npow_get_pv\x18\xe9\x02 \x01(\x02H\\\x88\x01\x01\x12\x18\n\x0bpow_get_pv2\x18\x46 \x01(\x02H]\x88\x01\x01\x12\x18\n\x0bpow_get_12v\x18% \x01(\x02H^\x88\x01\x01\x12\x18\n\x0bpow_get_24v\x18& \x01(\x02H_\x88\x01\x01\x12\x18\n\x0bpow_get_llc\x18\x34 \x01(\x02H`\x88\x01\x01\x12\x17\n\npow_get_ac\x18\x35 \x01(\x02Ha\x88\x01\x01\x12\x1a\n\rpow_get_ac_in\x18\x36 \x01(\x02Hb\x88\x01\x01\x12\x1c\n\x0epow_get_ac_out\x18\xf0\x02 \x01(\x02Hc\x88\x01\x01\x12\x1e\n\x11pow_get_ac_hv_out\x18\x37 \x01(\x02Hd\x88\x01\x01\x12\x1e\n\x11pow_get_ac_lv_out\x18\x38 \x01(\x02He\x88\x01\x01\x12#\n\x16pow_get_ac_lv_tt30_out\x18\x39 \x01(\x02Hf\x88\x01\x01\x12\x18\n\x0bpow_get_5p8\x18: \x01(\x02Hg\x88\x01\x01\x12\x18\n\npow_get_dc\x18\xa9\x02 \x01(\x02Hh\x88\x01\x01\x12\x19\n\x0bpow_get_bms\x18\x9e\x01 \x01(\x02Hi\x88\x01\x01\x12\x1b\n\rpow_get_4p8_1\x18\x9f\x01 \x01(\x02Hj\x88\x01\x01\x12\x1b\n\rpow_get_4p8_2\x18\xa0\x01 \x01(\x02Hk\x88\x01\x01\x12\x19\n\x0bpow_get_dcp\x18\xa9\x03 \x01(\x02Hl\x88\x01\x01\x12\x19\n\x0cpow_get_dcp2\x18M \x01(\x02Hm\x88\x01\x01\x12\x1c\n\x0fpow_get_dc_bidi\x18i \x01(\x02Hn\x88\x01\x01\x12\x42\n\x16\x64isplay_statistics_sum\x18\xcf\x03 \x01(\x0b\x32\x1c.DisplayStatisticsRecordListHo\x88\x01\x01\x12\x1d\n\x10\x66low_info_qcusb1\x18\r \x01(\rHp\x88\x01\x01\x12\x1d\n\x10\x66low_info_qcusb2\x18\x0e \x01(\rHq\x88\x01\x01\x12\x1d\n\x10\x66low_info_typec1\x18\x0f \x01(\rHr\x88\x01\x01\x12\x1d\n\x10\x66low_info_typec2\x18\x10 \x01(\rHs\x88\x01\x01\x12\x1b\n\x0e\x66low_info_pv_h\x18\x1f \x01(\rHt\x88\x01\x01\x12\x1b\n\x0e\x66low_info_pv_l\x18  \x01(\rHu\x88\x01\x01\x12\x1a\n\x0c\x66low_info_pv\x18\xe8\x02 \x01(\rHv\x88\x01\x01\x12\x1b\n\rflow_info_pv2\x18\x9e\x03 \x01(\rHw\x88\x01\x01\x12\x1a\n\rflow_info_12v\x18! \x01(\rHx\x88\x01\x01\x12\x1a\n\rflow_info_24v\x18" \x01(\rHy\x88\x01\x01\x12\x1c\n\x0f\x66low_info_ac2dc\x18- \x01(\rHz\x88\x01\x01\x12\x1c\n\x0f\x66low_info_dc2ac\x18. \x01(\rH{\x88\x01\x01\x12\x1c\n\x0f\x66low_info_ac_in\x18/ \x01(\rH|\x88\x01\x01\x12 \n\x13\x66low_info_ac_hv_out\x18\x30 \x01(\rH}\x88\x01\x01\x12 \n\x13\x66low_info_ac_lv_out\x18\x31 \x01(\rH~\x88\x01\x01\x12\x1d\n\x10\x66low_info_5p8_in\x18\x32 \x01(\rH\x7f\x88\x01\x01\x12\x1f\n\x11\x66low_info_5p8_out\x18\x33 \x01(\rH\x80\x01\x88\x01\x01\x12\x1f\n\x10\x66low_info_ac_out\x18\xef\x02 \x01(\rH\x81\x01\x88\x01\x01\x12 \n\x11\x66low_info_bms_dsg\x18\x98\x01 \x01(\rH\x82\x01\x88\x01\x01\x12 \n\x11\x66low_info_bms_chg\x18\x99\x01 \x01(\rH\x83\x01\x88\x01\x01\x12!\n\x12\x66low_info_4p8_1_in\x18\x9a\x01 \x01(\rH\x84\x01\x88\x01\x01\x12"\n\x13\x66low_info_4p8_1_out\x18\x9b\x01 \x01(\rH\x85\x01\x88\x01\x01\x12!\n\x12\x66low_info_4p8_2_in\x18\x9c\x01 \x01(\rH\x86\x01\x88\x01\x01\x12"\n\x13\x66low_info_4p8_2_out\x18\x9d\x01 \x01(\rH\x87\x01\x88\x01\x01\x12\x1f\n\x10\x66low_info_dcp_in\x18\xa7\x03 \x01(\rH\x88\x01\x88\x01\x01\x12 \n\x11\x66low_info_dcp_out\x18\xa8\x03 \x01(\rH\x89\x01\x88\x01\x01\x12\x1f\n\x11\x66low_info_dcp2_in\x18N \x01(\rH\x8a\x01\x88\x01\x01\x12 \n\x12\x66low_info_dcp2_out\x18O \x01(\rH\x8b\x01\x88\x01\x01\x12$\n\x16plug_in_info_pv_h_flag\x18\' \x01(\rH\x8c\x01\x88\x01\x01\x12$\n\x16plug_in_info_pv_h_type\x18( \x01(\rH\x8d\x01\x88\x01\x01\x12-\n\x1eplug_in_info_pv_h_charger_flag\x18\xab\x01 \x01(\x08H\x8e\x01\x88\x01\x01\x12+\n\x1cplug_in_info_pv_h_dc_amp_max\x18\xb5\x01 \x01(\rH\x8f\x01\x88\x01\x01\x12,\n\x1dplug_in_info_pv_h_chg_amp_max\x18\xec\x01 \x01(\rH\x90\x01\x88\x01\x01\x12,\n\x1dplug_in_info_pv_h_chg_vol_max\x18\xe9\x01 \x01(\rH\x91\x01\x88\x01\x01\x12$\n\x16plug_in_info_pv_l_flag\x18* \x01(\rH\x92\x01\x88\x01\x01\x12$\n\x16plug_in_info_pv_l_type\x18+ \x01(\rH\x93\x01\x88\x01\x01\x12-\n\x1eplug_in_info_pv_l_charger_flag\x18\xaa\x01 \x01(\x08H\x94\x01\x88\x01\x01\x12+\n\x1cplug_in_info_pv_l_dc_amp_max\x18\xb4\x01 \x01(\rH\x95\x01\x88\x01\x01\x12,\n\x1dplug_in_info_pv_l_chg_amp_max\x18\xeb\x01 \x01(\rH\x96\x01\x88\x01\x01\x12,\n\x1dplug_in_info_pv_l_chg_vol_max\x18\xea\x01 \x01(\rH\x97\x01\x88\x01\x01\x12#\n\x14plug_in_info_pv_flag\x18\xea\x02 \x01(\x08H\x98\x01\x88\x01\x01\x12#\n\x14plug_in_info_pv_type\x18\xeb\x02 \x01(\rH\x99\x01\x88\x01\x01\x12+\n\x1cplug_in_info_pv_charger_flag\x18\xec\x02 \x01(\x08H\x9a\x01\x88\x01\x01\x12)\n\x1aplug_in_info_pv_dc_amp_max\x18\xe4\x02 \x01(\rH\x9b\x01\x88\x01\x01\x12*\n\x1bplug_in_info_pv_chg_amp_max\x18\xed\x02 \x01(\rH\x9c\x01\x88\x01\x01\x12*\n\x1bplug_in_info_pv_chg_vol_max\x18\xee\x02 \x01(\rH\x9d\x01\x88\x01\x01\x12:\n\x1cplug_in_info_pv_chg_max_list\x18\x88\x01 \x01(\x0b\x32\r.PvChgMaxListH\x9e\x01\x88\x01\x01\x12$\n\x15plug_in_info_pv2_flag\x18\xa5\x03 \x01(\x08H\x9f\x01\x88\x01\x01\x12$\n\x15plug_in_info_pv2_type\x18\xa6\x03 \x01(\rH\xa0\x01\x88\x01\x01\x12,\n\x1dplug_in_info_pv2_charger_flag\x18\xae\x03 \x01(\x08H\xa1\x01\x88\x01\x01\x12)\n\x1bplug_in_info_pv2_dc_amp_max\x18P \x01(\rH\xa2\x01\x88\x01\x01\x12*\n\x1cplug_in_info_pv2_chg_amp_max\x18Q \x01(\rH\xa3\x01\x88\x01\x01\x12*\n\x1cplug_in_info_pv2_chg_vol_max\x18R \x01(\rH\xa4\x01\x88\x01\x01\x12;\n\x1dplug_in_info_pv2_chg_max_list\x18\x89\x01 \x01(\x0b\x32\r.PvChgMaxListH\xa5\x01\x88\x01\x01\x12%\n\x17plug_in_info_ac_in_flag\x18= \x01(\rH\xa6\x01\x88\x01\x01\x12+\n\x1cplug_in_info_ac_charger_flag\x18\xca\x01 \x01(\x08H\xa7\x01\x88\x01\x01\x12$\n\x16plug_in_info_ac_in_feq\x18> \x01(\rH\xa8\x01\x88\x01\x01\x12-\n\x1eplug_in_info_ac_in_chg_pow_max\x18\xd1\x01 \x01(\rH\xa9\x01\x88\x01\x01\x12\x31\n"plug_in_info_ac_in_chg_hal_pow_max\x18\xca\x03 \x01(\rH\xaa\x01\x88\x01\x01\x12:\n\x1bplug_in_info_ac_in_chg_mode\x18| \x01(\x0e\x32\x0f.AC_IN_CHG_MODEH\xab\x01\x88\x01\x01\x12.\n\x1fplug_in_info_ac_out_dsg_pow_max\x18\xee\x01 \x01(\rH\xac\x01\x88\x01\x01\x12+\n\x1cplug_in_info_5p8_chg_pow_max\x18\xd2\x01 \x01(\rH\xad\x01\x88\x01\x01\x12/\n plug_in_info_5p8_chg_hal_pow_max\x18\xc9\x03 \x01(\rH\xae\x01\x88\x01\x01\x12+\n\x1cplug_in_info_5p8_dsg_pow_max\x18\xed\x01 \x01(\rH\xaf\x01\x88\x01\x01\x12#\n\x15plug_in_info_5p8_flag\x18? \x01(\rH\xb0\x01\x88\x01\x01\x12\'\n\x18plug_in_info_5p8_dsg_chg\x18\xbf\x01 \x01(\rH\xb1\x01\x88\x01\x01\x12,\n\x1dplug_in_info_5p8_charger_flag\x18\xcb\x01 \x01(\x08H\xb2\x01\x88\x01\x01\x12#\n\x15plug_in_info_5p8_type\x18@ \x01(\rH\xb3\x01\x88\x01\x01\x12%\n\x17plug_in_info_5p8_detail\x18\x41 \x01(\rH\xb4\x01\x88\x01\x01\x12"\n\x13plug_in_info_5p8_sn\x18\xc1\x01 \x01(\tH\xb5\x01\x88\x01\x01\x12)\n\x1aplug_in_info_5p8_run_state\x18\xcc\x01 \x01(\rH\xb6\x01\x88\x01\x01\x12(\n\x19plug_in_info_5p8_err_code\x18\xd8\x01 \x01(\rH\xb7\x01\x88\x01\x01\x12(\n\x19plug_in_info_5p8_firm_ver\x18\xc2\x01 \x01(\rH\xb8\x01\x88\x01\x01\x12/\n\x15plug_in_info_5p8_resv\x18\xc0\x01 \x01(\x0b\x32\t.ResvInfoH\xb9\x01\x88\x01\x01\x12*\n\x1cplug_in_info_acp_chg_pow_max\x18k \x01(\rH\xba\x01\x88\x01\x01\x12.\n plug_in_info_acp_chg_hal_pow_max\x18l \x01(\rH\xbb\x01\x88\x01\x01\x12*\n\x1cplug_in_info_acp_dsg_pow_max\x18m \x01(\rH\xbc\x01\x88\x01\x01\x12#\n\x15plug_in_info_acp_flag\x18n \x01(\rH\xbd\x01\x88\x01\x01\x12&\n\x18plug_in_info_acp_dsg_chg\x18o \x01(\rH\xbe\x01\x88\x01\x01\x12+\n\x1dplug_in_info_acp_charger_flag\x18p \x01(\x08H\xbf\x01\x88\x01\x01\x12#\n\x15plug_in_info_acp_type\x18q \x01(\rH\xc0\x01\x88\x01\x01\x12%\n\x17plug_in_info_acp_detail\x18r \x01(\rH\xc1\x01\x88\x01\x01\x12!\n\x13plug_in_info_acp_sn\x18s \x01(\tH\xc2\x01\x88\x01\x01\x12(\n\x1aplug_in_info_acp_run_state\x18t \x01(\rH\xc3\x01\x88\x01\x01\x12\'\n\x19plug_in_info_acp_err_code\x18u \x01(\rH\xc4\x01\x88\x01\x01\x12\'\n\x19plug_in_info_acp_firm_ver\x18v \x01(\rH\xc5\x01\x88\x01\x01\x12.\n\x15plug_in_info_acp_resv\x18w \x01(\x0b\x32\t.ResvInfoH\xc6\x01\x88\x01\x01\x12\'\n\x19plug_in_info_dc_bidi_flag\x18j \x01(\x08H\xc7\x01\x88\x01\x01\x12\'\n\x18plug_in_info_dcp_in_flag\x18\xaa\x03 \x01(\x08H\xc8\x01\x88\x01\x01\x12,\n\x1dplug_in_info_dcp_dsg_chg_type\x18\xaf\x03 \x01(\rH\xc9\x01\x88\x01\x01\x12,\n\x1dplug_in_info_dcp_charger_flag\x18\xb3\x03 \x01(\x08H\xca\x01\x88\x01\x01\x12$\n\x15plug_in_info_dcp_type\x18\xab\x03 \x01(\rH\xcb\x01\x88\x01\x01\x12&\n\x17plug_in_info_dcp_detail\x18\xac\x03 \x01(\rH\xcc\x01\x88\x01\x01\x12"\n\x13plug_in_info_dcp_sn\x18\xb1\x03 \x01(\tH\xcd\x01\x88\x01\x01\x12)\n\x1aplug_in_info_dcp_run_state\x18\xb4\x03 \x01(\rH\xce\x01\x88\x01\x01\x12(\n\x19plug_in_info_dcp_firm_ver\x18\xb2\x03 \x01(\rH\xcf\x01\x88\x01\x01\x12/\n\x15plug_in_info_dcp_resv\x18\xb0\x03 \x01(\x0b\x32\t.ResvInfoH\xd0\x01\x88\x01\x01\x12\'\n\x19plug_in_info_dcp2_in_flag\x18S \x01(\x08H\xd1\x01\x88\x01\x01\x12,\n\x1eplug_in_info_dcp2_dsg_chg_type\x18T \x01(\rH\xd2\x01\x88\x01\x01\x12,\n\x1eplug_in_info_dcp2_charger_flag\x18U \x01(\x08H\xd3\x01\x88\x01\x01\x12$\n\x16plug_in_info_dcp2_type\x18V \x01(\rH\xd4\x01\x88\x01\x01\x12&\n\x18plug_in_info_dcp2_detail\x18W \x01(\rH\xd5\x01\x88\x01\x01\x12"\n\x14plug_in_info_dcp2_sn\x18X \x01(\tH\xd6\x01\x88\x01\x01\x12)\n\x1bplug_in_info_dcp2_run_state\x18Y \x01(\rH\xd7\x01\x88\x01\x01\x12(\n\x1aplug_in_info_dcp2_firm_ver\x18Z \x01(\rH\xd8\x01\x88\x01\x01\x12/\n\x16plug_in_info_dcp2_resv\x18[ \x01(\x0b\x32\t.ResvInfoH\xd9\x01\x88\x01\x01\x12)\n\x1aplug_in_info_4p8_1_in_flag\x18\xa1\x01 \x01(\rH\xda\x01\x88\x01\x01\x12.\n\x1fplug_in_info_4p8_1_dsg_chg_type\x18\xb7\x01 \x01(\rH\xdb\x01\x88\x01\x01\x12.\n\x1fplug_in_info_4p8_1_charger_flag\x18\xcd\x01 \x01(\x08H\xdc\x01\x88\x01\x01\x12&\n\x17plug_in_info_4p8_1_type\x18\xa2\x01 \x01(\rH\xdd\x01\x88\x01\x01\x12(\n\x19plug_in_info_4p8_1_detail\x18\xa3\x01 \x01(\rH\xde\x01\x88\x01\x01\x12$\n\x15plug_in_info_4p8_1_sn\x18\xb9\x01 \x01(\tH\xdf\x01\x88\x01\x01\x12+\n\x1cplug_in_info_4p8_1_run_state\x18\xce\x01 \x01(\rH\xe0\x01\x88\x01\x01\x12*\n\x1bplug_in_info_4p8_1_err_code\x18\xd9\x01 \x01(\rH\xe1\x01\x88\x01\x01\x12*\n\x1bplug_in_info_4p8_1_firm_ver\x18\xba\x01 \x01(\rH\xe2\x01\x88\x01\x01\x12\x31\n\x17plug_in_info_4p8_1_resv\x18\xb8\x01 \x01(\x0b\x32\t.ResvInfoH\xe3\x01\x88\x01\x01\x12)\n\x1aplug_in_info_4p8_2_in_flag\x18\xa4\x01 \x01(\rH\xe4\x01\x88\x01\x01\x12.\n\x1fplug_in_info_4p8_2_dsg_chg_type\x18\xbb\x01 \x01(\rH\xe5\x01\x88\x01\x01\x12.\n\x1fplug_in_info_4p8_2_charger_flag\x18\xcf\x01 \x01(\x08H\xe6\x01\x88\x01\x01\x12&\n\x17plug_in_info_4p8_2_type\x18\xa5\x01 \x01(\rH\xe7\x01\x88\x01\x01\x12(\n\x19plug_in_info_4p8_2_detail\x18\xa6\x01 \x01(\rH\xe8\x01\x88\x01\x01\x12$\n\x15plug_in_info_4p8_2_sn\x18\xbd\x01 \x01(\tH\xe9\x01\x88\x01\x01\x12+\n\x1cplug_in_info_4p8_2_run_state\x18\xd0\x01 \x01(\rH\xea\x01\x88\x01\x01\x12*\n\x1bplug_in_info_4p8_2_err_code\x18\xda\x01 \x01(\rH\xeb\x01\x88\x01\x01\x12*\n\x1bplug_in_info_4p8_2_firm_ver\x18\xbe\x01 \x01(\rH\xec\x01\x88\x01\x01\x12\x31\n\x17plug_in_info_4p8_2_resv\x18\xbc\x01 \x01(\x0b\x32\t.ResvInfoH\xed\x01\x88\x01\x01\x12\x44\n\x1cwireless_coordinate_dev_list\x18\x8e\x01 \x01(\x0b\x32\x17.WirelessCoordinateListH\xee\x01\x88\x01\x01\x12\x1a\n\x0bpd_err_code\x18\xd5\x01 \x01(\rH\xef\x01\x88\x01\x01\x12\x1c\n\rmppt_err_code\x18\xd7\x01 \x01(\rH\xf0\x01\x88\x01\x01\x12\x1b\n\x0cllc_err_code\x18\xd6\x01 \x01(\rH\xf1\x01\x88\x01\x01\x12\x1f\n\x10llc_inv_err_code\x18\xe8\x01 \x01(\rH\xf2\x01\x88\x01\x01\x12\x1c\n\rdcdc_err_code\x18\xb5\x03 \x01(\rH\xf3\x01\x88\x01\x01\x12(\n\x19plug_in_info_dcp_err_code\x18\xb6\x03 \x01(\rH\xf4\x01\x88\x01\x01\x12)\n\x1aplug_in_info_dcp2_err_code\x18\xb7\x03 \x01(\rH\xf5\x01\x88\x01\x01\x12\x1b\n\x0c\x62ms_err_code\x18\x8c\x01 \x01(\rH\xf6\x01\x88\x01\x01\x12\x1b\n\x0cinv_err_code\x18\xc2\x03 \x01(\rH\xf7\x01\x88\x01\x01\x12\x37\n\x14\x65rr_code_record_list\x18\x8d\x01 \x01(\x0b\x32\x12.ErrcodeRecordListH\xf8\x01\x88\x01\x01\x12\x1b\n\rpcs_fan_level\x18\x1e \x01(\rH\xf9\x01\x88\x01\x01\x12\x1f\n\x10pcs_fan_err_flag\x18\xe2\x01 \x01(\rH\xfa\x01\x88\x01\x01\x12#\n\x14generator_fuels_type\x18\xab\x02 \x01(\rH\xfb\x01\x88\x01\x01\x12$\n\x15generator_remain_time\x18\xac\x02 \x01(\rH\xfc\x01\x88\x01\x01\x12!\n\x12generator_run_time\x18\xad\x02 \x01(\rH\xfd\x01\x88\x01\x01\x12%\n\x16generator_total_output\x18\xae\x02 \x01(\rH\xfe\x01\x88\x01\x01\x12\'\n\x18generator_abnormal_state\x18\xaf\x02 \x01(\rH\xff\x01\x88\x01\x01\x12\x1c\n\rfuels_oil_val\x18\xb0\x02 \x01(\rH\x80\x02\x88\x01\x01\x12\'\n\x18\x66uels_liquefied_gas_type\x18\xb1\x02 \x01(\rH\x81\x02\x88\x01\x01\x12\'\n\x18\x66uels_liquefied_gas_uint\x18\xb2\x02 \x01(\rH\x82\x02\x88\x01\x01\x12&\n\x17\x66uels_liquefied_gas_val\x18\xb3\x02 \x01(\x02H\x83\x02\x88\x01\x01\x12\x33\n$fuels_liquefied_gas_consume_per_hour\x18\xb4\x02 \x01(\x02H\x84\x02\x88\x01\x01\x12-\n\x1e\x66uels_liquefied_gas_remain_val\x18\xb5\x02 \x01(\rH\x85\x02\x88\x01\x01\x12+\n\x1c\x66uels_liquefied_gas_lpg_uint\x18\x83\x01 \x01(\rH\x86\x02\x88\x01\x01\x12+\n\x1c\x66uels_liquefied_gas_lng_uint\x18\x84\x01 \x01(\rH\x87\x02\x88\x01\x01\x12"\n\x13generator_perf_mode\x18\xb6\x02 \x01(\rH\x88\x02\x88\x01\x01\x12$\n\x15generator_engine_open\x18\xb7\x02 \x01(\rH\x89\x02\x88\x01\x01\x12$\n\x16generator_low_power_en\x18\x7f \x01(\x08H\x8a\x02\x88\x01\x01\x12,\n\x1dgenerator_low_power_threshold\x18\x80\x01 \x01(\rH\x8b\x02\x88\x01\x01\x12\'\n\x18generator_lpg_monitor_en\x18\x81\x01 \x01(\x08H\x8c\x02\x88\x01\x01\x12$\n\x15generator_out_pow_max\x18\xb8\x02 \x01(\rH\x8d\x02\x88\x01\x01\x12\'\n\x18generator_ac_out_pow_max\x18\xb9\x02 \x01(\rH\x8e\x02\x88\x01\x01\x12\'\n\x18generator_dc_out_pow_max\x18\xba\x02 \x01(\rH\x8f\x02\x88\x01\x01\x12)\n\x1agenerator_sub_battery_temp\x18\xbb\x02 \x01(\x05H\x90\x02\x88\x01\x01\x12(\n\x19generator_sub_battery_soc\x18\xbc\x02 \x01(\rH\x91\x02\x88\x01\x01\x12*\n\x1bgenerator_sub_battery_state\x18\xbd\x02 \x01(\rH\x92\x02\x88\x01\x01\x12(\n\x19generator_maintence_state\x18\xbf\x02 \x01(\x08H\x93\x02\x88\x01\x01\x12%\n\x16generator_pcs_err_code\x18\xca\x02 \x01(\rH\x94\x02\x88\x01\x01\x12(\n\x1agenerator_conn_dev_errcode\x18{ \x01(\rH\x95\x02\x88\x01\x01\x12\x38\n\x13sp_charger_chg_mode\x18\xc5\x04 \x01(\x0e\x32\x14.SP_CHARGER_CHG_MODEH\x96\x02\x88\x01\x01\x12"\n\x13sp_charger_chg_open\x18\xd5\x04 \x01(\x08H\x97\x02\x88\x01\x01\x12\'\n\x18sp_charger_chg_pow_limit\x18\xd6\x04 \x01(\x02H\x98\x02\x88\x01\x01\x12%\n\x16sp_charger_chg_pow_max\x18\xdb\x04 \x01(\x02H\x99\x02\x88\x01\x01\x12#\n\x14sp_charger_run_state\x18\xc6\x04 \x01(\rH\x9a\x02\x88\x01\x01\x12(\n\x19sp_charger_is_connect_car\x18\xc7\x04 \x01(\x08H\x9b\x02\x88\x01\x01\x12.\n\x1fsp_charger_car_batt_vol_setting\x18\x8a\x01 \x01(\rH\x9c\x02\x88\x01\x01\x12&\n\x17sp_charger_car_batt_vol\x18\x8b\x01 \x01(\x02H\x9d\x02\x88\x01\x01\x12#\n\x14module_bluetooth_snr\x18\xd7\x04 \x01(\x02H\x9e\x02\x88\x01\x01\x12$\n\x15module_bluetooth_rssi\x18\xd8\x04 \x01(\x02H\x9f\x02\x88\x01\x01\x12\x1e\n\x0fmodule_wifi_snr\x18\xd9\x04 \x01(\x02H\xa0\x02\x88\x01\x01\x12\x1f\n\x10module_wifi_rssi\x18\xda\x04 \x01(\x02H\xa1\x02\x88\x01\x01\x12/\n installment_payment_serve_enable\x18\xcf\x04 \x01(\x08H\xa2\x02\x88\x01\x01\x12\x30\n\x0fserve_middlemen\x18\xd0\x04 \x01(\x0e\x32\x10.SERVE_MIDDLEMENH\xa3\x02\x88\x01\x01\x12T\n!installment_payment_overdue_limit\x18\xd1\x04 \x01(\x0e\x32".INSTALLMENT_PAYMENT_OVERDUE_LIMITH\xa4\x02\x88\x01\x01\x12\x44\n\x19installment_payment_state\x18\xd2\x04 \x01(\x0e\x32\x1a.INSTALLMENT_PAYMENT_STATEH\xa5\x02\x88\x01\x01\x12\x31\n"installment_payment_start_utc_time\x18\xd3\x04 \x01(\rH\xa6\x02\x88\x01\x01\x12\x39\n*installment_payment_overdue_limit_utc_time\x18\xd4\x04 \x01(\rH\xa7\x02\x88\x01\x01\x42\n\n\x08_errcodeB\r\n\x0b_sys_statusB\x12\n\x10_dev_online_flagB\x0f\n\r_utc_timezoneB\x12\n\x10_utc_timezone_idB\x0f\n\r_utc_set_modeB\x14\n\x12_cms_bms_run_stateB\x0f\n\r_cms_batt_socB\x0f\n\r_cms_batt_sohB\x14\n\x12_cms_chg_dsg_stateB\x14\n\x12_cms_batt_full_capB\x16\n\x14_cms_batt_design_capB\x16\n\x14_cms_batt_remain_capB\x17\n\x15_cms_batt_full_energyB\x13\n\x11_cms_dsg_rem_timeB\x13\n\x11_cms_chg_rem_timeB\x17\n\x15_cms_batt_pow_out_maxB\x16\n\x14_cms_batt_pow_in_maxB\x10\n\x0e_cms_batt_tempB\x12\n\x10_cms_max_chg_socB\x12\n\x10_cms_min_dsg_socB\x0f\n\r_bms_batt_socB\x0f\n\r_bms_batt_sohB\x14\n\x12_bms_chg_dsg_stateB\x11\n\x0f_bms_design_capB\x13\n\x11_bms_dsg_rem_timeB\x13\n\x11_bms_chg_rem_timeB\x14\n\x12_bms_min_cell_tempB\x14\n\x12_bms_max_cell_tempB\x13\n\x11_bms_min_mos_tempB\x13\n\x11_bms_max_mos_tempB\x12\n\x10_dev_sleep_stateB\n\n\x08_en_beepB\x0c\n\n_lcd_lightB\x0e\n\x0c_ac_out_openB\x17\n\x15_btn_ac_out_lv_switchB\x17\n\x15_btn_ac_out_hv_switchB\x0e\n\x0c_dc_out_openB\x18\n\x16_btn_dc_12v_out_switchB\x11\n\x0f_btn_usb_switchB\x13\n\x11_dev_standby_timeB\x12\n\x10_screen_off_timeB\x12\n\x10_ac_standby_timeB\x12\n\x10_dc_standby_timeB\x13\n\x11_ble_standby_timeB\x0c\n\n_ups_alramB\x0b\n\t_led_modeB\x12\n\x10_low_power_alarmB\x13\n\x11_silence_chg_wattB\x0e\n\x0c_ac_out_freqB\x11\n\x0f_llc_hv_lv_flagB\x14\n\x12_ac_always_on_flagB\x12\n\x10_ac_hv_always_onB\x12\n\x10_ac_lv_always_onB\x18\n\x16_ac_always_on_mini_socB\x0c\n\n_xboost_enB\x1a\n\x18_output_power_off_memoryB\x15\n\x13_fast_charge_switchB\x10\n\x0e_llc_GFCI_flagB\x18\n\x16_ac_energy_saving_openB\x15\n\x13_bypass_out_disableB\x19\n\x17_pv_dc_chg_setting_listB\x0e\n\x0c_pv_chg_typeB\x16\n\x14_energy_backup_stateB\x1a\n\x18_energy_backup_start_socB\x13\n\x11_energy_backup_enB\x17\n\x15_storm_pattern_enableB\x1a\n\x18_storm_pattern_open_flagB\x19\n\x17_storm_pattern_end_timeB\x14\n\x12_time_task_currentB\x1c\n\x1a_current_time_task_v2_itemB\x1a\n\x18_time_task_conflict_flagB\x17\n\x15_time_task_change_cntB\x15\n\x13_cms_oil_self_startB\x11\n\x0f_cms_oil_on_socB\x12\n\x10_cms_oil_off_socB\x1a\n\x18_wireless_oil_self_startB\x16\n\x14_wireless_oil_on_socB\x17\n\x15_wireless_oil_off_socB \n\x1e_generator_pv_hybrid_mode_openB#\n!_generator_pv_hybrid_mode_soc_maxB\x1b\n\x19_generator_care_mode_openB!\n\x1f_generator_care_mode_start_timeB\x18\n\x16_multi_bp_chg_dsg_modeB\x0f\n\r_pow_in_sum_wB\x10\n\x0e_pow_out_sum_wB\x11\n\x0f_pow_get_qcusb1B\x11\n\x0f_pow_get_qcusb2B\x11\n\x0f_pow_get_typec1B\x11\n\x0f_pow_get_typec2B\x0f\n\r_pow_get_pv_hB\x0f\n\r_pow_get_pv_lB\r\n\x0b_pow_get_pvB\x0e\n\x0c_pow_get_pv2B\x0e\n\x0c_pow_get_12vB\x0e\n\x0c_pow_get_24vB\x0e\n\x0c_pow_get_llcB\r\n\x0b_pow_get_acB\x10\n\x0e_pow_get_ac_inB\x11\n\x0f_pow_get_ac_outB\x14\n\x12_pow_get_ac_hv_outB\x14\n\x12_pow_get_ac_lv_outB\x19\n\x17_pow_get_ac_lv_tt30_outB\x0e\n\x0c_pow_get_5p8B\r\n\x0b_pow_get_dcB\x0e\n\x0c_pow_get_bmsB\x10\n\x0e_pow_get_4p8_1B\x10\n\x0e_pow_get_4p8_2B\x0e\n\x0c_pow_get_dcpB\x0f\n\r_pow_get_dcp2B\x12\n\x10_pow_get_dc_bidiB\x19\n\x17_display_statistics_sumB\x13\n\x11_flow_info_qcusb1B\x13\n\x11_flow_info_qcusb2B\x13\n\x11_flow_info_typec1B\x13\n\x11_flow_info_typec2B\x11\n\x0f_flow_info_pv_hB\x11\n\x0f_flow_info_pv_lB\x0f\n\r_flow_info_pvB\x10\n\x0e_flow_info_pv2B\x10\n\x0e_flow_info_12vB\x10\n\x0e_flow_info_24vB\x12\n\x10_flow_info_ac2dcB\x12\n\x10_flow_info_dc2acB\x12\n\x10_flow_info_ac_inB\x16\n\x14_flow_info_ac_hv_outB\x16\n\x14_flow_info_ac_lv_outB\x13\n\x11_flow_info_5p8_inB\x14\n\x12_flow_info_5p8_outB\x13\n\x11_flow_info_ac_outB\x14\n\x12_flow_info_bms_dsgB\x14\n\x12_flow_info_bms_chgB\x15\n\x13_flow_info_4p8_1_inB\x16\n\x14_flow_info_4p8_1_outB\x15\n\x13_flow_info_4p8_2_inB\x16\n\x14_flow_info_4p8_2_outB\x13\n\x11_flow_info_dcp_inB\x14\n\x12_flow_info_dcp_outB\x14\n\x12_flow_info_dcp2_inB\x15\n\x13_flow_info_dcp2_outB\x19\n\x17_plug_in_info_pv_h_flagB\x19\n\x17_plug_in_info_pv_h_typeB!\n\x1f_plug_in_info_pv_h_charger_flagB\x1f\n\x1d_plug_in_info_pv_h_dc_amp_maxB \n\x1e_plug_in_info_pv_h_chg_amp_maxB \n\x1e_plug_in_info_pv_h_chg_vol_maxB\x19\n\x17_plug_in_info_pv_l_flagB\x19\n\x17_plug_in_info_pv_l_typeB!\n\x1f_plug_in_info_pv_l_charger_flagB\x1f\n\x1d_plug_in_info_pv_l_dc_amp_maxB \n\x1e_plug_in_info_pv_l_chg_amp_maxB \n\x1e_plug_in_info_pv_l_chg_vol_maxB\x17\n\x15_plug_in_info_pv_flagB\x17\n\x15_plug_in_info_pv_typeB\x1f\n\x1d_plug_in_info_pv_charger_flagB\x1d\n\x1b_plug_in_info_pv_dc_amp_maxB\x1e\n\x1c_plug_in_info_pv_chg_amp_maxB\x1e\n\x1c_plug_in_info_pv_chg_vol_maxB\x1f\n\x1d_plug_in_info_pv_chg_max_listB\x18\n\x16_plug_in_info_pv2_flagB\x18\n\x16_plug_in_info_pv2_typeB \n\x1e_plug_in_info_pv2_charger_flagB\x1e\n\x1c_plug_in_info_pv2_dc_amp_maxB\x1f\n\x1d_plug_in_info_pv2_chg_amp_maxB\x1f\n\x1d_plug_in_info_pv2_chg_vol_maxB \n\x1e_plug_in_info_pv2_chg_max_listB\x1a\n\x18_plug_in_info_ac_in_flagB\x1f\n\x1d_plug_in_info_ac_charger_flagB\x19\n\x17_plug_in_info_ac_in_feqB!\n\x1f_plug_in_info_ac_in_chg_pow_maxB%\n#_plug_in_info_ac_in_chg_hal_pow_maxB\x1e\n\x1c_plug_in_info_ac_in_chg_modeB"\n _plug_in_info_ac_out_dsg_pow_maxB\x1f\n\x1d_plug_in_info_5p8_chg_pow_maxB#\n!_plug_in_info_5p8_chg_hal_pow_maxB\x1f\n\x1d_plug_in_info_5p8_dsg_pow_maxB\x18\n\x16_plug_in_info_5p8_flagB\x1b\n\x19_plug_in_info_5p8_dsg_chgB \n\x1e_plug_in_info_5p8_charger_flagB\x18\n\x16_plug_in_info_5p8_typeB\x1a\n\x18_plug_in_info_5p8_detailB\x16\n\x14_plug_in_info_5p8_snB\x1d\n\x1b_plug_in_info_5p8_run_stateB\x1c\n\x1a_plug_in_info_5p8_err_codeB\x1c\n\x1a_plug_in_info_5p8_firm_verB\x18\n\x16_plug_in_info_5p8_resvB\x1f\n\x1d_plug_in_info_acp_chg_pow_maxB#\n!_plug_in_info_acp_chg_hal_pow_maxB\x1f\n\x1d_plug_in_info_acp_dsg_pow_maxB\x18\n\x16_plug_in_info_acp_flagB\x1b\n\x19_plug_in_info_acp_dsg_chgB \n\x1e_plug_in_info_acp_charger_flagB\x18\n\x16_plug_in_info_acp_typeB\x1a\n\x18_plug_in_info_acp_detailB\x16\n\x14_plug_in_info_acp_snB\x1d\n\x1b_plug_in_info_acp_run_stateB\x1c\n\x1a_plug_in_info_acp_err_codeB\x1c\n\x1a_plug_in_info_acp_firm_verB\x18\n\x16_plug_in_info_acp_resvB\x1c\n\x1a_plug_in_info_dc_bidi_flagB\x1b\n\x19_plug_in_info_dcp_in_flagB \n\x1e_plug_in_info_dcp_dsg_chg_typeB \n\x1e_plug_in_info_dcp_charger_flagB\x18\n\x16_plug_in_info_dcp_typeB\x1a\n\x18_plug_in_info_dcp_detailB\x16\n\x14_plug_in_info_dcp_snB\x1d\n\x1b_plug_in_info_dcp_run_stateB\x1c\n\x1a_plug_in_info_dcp_firm_verB\x18\n\x16_plug_in_info_dcp_resvB\x1c\n\x1a_plug_in_info_dcp2_in_flagB!\n\x1f_plug_in_info_dcp2_dsg_chg_typeB!\n\x1f_plug_in_info_dcp2_charger_flagB\x19\n\x17_plug_in_info_dcp2_typeB\x1b\n\x19_plug_in_info_dcp2_detailB\x17\n\x15_plug_in_info_dcp2_snB\x1e\n\x1c_plug_in_info_dcp2_run_stateB\x1d\n\x1b_plug_in_info_dcp2_firm_verB\x19\n\x17_plug_in_info_dcp2_resvB\x1d\n\x1b_plug_in_info_4p8_1_in_flagB"\n _plug_in_info_4p8_1_dsg_chg_typeB"\n _plug_in_info_4p8_1_charger_flagB\x1a\n\x18_plug_in_info_4p8_1_typeB\x1c\n\x1a_plug_in_info_4p8_1_detailB\x18\n\x16_plug_in_info_4p8_1_snB\x1f\n\x1d_plug_in_info_4p8_1_run_stateB\x1e\n\x1c_plug_in_info_4p8_1_err_codeB\x1e\n\x1c_plug_in_info_4p8_1_firm_verB\x1a\n\x18_plug_in_info_4p8_1_resvB\x1d\n\x1b_plug_in_info_4p8_2_in_flagB"\n _plug_in_info_4p8_2_dsg_chg_typeB"\n _plug_in_info_4p8_2_charger_flagB\x1a\n\x18_plug_in_info_4p8_2_typeB\x1c\n\x1a_plug_in_info_4p8_2_detailB\x18\n\x16_plug_in_info_4p8_2_snB\x1f\n\x1d_plug_in_info_4p8_2_run_stateB\x1e\n\x1c_plug_in_info_4p8_2_err_codeB\x1e\n\x1c_plug_in_info_4p8_2_firm_verB\x1a\n\x18_plug_in_info_4p8_2_resvB\x1f\n\x1d_wireless_coordinate_dev_listB\x0e\n\x0c_pd_err_codeB\x10\n\x0e_mppt_err_codeB\x0f\n\r_llc_err_codeB\x13\n\x11_llc_inv_err_codeB\x10\n\x0e_dcdc_err_codeB\x1c\n\x1a_plug_in_info_dcp_err_codeB\x1d\n\x1b_plug_in_info_dcp2_err_codeB\x0f\n\r_bms_err_codeB\x0f\n\r_inv_err_codeB\x17\n\x15_err_code_record_listB\x10\n\x0e_pcs_fan_levelB\x13\n\x11_pcs_fan_err_flagB\x17\n\x15_generator_fuels_typeB\x18\n\x16_generator_remain_timeB\x15\n\x13_generator_run_timeB\x19\n\x17_generator_total_outputB\x1b\n\x19_generator_abnormal_stateB\x10\n\x0e_fuels_oil_valB\x1b\n\x19_fuels_liquefied_gas_typeB\x1b\n\x19_fuels_liquefied_gas_uintB\x1a\n\x18_fuels_liquefied_gas_valB\'\n%_fuels_liquefied_gas_consume_per_hourB!\n\x1f_fuels_liquefied_gas_remain_valB\x1f\n\x1d_fuels_liquefied_gas_lpg_uintB\x1f\n\x1d_fuels_liquefied_gas_lng_uintB\x16\n\x14_generator_perf_modeB\x18\n\x16_generator_engine_openB\x19\n\x17_generator_low_power_enB \n\x1e_generator_low_power_thresholdB\x1b\n\x19_generator_lpg_monitor_enB\x18\n\x16_generator_out_pow_maxB\x1b\n\x19_generator_ac_out_pow_maxB\x1b\n\x19_generator_dc_out_pow_maxB\x1d\n\x1b_generator_sub_battery_tempB\x1c\n\x1a_generator_sub_battery_socB\x1e\n\x1c_generator_sub_battery_stateB\x1c\n\x1a_generator_maintence_stateB\x19\n\x17_generator_pcs_err_codeB\x1d\n\x1b_generator_conn_dev_errcodeB\x16\n\x14_sp_charger_chg_modeB\x16\n\x14_sp_charger_chg_openB\x1b\n\x19_sp_charger_chg_pow_limitB\x19\n\x17_sp_charger_chg_pow_maxB\x17\n\x15_sp_charger_run_stateB\x1c\n\x1a_sp_charger_is_connect_carB"\n _sp_charger_car_batt_vol_settingB\x1a\n\x18_sp_charger_car_batt_volB\x17\n\x15_module_bluetooth_snrB\x18\n\x16_module_bluetooth_rssiB\x12\n\x10_module_wifi_snrB\x13\n\x11_module_wifi_rssiB#\n!_installment_payment_serve_enableB\x12\n\x10_serve_middlemenB$\n"_installment_payment_overdue_limitB\x1c\n\x1a_installment_payment_stateB%\n#_installment_payment_start_utc_timeB-\n+_installment_payment_overdue_limit_utc_time"\x89-\n\x15RuntimePropertyUpload\x12\x31\n#display_property_full_upload_period\x18\xa5\x02 \x01(\x05H\x00\x88\x01\x01\x12\x38\n*display_property_incremental_upload_period\x18\xa6\x02 \x01(\x05H\x01\x88\x01\x01\x12\x31\n#runtime_property_full_upload_period\x18\xa7\x02 \x01(\x05H\x02\x88\x01\x01\x12\x38\n*runtime_property_incremental_upload_period\x18\xa8\x02 \x01(\x05H\x03\x88\x01\x01\x12\x1a\n\x0c\x63ms_batt_vol\x18\x88\x02 \x01(\x02H\x04\x88\x01\x01\x12\x1a\n\x0c\x63ms_batt_amp\x18\x89\x02 \x01(\x02H\x05\x88\x01\x01\x12\x1d\n\x0f\x63ms_chg_req_vol\x18\x8a\x02 \x01(\x02H\x06\x88\x01\x01\x12\x1d\n\x0f\x63ms_chg_req_amp\x18\x8b\x02 \x01(\x02H\x07\x88\x01\x01\x12\x1a\n\x0c\x62ms_firm_ver\x18\xf1\x01 \x01(\rH\x08\x88\x01\x01\x12\x1a\n\x0c\x62ms_batt_vol\x18\xf4\x01 \x01(\x02H\t\x88\x01\x01\x12\x1a\n\x0c\x62ms_batt_amp\x18\xf5\x01 \x01(\x02H\n\x88\x01\x01\x12\x1b\n\rbms_bal_state\x18\xf6\x01 \x01(\rH\x0b\x88\x01\x01\x12\x1a\n\x0c\x62ms_full_cap\x18\xf7\x01 \x01(\rH\x0c\x88\x01\x01\x12\x1c\n\x0e\x62ms_remain_cap\x18\xf9\x01 \x01(\rH\r\x88\x01\x01\x12\x1b\n\rbms_alm_state\x18\xfa\x01 \x01(\rH\x0e\x88\x01\x01\x12\x1d\n\x0f\x62ms_alm_state_2\x18\xa3\x02 \x01(\rH\x0f\x88\x01\x01\x12\x1b\n\rbms_pro_state\x18\xfb\x01 \x01(\rH\x10\x88\x01\x01\x12\x1d\n\x0f\x62ms_pro_state_2\x18\xa4\x02 \x01(\rH\x11\x88\x01\x01\x12\x1b\n\rbms_flt_state\x18\xfc\x01 \x01(\rH\x12\x88\x01\x01\x12\x1a\n\x0c\x62ms_err_code\x18\xfd\x01 \x01(\rH\x13\x88\x01\x01\x12\x1e\n\x10\x62ms_min_cell_vol\x18\x80\x02 \x01(\rH\x14\x88\x01\x01\x12\x1e\n\x10\x62ms_max_cell_vol\x18\x81\x02 \x01(\rH\x15\x88\x01\x01\x12\x1a\n\rac_phase_type\x18\x15 \x01(\rH\x16\x88\x01\x01\x12\x1a\n\rpcs_work_mode\x18\x18 \x01(\rH\x17\x88\x01\x01\x12\x42\n\x16runtime_statistics_sum\x18\xd0\x03 \x01(\x0b\x32\x1c.RuntimeStatisticsRecordListH\x18\x88\x01\x01\x12"\n\x15plug_in_info_pv_h_vol\x18) \x01(\x02H\x19\x88\x01\x01\x12#\n\x15plug_in_info_pv_h_amp\x18\xdd\x01 \x01(\x02H\x1a\x88\x01\x01\x12"\n\x15plug_in_info_pv_l_vol\x18, \x01(\x02H\x1b\x88\x01\x01\x12#\n\x15plug_in_info_pv_l_amp\x18\xde\x01 \x01(\x02H\x1c\x88\x01\x01\x12!\n\x13plug_in_info_pv_vol\x18\xfc\x02 \x01(\x02H\x1d\x88\x01\x01\x12!\n\x13plug_in_info_pv_amp\x18\xfd\x02 \x01(\x02H\x1e\x88\x01\x01\x12"\n\x14plug_in_info_pv2_vol\x18\xba\x03 \x01(\x02H\x1f\x88\x01\x01\x12!\n\x14plug_in_info_pv2_amp\x18G \x01(\x02H \x88\x01\x01\x12#\n\x16plug_in_info_ac_in_vol\x18\x44 \x01(\x02H!\x88\x01\x01\x12$\n\x16plug_in_info_ac_in_amp\x18\xdf\x01 \x01(\x02H"\x88\x01\x01\x12%\n\x18plug_in_info_ac_out_type\x18; \x01(\rH#\x88\x01\x01\x12%\n\x18plug_in_info_ac_out_freq\x18< \x01(\rH$\x88\x01\x01\x12$\n\x17plug_in_info_ac_out_vol\x18\x43 \x01(\x02H%\x88\x01\x01\x12%\n\x17plug_in_info_ac_out_amp\x18\xe0\x01 \x01(\x02H&\x88\x01\x01\x12!\n\x14plug_in_info_5p8_vol\x18\x45 \x01(\x02H\'\x88\x01\x01\x12"\n\x14plug_in_info_5p8_amp\x18\xe1\x01 \x01(\x02H(\x88\x01\x01\x12"\n\x15plug_in_info_5p8_freq\x18\x42 \x01(\rH)\x88\x01\x01\x12!\n\x14plug_in_info_acp_vol\x18x \x01(\x02H*\x88\x01\x01\x12!\n\x14plug_in_info_acp_amp\x18y \x01(\x02H+\x88\x01\x01\x12"\n\x15plug_in_info_acp_freq\x18z \x01(\rH,\x88\x01\x01\x12"\n\x14plug_in_info_12v_vol\x18\xfe\x02 \x01(\x02H-\x88\x01\x01\x12"\n\x14plug_in_info_12v_amp\x18\xff\x02 \x01(\x02H.\x88\x01\x01\x12"\n\x14plug_in_info_bms_vol\x18\xa9\x01 \x01(\x02H/\x88\x01\x01\x12%\n\x18plug_in_info_dc_bidi_vol\x18g \x01(\x02H0\x88\x01\x01\x12%\n\x18plug_in_info_dc_bidi_amp\x18h \x01(\x02H1\x88\x01\x01\x12"\n\x14plug_in_info_dcp_vol\x18\xbb\x03 \x01(\x02H2\x88\x01\x01\x12"\n\x14plug_in_info_dcp_amp\x18\xc0\x03 \x01(\x02H3\x88\x01\x01\x12"\n\x15plug_in_info_dcp2_vol\x18\\ \x01(\x02H4\x88\x01\x01\x12"\n\x15plug_in_info_dcp2_amp\x18] \x01(\x02H5\x88\x01\x01\x12$\n\x16plug_in_info_4p8_1_vol\x18\xa7\x01 \x01(\x02H6\x88\x01\x01\x12$\n\x16plug_in_info_4p8_1_amp\x18\xef\x01 \x01(\x02H7\x88\x01\x01\x12$\n\x16plug_in_info_4p8_2_vol\x18\xa8\x01 \x01(\x02H8\x88\x01\x01\x12$\n\x16plug_in_info_4p8_2_amp\x18\xf0\x01 \x01(\x02H9\x88\x01\x01\x12\x1e\n\x10pd_mppt_comm_err\x18\xac\x01 \x01(\x08H:\x88\x01\x01\x12\x1d\n\x0fpd_llc_comm_err\x18\xad\x01 \x01(\x08H;\x88\x01\x01\x12\x1d\n\x0fpd_bms_comm_err\x18\xae\x01 \x01(\x08H<\x88\x01\x01\x12\x1d\n\x0fpd_iot_comm_err\x18\xaf\x01 \x01(\x08H=\x88\x01\x01\x12\x1e\n\x10pd_dcdc_comm_err\x18\xbc\x03 \x01(\x08H>\x88\x01\x01\x12\x1d\n\x0fpd_inv_comm_err\x18\xbd\x03 \x01(\x08H?\x88\x01\x01\x12\x19\n\x0bpd_firm_ver\x18\xb0\x01 \x01(\rH@\x88\x01\x01\x12\x1a\n\x0ciot_firm_ver\x18\xb1\x01 \x01(\rHA\x88\x01\x01\x12\x1b\n\rmppt_firm_ver\x18\xb2\x01 \x01(\rHB\x88\x01\x01\x12\x1a\n\x0cllc_firm_ver\x18\xb3\x01 \x01(\rHC\x88\x01\x01\x12\x1e\n\x10llc_inv_firm_ver\x18\xe7\x01 \x01(\rHD\x88\x01\x01\x12\x1b\n\rdcdc_firm_ver\x18\xbe\x03 \x01(\rHE\x88\x01\x01\x12\x1a\n\x0cinv_firm_ver\x18\xbf\x03 \x01(\rHF\x88\x01\x01\x12\x18\n\x0btemp_pcs_dc\x18\x1a \x01(\x02HG\x88\x01\x01\x12\x18\n\x0btemp_pcs_ac\x18\x1b \x01(\x02HH\x88\x01\x01\x12\x16\n\ttemp_pv_h\x18\x1c \x01(\x02HI\x88\x01\x01\x12\x16\n\ttemp_pv_l\x18\x1d \x01(\x02HJ\x88\x01\x01\x12\x15\n\x07temp_pv\x18\xfb\x02 \x01(\x02HK\x88\x01\x01\x12\x16\n\x08temp_pv2\x18\xb8\x03 \x01(\x02HL\x88\x01\x01\x12\x1f\n\x11\x62ms_overload_icon\x18\x94\x02 \x01(\rHM\x88\x01\x01\x12\x1b\n\rbms_warn_icon\x18\x95\x02 \x01(\rHN\x88\x01\x01\x12 \n\x12\x62ms_high_temp_icon\x18\x96\x02 \x01(\rHO\x88\x01\x01\x12\x1f\n\x11\x62ms_low_temp_icon\x18\x97\x02 \x01(\rHP\x88\x01\x01\x12\x1c\n\x0e\x62ms_limit_icon\x18\x98\x02 \x01(\rHQ\x88\x01\x01\x12!\n\x13generator_run_state\x18\xc0\x02 \x01(\rHR\x88\x01\x01\x12$\n\x16generator_oil_val_real\x18\xc1\x02 \x01(\rHS\x88\x01\x01\x12"\n\x14generator_engine_spd\x18\xc2\x02 \x01(\x05HT\x88\x01\x01\x12&\n\x18generator_engine_oil_val\x18\xc3\x02 \x01(\rHU\x88\x01\x01\x12-\n\x1fgenerator_engine_activation_cnt\x18\xc4\x02 \x01(\rHV\x88\x01\x01\x12(\n\x1agenerator_engine_head_temp\x18\xc5\x02 \x01(\x05HW\x88\x01\x01\x12\'\n\x19generator_sub_battery_vol\x18\xc6\x02 \x01(\rHX\x88\x01\x01\x12\'\n\x19generator_sub_battery_amp\x18\xc7\x02 \x01(\x05HY\x88\x01\x01\x12-\n\x1fgenerator_commc_cnt_ems_to_psdr\x18\xc8\x02 \x01(\rHZ\x88\x01\x01\x12-\n\x1fgenerator_commc_cnt_psdr_to_ems\x18\xc9\x02 \x01(\rH[\x88\x01\x01\x12%\n\x17generator_pcs_fan_level\x18\xcb\x02 \x01(\rH\\\x88\x01\x01\x12#\n\x15generator_pcs_bus_vol\x18\xcc\x02 \x01(\x02H]\x88\x01\x01\x12#\n\x15generator_pcs_bus_amp\x18\xcd\x02 \x01(\x02H^\x88\x01\x01\x12!\n\x13generator_pcs_temp1\x18\xce\x02 \x01(\x05H_\x88\x01\x01\x12!\n\x13generator_pcs_temp2\x18\xcf\x02 \x01(\x05H`\x88\x01\x01\x12&\n\x18generator_pcs_fules_type\x18\xd0\x02 \x01(\rHa\x88\x01\x01\x42&\n$_display_property_full_upload_periodB-\n+_display_property_incremental_upload_periodB&\n$_runtime_property_full_upload_periodB-\n+_runtime_property_incremental_upload_periodB\x0f\n\r_cms_batt_volB\x0f\n\r_cms_batt_ampB\x12\n\x10_cms_chg_req_volB\x12\n\x10_cms_chg_req_ampB\x0f\n\r_bms_firm_verB\x0f\n\r_bms_batt_volB\x0f\n\r_bms_batt_ampB\x10\n\x0e_bms_bal_stateB\x0f\n\r_bms_full_capB\x11\n\x0f_bms_remain_capB\x10\n\x0e_bms_alm_stateB\x12\n\x10_bms_alm_state_2B\x10\n\x0e_bms_pro_stateB\x12\n\x10_bms_pro_state_2B\x10\n\x0e_bms_flt_stateB\x0f\n\r_bms_err_codeB\x13\n\x11_bms_min_cell_volB\x13\n\x11_bms_max_cell_volB\x10\n\x0e_ac_phase_typeB\x10\n\x0e_pcs_work_modeB\x19\n\x17_runtime_statistics_sumB\x18\n\x16_plug_in_info_pv_h_volB\x18\n\x16_plug_in_info_pv_h_ampB\x18\n\x16_plug_in_info_pv_l_volB\x18\n\x16_plug_in_info_pv_l_ampB\x16\n\x14_plug_in_info_pv_volB\x16\n\x14_plug_in_info_pv_ampB\x17\n\x15_plug_in_info_pv2_volB\x17\n\x15_plug_in_info_pv2_ampB\x19\n\x17_plug_in_info_ac_in_volB\x19\n\x17_plug_in_info_ac_in_ampB\x1b\n\x19_plug_in_info_ac_out_typeB\x1b\n\x19_plug_in_info_ac_out_freqB\x1a\n\x18_plug_in_info_ac_out_volB\x1a\n\x18_plug_in_info_ac_out_ampB\x17\n\x15_plug_in_info_5p8_volB\x17\n\x15_plug_in_info_5p8_ampB\x18\n\x16_plug_in_info_5p8_freqB\x17\n\x15_plug_in_info_acp_volB\x17\n\x15_plug_in_info_acp_ampB\x18\n\x16_plug_in_info_acp_freqB\x17\n\x15_plug_in_info_12v_volB\x17\n\x15_plug_in_info_12v_ampB\x17\n\x15_plug_in_info_bms_volB\x1b\n\x19_plug_in_info_dc_bidi_volB\x1b\n\x19_plug_in_info_dc_bidi_ampB\x17\n\x15_plug_in_info_dcp_volB\x17\n\x15_plug_in_info_dcp_ampB\x18\n\x16_plug_in_info_dcp2_volB\x18\n\x16_plug_in_info_dcp2_ampB\x19\n\x17_plug_in_info_4p8_1_volB\x19\n\x17_plug_in_info_4p8_1_ampB\x19\n\x17_plug_in_info_4p8_2_volB\x19\n\x17_plug_in_info_4p8_2_ampB\x13\n\x11_pd_mppt_comm_errB\x12\n\x10_pd_llc_comm_errB\x12\n\x10_pd_bms_comm_errB\x12\n\x10_pd_iot_comm_errB\x13\n\x11_pd_dcdc_comm_errB\x12\n\x10_pd_inv_comm_errB\x0e\n\x0c_pd_firm_verB\x0f\n\r_iot_firm_verB\x10\n\x0e_mppt_firm_verB\x0f\n\r_llc_firm_verB\x13\n\x11_llc_inv_firm_verB\x10\n\x0e_dcdc_firm_verB\x0f\n\r_inv_firm_verB\x0e\n\x0c_temp_pcs_dcB\x0e\n\x0c_temp_pcs_acB\x0c\n\n_temp_pv_hB\x0c\n\n_temp_pv_lB\n\n\x08_temp_pvB\x0b\n\t_temp_pv2B\x14\n\x12_bms_overload_iconB\x10\n\x0e_bms_warn_iconB\x15\n\x13_bms_high_temp_iconB\x14\n\x12_bms_low_temp_iconB\x11\n\x0f_bms_limit_iconB\x16\n\x14_generator_run_stateB\x19\n\x17_generator_oil_val_realB\x17\n\x15_generator_engine_spdB\x1b\n\x19_generator_engine_oil_valB"\n _generator_engine_activation_cntB\x1d\n\x1b_generator_engine_head_tempB\x1c\n\x1a_generator_sub_battery_volB\x1c\n\x1a_generator_sub_battery_ampB"\n _generator_commc_cnt_ems_to_psdrB"\n _generator_commc_cnt_psdr_to_emsB\x1a\n\x18_generator_pcs_fan_levelB\x18\n\x16_generator_pcs_bus_volB\x18\n\x16_generator_pcs_bus_ampB\x16\n\x14_generator_pcs_temp1B\x16\n\x14_generator_pcs_temp2B\x1b\n\x19_generator_pcs_fules_type"\x89\x02\n\nDevRequest\x12\x19\n\x0c\x64\x65v_utc_time\x18\x01 \x01(\rH\x00\x88\x01\x01\x12\x1d\n\x10\x64\x65v_utc_timezone\x18\x02 \x01(\x02H\x01\x88\x01\x01\x12+\n\x1erequire_property_upload_period\x18\x03 \x01(\x08H\x02\x88\x01\x01\x12\x32\n\x14require_tou_strategy\x18\x04 \x01(\x0b\x32\x0f.ReqTouStrategyH\x03\x88\x01\x01\x42\x0f\n\r_dev_utc_timeB\x13\n\x11_dev_utc_timezoneB!\n\x1f_require_property_upload_periodB\x17\n\x15_require_tou_strategy"\xb6\x01\n\rDevRequestAck\x12\x17\n\nrequest_id\x18\x01 \x01(\rH\x00\x88\x01\x01\x12\x17\n\nrequire_ok\x18\x02 \x01(\rH\x01\x88\x01\x01\x12:\n\x16property_upload_period\x18\x03 \x01(\x0b\x32\x15.PropertyUploadPeriodH\x02\x88\x01\x01\x42\r\n\x0b_request_idB\r\n\x0b_require_okB\x19\n\x17_property_upload_period*!\n\x0bMODULE_TYPE\x12\x12\n\x0eMODULE_TYPE_EF\x10\x00*\xa6\x01\n\x13SP_CHARGER_CHG_MODE\x12\x1c\n\x18SP_CHARGER_CHG_MODE_IDLE\x10\x00\x12#\n\x1fSP_CHARGER_CHG_MODE_DRIVING_CHG\x10\x01\x12\'\n#SP_CHARGER_CHG_MODE_BAT_MAINTENANCE\x10\x02\x12#\n\x1fSP_CHARGER_CHG_MODE_PARKING_CHG\x10\x03*H\n\x0fSERVE_MIDDLEMEN\x12\x18\n\x14SERVE_MIDDLEMEN_NONE\x10\x00\x12\x1b\n\x17SERVE_MIDDLEMEN_SUNNOVA\x10\x01*\xf1\x01\n\x19INSTALLMENT_PAYMENT_STATE\x12/\n+INSTALLMENT_PAYMENT_STATE_WAIT_FOT_ACTIVATE\x10\x00\x12\'\n#INSTALLMENT_PAYMENT_STATE_ACTIVATED\x10\x01\x12%\n!INSTALLMENT_PAYMENT_STATE_OVERDUE\x10\x02\x12$\n INSTALLMENT_PAYMENT_STATE_SETTLE\x10\x03\x12-\n)INSTALLMENT_PAYMENT_STATE_MANUAL_LOCKDOWN\x10\x04*\x83\x01\n!INSTALLMENT_PAYMENT_OVERDUE_LIMIT\x12*\n&INSTALLMENT_PAYMENT_OVERDUE_LIMIT_NONE\x10\x00\x12\x32\n.INSTALLMENT_PAYMENT_OVERDUE_LIMIT_CLOSE_OUTPUT\x10\x01*\xe3\x08\n\x11STATISTICS_OBJECT\x12\x1b\n\x17STATISTICS_OBJECT_START\x10\x00\x12#\n\x1fSTATISTICS_OBJECT_DEV_WORK_TIME\x10\x01\x12#\n\x1fSTATISTICS_OBJECT_AC_OUT_ENERGY\x10\x02\x12&\n"STATISTICS_OBJECT_DC12V_OUT_ENERGY\x10\x03\x12&\n"STATISTICS_OBJECT_TYPEC_OUT_ENERGY\x10\x04\x12%\n!STATISTICS_OBJECT_USBA_OUT_ENERGY\x10\x05\x12"\n\x1eSTATISTICS_OBJECT_AC_IN_ENERGY\x10\x06\x12"\n\x1eSTATISTICS_OBJECT_PV_IN_ENERGY\x10\x07\x12(\n$STATISTICS_OBJECT_AC_IN_0W_100W_TIME\x10\x08\x12*\n&STATISTICS_OBJECT_AC_IN_OVER_100W_TIME\x10\t\x12(\n$STATISTICS_OBJECT_AC_OUT_0W_50W_TIME\x10\n\x12*\n&STATISTICS_OBJECT_AC_OUT_50W_100W_TIME\x10\x0b\x12+\n\'STATISTICS_OBJECT_AC_OUT_100W_200W_TIME\x10\x0c\x12+\n\'STATISTICS_OBJECT_AC_OUT_OVER_200W_TIME\x10\r\x12+\n\'STATISTICS_OBJECT_AC_OUT_200W_300W_TIME\x10\x0e\x12+\n\'STATISTICS_OBJECT_AC_OUT_300W_400W_TIME\x10\x0f\x12+\n\'STATISTICS_OBJECT_AC_OUT_400W_500W_TIME\x10\x10\x12+\n\'STATISTICS_OBJECT_AC_OUT_OVER_500W_TIME\x10\x11\x12 \n\x1cSTATISTICS_OBJECT_PV_IN_TIME\x10\x12\x12#\n\x1fSTATISTICS_OBJECT_TYPEC_IN_TIME\x10\x13\x12(\n$STATISTICS_OBJECT_DC_OUT_0W_60W_TIME\x10\x14\x12*\n&STATISTICS_OBJECT_DC_OUT_OVER_60W_TIME\x10\x15\x12+\n\'STATISTICS_OBJECT_TYPEC_OUT_0W_30W_TIME\x10\x16\x12,\n(STATISTICS_OBJECT_TYPEC_OUT_30W_60W_TIME\x10\x17\x12-\n)STATISTICS_OBJECT_TYPEC_OUT_OVER_60W_TIME\x10\x18\x12#\n\x1fSTATISTICS_OBJECT_USBA_OUT_TIME\x10\x19\x12"\n\x1eSTATISTICS_OBJECT_LED_OUT_TIME\x10\x1a*q\n\x0e\x41\x43_IN_CHG_MODE\x12\x1f\n\x1b\x41\x43_IN_CHG_MODE_SELF_DEF_POW\x10\x00\x12"\n\x1e\x41\x43_IN_CHG_MODE_BAT_OPTIMAL_POW\x10\x01\x12\x1a\n\x16\x41\x43_IN_CHG_MODE_SILENCE\x10\x02*Q\n\rPV_PLUG_INDEX\x12\x16\n\x12PV_PLUG_INDEX_RESV\x10\x00\x12\x13\n\x0fPV_PLUG_INDEX_1\x10\x01\x12\x13\n\x0fPV_PLUG_INDEX_2\x10\x02*v\n\x0fPV_CHG_VOL_SPEC\x12\x18\n\x14PV_CHG_VOL_SPEC_RESV\x10\x00\x12\x17\n\x13PV_CHG_VOL_SPEC_12V\x10\x01\x12\x17\n\x13PV_CHG_VOL_SPEC_24V\x10\x02\x12\x17\n\x13PV_CHG_VOL_SPEC_48V\x10\x03*_\n\x0eTIME_TASK_MODE\x12\x17\n\x13TIME_TASK_MODE_RESV\x10\x00\x12\x1b\n\x17TIME_TASK_MODE_PER_WEEK\x10\x01\x12\x17\n\x13TIME_TASK_MODE_ONCE\x10\x02*\xa3\x02\n\x0eTIME_TASK_TYPE\x12\x19\n\x15TIME_TASK_TYPE_AC_CHG\x10\x00\x12\x19\n\x15TIME_TASK_TYPE_AC_DSG\x10\x01\x12\x1a\n\x16TIME_TASK_TYPE_AC2_DSG\x10\x02\x12\x19\n\x15TIME_TASK_TYPE_DC_CHG\x10\x03\x12\x1a\n\x16TIME_TASK_TYPE_DC2_CHG\x10\x04\x12\x19\n\x15TIME_TASK_TYPE_DC_DSG\x10\x05\x12\x19\n\x15TIME_TASK_TYPE_OIL_ON\x10\x06\x12\x1a\n\x16TIME_TASK_TYPE_OIL_OFF\x10\x07\x12\x1a\n\x16TIME_TASK_TYPE_USB_CHG\x10\x08\x12\x1a\n\x16TIME_TASK_TYPE_USB_DSG\x10\tB\x02P\x01\x62\x06proto3'
+)
+
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, "pr705_pb2", globals())
+if _descriptor._USE_C_DESCRIPTORS == False:
+
+    DESCRIPTOR._options = None
+    DESCRIPTOR._serialized_options = b"P\001"
+    _MODULE_TYPE._serialized_start = 44694
+    _MODULE_TYPE._serialized_end = 44727
+    _SP_CHARGER_CHG_MODE._serialized_start = 44730
+    _SP_CHARGER_CHG_MODE._serialized_end = 44896
+    _SERVE_MIDDLEMEN._serialized_start = 44898
+    _SERVE_MIDDLEMEN._serialized_end = 44970
+    _INSTALLMENT_PAYMENT_STATE._serialized_start = 44973
+    _INSTALLMENT_PAYMENT_STATE._serialized_end = 45214
+    _INSTALLMENT_PAYMENT_OVERDUE_LIMIT._serialized_start = 45217
+    _INSTALLMENT_PAYMENT_OVERDUE_LIMIT._serialized_end = 45348
+    _STATISTICS_OBJECT._serialized_start = 45351
+    _STATISTICS_OBJECT._serialized_end = 46474
+    _AC_IN_CHG_MODE._serialized_start = 46476
+    _AC_IN_CHG_MODE._serialized_end = 46589
+    _PV_PLUG_INDEX._serialized_start = 46591
+    _PV_PLUG_INDEX._serialized_end = 46672
+    _PV_CHG_VOL_SPEC._serialized_start = 46674
+    _PV_CHG_VOL_SPEC._serialized_end = 46792
+    _TIME_TASK_MODE._serialized_start = 46794
+    _TIME_TASK_MODE._serialized_end = 46889
+    _TIME_TASK_TYPE._serialized_start = 46892
+    _TIME_TASK_TYPE._serialized_end = 47183
+    _EVENTPUSH._serialized_start = 16
+    _EVENTPUSH._serialized_end = 275
+    _EVENTPUSH_LOGITEM._serialized_start = 118
+    _EVENTPUSH_LOGITEM._serialized_end = 247
+    _EVENTACK._serialized_start = 278
+    _EVENTACK._serialized_end = 406
+    _REQTOUSTRATEGY._serialized_start = 408
+    _REQTOUSTRATEGY._serialized_end = 462
+    _CFGBEEP._serialized_start = 464
+    _CFGBEEP._serialized_end = 563
+    _CFGACOUTALWAYSON._serialized_start = 566
+    _CFGACOUTALWAYSON._serialized_end = 700
+    _CFGBMSPOWEROFFWRITEACK._serialized_start = 702
+    _CFGBMSPOWEROFFWRITEACK._serialized_end = 822
+    _CFGBMSPUSHWRITE._serialized_start = 825
+    _CFGBMSPUSHWRITE._serialized_end = 1054
+    _CFGBMSPUSHWRITEACK._serialized_start = 1056
+    _CFGBMSPUSHWRITEACK._serialized_end = 1182
+    _SETTIMETASKWRITE._serialized_start = 1185
+    _SETTIMETASKWRITE._serialized_end = 1521
+    _SETTIMETASKWRITEACK._serialized_start = 1523
+    _SETTIMETASKWRITEACK._serialized_end = 1638
+    _GETALLTIMETASKREADCK._serialized_start = 1640
+    _GETALLTIMETASKREADCK._serialized_end = 1700
+    _CFGENERGYBACKUP._serialized_start = 1703
+    _CFGENERGYBACKUP._serialized_end = 1838
+    _CFGACHVALWAYSON._serialized_start = 1841
+    _CFGACHVALWAYSON._serialized_end = 1970
+    _CFGACLVALWAYSON._serialized_start = 1973
+    _CFGACLVALWAYSON._serialized_end = 2102
+    _CFGTOUSTRATEGY._serialized_start = 2104
+    _CFGTOUSTRATEGY._serialized_end = 2210
+    _CFGRJ45COMMCSERVICE._serialized_start = 2213
+    _CFGRJ45COMMCSERVICE._serialized_end = 2470
+    _CFGSTORMPATTERN._serialized_start = 2473
+    _CFGSTORMPATTERN._serialized_end = 2680
+    _CFGGENERATORMPPTHYBRIDMODE._serialized_start = 2683
+    _CFGGENERATORMPPTHYBRIDMODE._serialized_end = 2873
+    _CFGGENERATORCAREMODE._serialized_start = 2876
+    _CFGGENERATORCAREMODE._serialized_end = 3046
+    _CFGENERGYSTRATEGYOPERATEMODE._serialized_start = 3049
+    _CFGENERGYSTRATEGYOPERATEMODE._serialized_end = 3275
+    _INSTALLMENTPAYMENTSERVEBELONE._serialized_start = 3278
+    _INSTALLMENTPAYMENTSERVEBELONE._serialized_end = 3597
+    _INSTALLMENTPAYMENTSERVE._serialized_start = 3600
+    _INSTALLMENTPAYMENTSERVE._serialized_end = 3915
+    _RESVINFO._serialized_start = 3917
+    _RESVINFO._serialized_end = 3946
+    _RESETMIDDLEMENDELIVERYSETTING._serialized_start = 3948
+    _RESETMIDDLEMENDELIVERYSETTING._serialized_end = 4047
+    _PROPERTYUPLOADPERIOD._serialized_start = 4050
+    _PROPERTYUPLOADPERIOD._serialized_end = 4460
+    _PVDCCHGSETTING._serialized_start = 4463
+    _PVDCCHGSETTING._serialized_end = 4661
+    _PVDCCHGSETTINGLIST._serialized_start = 4663
+    _PVDCCHGSETTINGLIST._serialized_end = 4719
+    _PVCHGMAXITEM._serialized_start = 4722
+    _PVCHGMAXITEM._serialized_end = 4884
+    _PVCHGMAXLIST._serialized_start = 4886
+    _PVCHGMAXLIST._serialized_end = 4940
+    _TIMETASKITEMV2._serialized_start = 4943
+    _TIMETASKITEMV2._serialized_end = 5345
+    _TIMETASKITEMV2LIST._serialized_start = 5347
+    _TIMETASKITEMV2LIST._serialized_end = 5403
+    _STATISTICSRECORDITEM._serialized_start = 5406
+    _STATISTICSRECORDITEM._serialized_end = 5558
+    _DISPLAYSTATISTICSRECORDLIST._serialized_start = 5560
+    _DISPLAYSTATISTICSRECORDLIST._serialized_end = 5631
+    _RUNTIMESTATISTICSRECORDLIST._serialized_start = 5633
+    _RUNTIMESTATISTICSRECORDLIST._serialized_end = 5704
+    _ERRCODERECORDITEM._serialized_start = 5706
+    _ERRCODERECORDITEM._serialized_end = 5813
+    _ERRCODERECORDLIST._serialized_start = 5815
+    _ERRCODERECORDLIST._serialized_end = 5873
+    _WIRELESSCOORDINATELIST._serialized_start = 5876
+    _WIRELESSCOORDINATELIST._serialized_end = 6140
+    _CONFIGWRITE._serialized_start = 6143
+    _CONFIGWRITE._serialized_end = 12726
+    _CONFIGWRITEACK._serialized_start = 12729
+    _CONFIGWRITEACK._serialized_end = 19422
+    _CONFIGREAD._serialized_start = 19424
+    _CONFIGREAD._serialized_end = 19455
+    _CONFIGREADACK._serialized_start = 19458
+    _CONFIGREADACK._serialized_end = 19734
+    _DISPLAYPROPERTYUPLOAD._serialized_start = 19738
+    _DISPLAYPROPERTYUPLOAD._serialized_end = 38467
+    _RUNTIMEPROPERTYUPLOAD._serialized_start = 38470
+    _RUNTIMEPROPERTYUPLOAD._serialized_end = 44239
+    _DEVREQUEST._serialized_start = 44242
+    _DEVREQUEST._serialized_end = 44507
+    _DEVREQUESTACK._serialized_start = 44510
+    _DEVREQUESTACK._serialized_end = 44692
+# @@protoc_insertion_point(module_scope)
diff --git a/custom_components/ef_ble/manifest.json b/custom_components/ef_ble/manifest.json
index c68af445..bc1f4422 100644
--- a/custom_components/ef_ble/manifest.json
+++ b/custom_components/ef_ble/manifest.json
@@ -2,19 +2,28 @@
     "domain": "ef_ble",
     "name": "EcoFlow BLE (Unofficial)",
 
-    "bluetooth": [{
-        "local_name": "EF-HD3*",
-        "service_uuid": "00000002-0000-1000-8000-00805f9b34fb",
-        "manufacturer_id": 46517,
-        "manufacturer_data_start": [19, 72, 68, 51, 49, 90, 65, 83, 52, 88, 71, 52, 80],
-        "connectable": true
-    },{
-        "local_name": "EF-YJ*",
-        "service_uuid": "00000002-0000-1000-8000-00805f9b34fb",
-        "manufacturer_id": 46517,
-        "manufacturer_data_start": [19, 89, 55, 49, 49, 90, 65, 66, 53, 83, 71, 50, 82],
-        "connectable": true
-    }],
+    "bluetooth": [
+        {
+            "local_name": "EF-HD3*",
+            "service_uuid": "00000002-0000-1000-8000-00805f9b34fb",
+            "manufacturer_id": 46517,
+            "manufacturer_data_start": [19, 72, 68, 51, 49, 90, 65, 83, 52, 88, 71, 52, 80],
+            "connectable": true
+        },
+        {
+            "local_name": "EF-YJ*",
+            "service_uuid": "00000002-0000-1000-8000-00805f9b34fb",
+            "manufacturer_id": 46517,
+            "manufacturer_data_start": [19, 89, 55, 49, 49, 90, 65, 66, 53, 83, 71, 50, 82],
+            "connectable": true
+        },
+        {
+            "local_name": "EF-R3*",
+            "manufacturer_id": 46517,
+            "manufacturer_data_start": [19, 82, 54],
+            "connectable": true
+        }
+    ],
 
     "codeowners": ["@rabits"],
     "config_flow": true,
diff --git a/custom_components/ef_ble/sensor.py b/custom_components/ef_ble/sensor.py
index 8cf8ed78..ffee566a 100644
--- a/custom_components/ef_ble/sensor.py
+++ b/custom_components/ef_ble/sensor.py
@@ -1,29 +1,201 @@
 """EcoFlow BLE sensor"""
 
-import random
 import logging
 
+from custom_components.ef_ble.eflib import DeviceBase
+
 from homeassistant.components.sensor import (
     SensorDeviceClass,
     SensorEntity,
+    SensorEntityDescription,
     SensorStateClass,
 )
-
-from homeassistant.core import HomeAssistant
-from homeassistant.helpers.entity import Entity
-from homeassistant.helpers.entity_platform import AddEntitiesCallback
-from homeassistant.helpers.entity import DeviceInfo
 from homeassistant.const import (
     PERCENTAGE,
-    UnitOfPower,
     UnitOfElectricCurrent,
+    UnitOfEnergy,
+    UnitOfPower,
 )
+from homeassistant.core import HomeAssistant
+from homeassistant.helpers.entity import DeviceInfo
+from homeassistant.helpers.entity_platform import AddEntitiesCallback
 
 from . import DeviceConfigEntry
 from .const import DOMAIN, MANUFACTURER
 
 _LOGGER = logging.getLogger(__name__)
 
+SENSOR_TYPES: dict[str, SensorEntityDescription] = {
+    "battery_level": SensorEntityDescription(
+        key="battery_level",
+        name="Battery",
+        native_unit_of_measurement=PERCENTAGE,
+        device_class=SensorDeviceClass.BATTERY,
+    ),
+    "grid_power": SensorEntityDescription(
+        key="grid_power",
+        name="Grid Power",
+        native_unit_of_measurement=UnitOfPower.WATT,
+        device_class=SensorDeviceClass.POWER,
+        suggested_display_precision=2,
+        icon="mdi:transmission-tower",
+    ),
+    "in_use_power": SensorEntityDescription(
+        key="in_use_power",
+        name="In Use Power",
+        native_unit_of_measurement=UnitOfPower.WATT,
+        device_class=SensorDeviceClass.POWER,
+        suggested_display_precision=2,
+        icon="mdi:home-lightning-bolt-outline",
+    ),
+    "input_power": SensorEntityDescription(
+        key="input_power",
+        name="Input Power",
+        native_unit_of_measurement=UnitOfPower.WATT,
+        device_class=SensorDeviceClass.POWER,
+        suggested_display_precision=0,
+        icon="mdi:home-lightning-bolt-outline",
+    ),
+    "input_energy": SensorEntityDescription(
+        key="input_energy",
+        name="Input Energy Total",
+        native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
+        device_class=SensorDeviceClass.ENERGY,
+        state_class=SensorStateClass.TOTAL_INCREASING,
+        suggested_display_precision=3,
+        suggested_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
+    ),
+    "output_power": SensorEntityDescription(
+        key="output_power",
+        name="Output Power",
+        native_unit_of_measurement=UnitOfPower.WATT,
+        device_class=SensorDeviceClass.POWER,
+        suggested_display_precision=0,
+        icon="mdi:home-lightning-bolt-outline",
+    ),
+    "output_energy": SensorEntityDescription(
+        key="output_energy",
+        name="Output Energy Total",
+        native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
+        device_class=SensorDeviceClass.ENERGY,
+        state_class=SensorStateClass.TOTAL_INCREASING,
+        suggested_display_precision=3,
+        suggested_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
+    ),
+    "lv_solar_power": SensorEntityDescription(
+        key="lv_solar_power",
+        name="LV Solar Power",
+        native_unit_of_measurement=UnitOfPower.WATT,
+        device_class=SensorDeviceClass.POWER,
+        suggested_display_precision=2,
+        icon="mdi:solar-panel",
+    ),
+    "hv_solar_power": SensorEntityDescription(
+        key="hv_solar_power",
+        name="HV Solar Power",
+        native_unit_of_measurement=UnitOfPower.WATT,
+        device_class=SensorDeviceClass.POWER,
+        suggested_display_precision=2,
+        icon="mdi:solar-panel-large",
+    ),
+    "ac_input_power": SensorEntityDescription(
+        key="ac_input_power",
+        name="AC Input Power",
+        native_unit_of_measurement=UnitOfPower.WATT,
+        device_class=SensorDeviceClass.POWER,
+        suggested_display_precision=2,
+    ),
+    "ac_output_power": SensorEntityDescription(
+        key="ac_output_power",
+        name="AC Output Power",
+        native_unit_of_measurement=UnitOfPower.WATT,
+        device_class=SensorDeviceClass.POWER,
+        suggested_display_precision=2,
+    ),
+    "ac_input_energy": SensorEntityDescription(
+        key="ac_input_energy",
+        name="AC Input Energy",
+        native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
+        device_class=SensorDeviceClass.ENERGY,
+        state_class=SensorStateClass.TOTAL_INCREASING,
+        suggested_display_precision=3,
+        suggested_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
+    ),
+    "ac_output_energy": SensorEntityDescription(
+        key="ac_output_energy",
+        name="AC Output Energy",
+        native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
+        device_class=SensorDeviceClass.ENERGY,
+        state_class=SensorStateClass.TOTAL_INCREASING,
+        suggested_display_precision=3,
+        suggested_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
+    ),
+    "dc_input_power": SensorEntityDescription(
+        key="dc_input_power",
+        name="DC Input Power",
+        native_unit_of_measurement=UnitOfPower.WATT,
+        device_class=SensorDeviceClass.POWER,
+        suggested_display_precision=2,
+    ),
+    "dc_input_energy": SensorEntityDescription(
+        key="dc_input_energy",
+        name="DC Input Energy",
+        native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
+        device_class=SensorDeviceClass.ENERGY,
+        state_class=SensorStateClass.TOTAL_INCREASING,
+        suggested_display_precision=3,
+        suggested_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
+    ),
+    "dc12v_output_power": SensorEntityDescription(
+        key="dc12v_output_power",
+        name="DC 12V Output Power",
+        native_unit_of_measurement=UnitOfPower.WATT,
+        device_class=SensorDeviceClass.POWER,
+        suggested_display_precision=2,
+    ),
+    "dc12v_output_energy": SensorEntityDescription(
+        key="dc12v_output_energy",
+        name="DC 12V Output Energy",
+        native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
+        device_class=SensorDeviceClass.ENERGY,
+        state_class=SensorStateClass.TOTAL_INCREASING,
+        suggested_display_precision=3,
+        suggested_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
+    ),
+    "usbc_output_power": SensorEntityDescription(
+        key="usbc_output_power",
+        name="USC C Output Power",
+        native_unit_of_measurement=UnitOfPower.WATT,
+        device_class=SensorDeviceClass.POWER,
+        suggested_display_precision=2,
+    ),
+    "usbc_output_energy": SensorEntityDescription(
+        key="usbc_output_energy",
+        name="USB C Output Energy",
+        native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
+        device_class=SensorDeviceClass.ENERGY,
+        state_class=SensorStateClass.TOTAL_INCREASING,
+        suggested_display_precision=3,
+        suggested_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
+    ),
+    "usba_output_power": SensorEntityDescription(
+        key="usba_output_power",
+        name="USC A Output Power",
+        native_unit_of_measurement=UnitOfPower.WATT,
+        device_class=SensorDeviceClass.POWER,
+        suggested_display_precision=2,
+    ),
+    "usba_output_energy": SensorEntityDescription(
+        key="usba_output_energy",
+        name="USB A Output Energy",
+        native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
+        device_class=SensorDeviceClass.ENERGY,
+        state_class=SensorStateClass.TOTAL_INCREASING,
+        suggested_display_precision=3,
+        suggested_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
+    ),
+}
+
 
 async def async_setup_entry(
     hass: HomeAssistant,
@@ -33,11 +205,11 @@ async def async_setup_entry(
     """Add sensors for passed config_entry in HA."""
     device = config_entry.runtime_data
 
-    new_sensors = []
-
-    # Common sensors
-    if hasattr(device, "battery_level"):
-        new_sensors.append(BatterySensor(device))
+    new_sensors = [
+        EcoflowSensor(device, sensor)
+        for sensor in SENSOR_TYPES
+        if hasattr(device, sensor)
+    ]
 
     # SHP2 sensors
     if hasattr(device, "circuit_power"):
@@ -46,40 +218,32 @@ async def async_setup_entry(
     if hasattr(device, "circuit_current"):
         for i in range(len(device.circuit_current)):
             new_sensors.append(CircuitCurrentSensor(device, i))
-    if hasattr(device, "grid_power"):
-        new_sensors.append(GridPowerSensor(device))
-    if hasattr(device, "in_use_power"):
-        new_sensors.append(InUsePowerSensor(device))
     if hasattr(device, "channel_power"):
         for i in range(len(device.channel_power)):
             new_sensors.append(ChannelPowerSensor(device, i))
 
-    # DPU sensors
-    if hasattr(device, "hv_solar_power"):
-        new_sensors.append(HVSolarPowerSensor(device))
-    if hasattr(device, "lv_solar_power"):
-        new_sensors.append(LVSolarPowerSensor(device))
-    if hasattr(device, "input_power"):
-        new_sensors.append(InputPowerSensor(device))
-    if hasattr(device, "output_power"):
-        new_sensors.append(OutputPowerSensor(device))
-
     if new_sensors:
         async_add_entities(new_sensors)
 
 
-class SensorBase(SensorEntity):
+class EcoflowSensor(SensorEntity):
     """Base representation of a sensor."""
 
     _attr_has_entity_name = True
-    _attr_state_class = SensorStateClass.MEASUREMENT
 
-    # Name of the property to use to get a native value
-    ef_dev_property = "UNDEFINED"
-
-    def __init__(self, device):
+    def __init__(self, device: DeviceBase, sensor: str):
         """Initialize the sensor."""
         self._device = device
+        self._sensor = sensor
+        self._attr_unique_id = f"{device.name}_{sensor}"
+
+        if sensor in SENSOR_TYPES:
+            self.entity_description = SENSOR_TYPES[sensor]
+
+            if self.entity_description.state_class is None:
+                self._attr_state_class = SensorStateClass.MEASUREMENT
+        else:
+            self._attr_state_class = SensorStateClass.MEASUREMENT
 
     @property
     def device_info(self):
@@ -100,45 +264,18 @@ def available(self) -> bool:
     @property
     def native_value(self) -> int | float | bool:
         """Return the value of the sensor."""
-        return getattr(self._device, self.ef_dev_property, None)
+        return getattr(self._device, self._sensor, None)
 
     async def async_added_to_hass(self):
         """Run when this Entity has been added to HA."""
-        if self.ef_dev_property != "UNDEFINED":
-            self._device.register_callback(
-                self.async_write_ha_state, self.ef_dev_property
-            )
-        else:
-            self._device.register_callback(self.async_write_ha_state, None)
+        self._device.register_callback(self.async_write_ha_state, self._sensor)
 
     async def async_will_remove_from_hass(self):
         """Entity being removed from hass."""
-        if self.ef_dev_property != "UNDEFINED":
-            self._device.remove_callback(
-                self.async_write_ha_state, self.ef_dev_property
-            )
-        else:
-            self._device.remove_callback(self.async_write_ha_state, None)
-
-
-class BatterySensor(SensorBase):
-    """Shows total battery level of a device."""
-
-    device_class = SensorDeviceClass.BATTERY
-    _attr_native_unit_of_measurement = PERCENTAGE
-
-    # Name of the property to use to get a native value
-    ef_dev_property = "battery_level"
-
-    def __init__(self, device):
-        """Initialize the sensor."""
-        super().__init__(device)
-
-        self._attr_unique_id = f"{self._device.name}_battery"
-        self._attr_name = "Battery"
+        self._device.remove_callback(self.async_write_ha_state, self._sensor)
 
 
-class CircuitPowerSensor(SensorBase):
+class CircuitPowerSensor(EcoflowSensor):
     """Represents circuit consumed wattage."""
 
     device_class = SensorDeviceClass.POWER
@@ -147,10 +284,10 @@ class CircuitPowerSensor(SensorBase):
 
     def __init__(self, device, index):
         """Initialize the sensor."""
-        super().__init__(device)
+        super().__init__(device, f"circuit_power_{index}")
 
-        self._attr_unique_id = f"{self._device.name}_circuit_power_{index+1}"
-        self._attr_name = f"Circuit Power {index+1:02d}"
+        self._attr_unique_id = f"{self._device.name}_circuit_power_{index + 1}"
+        self._attr_name = f"Circuit Power {index + 1:02d}"
         self._index = index
 
     @property
@@ -159,7 +296,7 @@ def native_value(self) -> float:
         return self._device.circuit_power[self._index]
 
 
-class CircuitCurrentSensor(SensorBase):
+class CircuitCurrentSensor(EcoflowSensor):
     """Represents circuit consumed amperage."""
 
     device_class = SensorDeviceClass.CURRENT
@@ -169,10 +306,10 @@ class CircuitCurrentSensor(SensorBase):
 
     def __init__(self, device, index):
         """Initialize the sensor."""
-        super().__init__(device)
+        super().__init__(device, f"circuit_current_{index}")
 
-        self._attr_unique_id = f"{self._device.name}_circuit_current_{index+1}"
-        self._attr_name = f"Circuit Current {index+1:02d}"
+        self._attr_unique_id = f"{self._device.name}_circuit_current_{index + 1}"
+        self._attr_name = f"Circuit Current {index + 1:02d}"
         self._index = index
 
     @property
@@ -181,49 +318,7 @@ def native_value(self) -> float:
         return self._device.circuit_current[self._index]
 
 
-class GridPowerSensor(SensorBase):
-    """Represents grid intake wattage."""
-
-    device_class = SensorDeviceClass.POWER
-    _attr_native_unit_of_measurement = UnitOfPower.WATT
-    _attr_suggested_display_precision = 2
-    _attr_icon = "mdi:transmission-tower"
-
-    def __init__(self, device):
-        """Initialize the sensor."""
-        super().__init__(device)
-
-        self._attr_unique_id = f"{self._device.name}_grid_power"
-        self._attr_name = "Grid Power"
-
-    @property
-    def native_value(self) -> float:
-        """Return the value of the sensor."""
-        return self._device.grid_power
-
-
-class InUsePowerSensor(SensorBase):
-    """Represents in use wattage."""
-
-    device_class = SensorDeviceClass.POWER
-    _attr_native_unit_of_measurement = UnitOfPower.WATT
-    _attr_suggested_display_precision = 2
-    _attr_icon = "mdi:home-lightning-bolt-outline"
-
-    def __init__(self, device):
-        """Initialize the sensor."""
-        super().__init__(device)
-
-        self._attr_unique_id = f"{self._device.name}_in_use_power"
-        self._attr_name = "In Use Power"
-
-    @property
-    def native_value(self) -> float:
-        """Return the value of the sensor."""
-        return self._device.in_use_power
-
-
-class ChannelPowerSensor(SensorBase):
+class ChannelPowerSensor(EcoflowSensor):
     """Represents backup channel wattage."""
 
     device_class = SensorDeviceClass.POWER
@@ -232,97 +327,13 @@ class ChannelPowerSensor(SensorBase):
 
     def __init__(self, device, index):
         """Initialize the sensor."""
-        super().__init__(device)
+        super().__init__(device, f"channel_power_{index}")
 
-        self._attr_unique_id = f"{self._device.name}_channel_power_{index+1}"
-        self._attr_name = f"Channel Power {index+1}"
+        self._attr_unique_id = f"{self._device.name}_channel_power_{index + 1}"
+        self._attr_name = f"Channel Power {index + 1}"
         self._index = index
 
     @property
     def native_value(self) -> float:
         """Return the value of the sensor."""
         return self._device.channel_power[self._index]
-
-
-class HVSolarPowerSensor(SensorBase):
-    """Represents high voltage intake wattage."""
-
-    device_class = SensorDeviceClass.POWER
-    _attr_native_unit_of_measurement = UnitOfPower.WATT
-    _attr_suggested_display_precision = 2
-    _attr_icon = "mdi:solar-panel-large"
-
-    def __init__(self, device):
-        """Initialize the sensor."""
-        super().__init__(device)
-
-        self._attr_unique_id = f"{self._device.name}_hv_solar_power"
-        self._attr_name = "HV Solar Power"
-
-    @property
-    def native_value(self) -> float:
-        """Return the value of the sensor."""
-        return self._device.hv_solar_power
-
-
-class LVSolarPowerSensor(SensorBase):
-    """Represents low voltage intake wattage."""
-
-    device_class = SensorDeviceClass.POWER
-    _attr_native_unit_of_measurement = UnitOfPower.WATT
-    _attr_suggested_display_precision = 2
-    _attr_icon = "mdi:solar-panel"
-
-    def __init__(self, device):
-        """Initialize the sensor."""
-        super().__init__(device)
-
-        self._attr_unique_id = f"{self._device.name}_lv_solar_power"
-        self._attr_name = "LV Solar Power"
-
-    @property
-    def native_value(self) -> float:
-        """Return the value of the sensor."""
-        return self._device.lv_solar_power
-
-
-class InputPowerSensor(SensorBase):
-    """Represents total intake wattage."""
-
-    device_class = SensorDeviceClass.POWER
-    _attr_native_unit_of_measurement = UnitOfPower.WATT
-    _attr_suggested_display_precision = 0
-    _attr_icon = "mdi:home-lightning-bolt-outline"
-
-    def __init__(self, device):
-        """Initialize the sensor."""
-        super().__init__(device)
-
-        self._attr_unique_id = f"{self._device.name}_input_power"
-        self._attr_name = "Input Power"
-
-    @property
-    def native_value(self) -> float:
-        """Return the value of the sensor."""
-        return self._device.input_power
-
-
-class OutputPowerSensor(SensorBase):
-    """Represents total output wattage."""
-
-    device_class = SensorDeviceClass.POWER
-    _attr_native_unit_of_measurement = UnitOfPower.WATT
-    _attr_suggested_display_precision = 0
-    _attr_icon = "mdi:home-lightning-bolt-outline"
-
-    def __init__(self, device):
-        """Initialize the sensor."""
-        super().__init__(device)
-
-        self._attr_unique_id = f"{self._device.name}_output_power"
-        self._attr_name = "Output Power"
-
-    @property
-    def native_value(self) -> float:
-        """Return the value of the sensor."""
-        return self._device.output_power


Reviews:
user: login: GnoX
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-01T09:12:56Z
user: login: rabits
state: COMMENTED
author_association: OWNER
submitted_at: 2025-03-02T00:14:26Z
user: login: rabits
body: Unfortunately throwning the next exception after reloading:
```
2025-03-01 19:42:08.893 ERROR (MainThread) [homeassistant.components.sensor] Error while setting up ef_ble platform for sensor
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/entity_platform.py", line 366, in _async_setup_platform
    await asyncio.shield(awaitable)
  File "/config/custom_components/ef_ble/sensor.py", line 216, in async_setup_entry
    new_sensors.append(CircuitPowerSensor(device, i))
                       ~~~~~~~~~~~~~~~~~~^^^^^^^^^^^
  File "/config/custom_components/ef_ble/sensor.py", line 281, in __init__
    super().__init__(device, f"circuit_power_{index}")
    ~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/ef_ble/sensor.py", line 238, in __init__
    self.entity_description = SENSOR_TYPES[sensor]
                              ~~~~~~~~~~~~^^^^^^^^
KeyError: 'circuit_power_0'
2025-03-01 19:42:08.898 INFO (MainThread) [homeassistant.components.binary_sensor] Setting up ef_ble.binary_sensor
2025-03-01 19:42:08.899 ERROR (MainThread) [homeassistant.components.binary_sensor] Error while setting up ef_ble platform for binary_sensor
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/entity_platform.py", line 366, in _async_setup_platform
    await asyncio.shield(awaitable)
  File "/config/custom_components/ef_ble/binary_sensor.py", line 26, in async_setup_entry
    new_sensors.append(ErrorDetectedSensor(device, "error_happened"))
                       ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/ef_ble/binary_sensor.py", line 40, in __init__
    super().__init__(device, sensor)
    ~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^
  File "/config/custom_components/ef_ble/sensor.py", line 238, in __init__
    self.entity_description = SENSOR_TYPES[sensor]
                              ~~~~~~~~~~~~^^^^^^^^
KeyError: 'error_happened'
```
Will check closer what's up with it...

Was able to fix that by changing the next lines in SENSORS:
```diff
diff --git a/custom_components/ef_ble/sensor.py b/custom_components/ef_ble/sensor.py
index 64100ad..872c13b 100644
--- a/custom_components/ef_ble/sensor.py
+++ b/custom_components/ef_ble/sensor.py
@@ -32,6 +32,27 @@ SENSOR_TYPES: dict[str, SensorEntityDescription] = {
         native_unit_of_measurement=PERCENTAGE,
         device_class=SensorDeviceClass.BATTERY,
     ),
+    "channel_power": SensorEntityDescription(
+        key="channel_power",
+        name="Channel Power",
+        native_unit_of_measurement=UnitOfPower.WATT,
+        device_class=SensorDeviceClass.POWER,
+        suggested_display_precision=2,
+    ),
+    "circuit_power": SensorEntityDescription(
+        key="circuit_power",
+        name="Circuit Power",
+        native_unit_of_measurement=UnitOfPower.WATT,
+        device_class=SensorDeviceClass.POWER,
+        suggested_display_precision=2,
+    ),
+    "circuit_current": SensorEntityDescription(
+        key="circuit_current",
+        name="Circuit Current",
+        native_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
+        device_class=SensorDeviceClass.CURRENT,
+        suggested_display_precision=2,
+    ),
     "grid_power": SensorEntityDescription(
         key="grid_power",
         name="Grid Power",
@@ -278,7 +299,7 @@ class CircuitPowerSensor(EcoflowSensor):

     def __init__(self, device, index):
         """Initialize the sensor."""
-        super().__init__(device, f"circuit_power_{index}")
+        super().__init__(device, "circuit_power")

         self._attr_unique_id = f"{self._device.name}_circuit_power_{index+1}"
         self._attr_name = f"Circuit Power {index + 1:02d}"
@@ -300,7 +321,7 @@ class CircuitCurrentSensor(EcoflowSensor):

     def __init__(self, device, index):
         """Initialize the sensor."""
-        super().__init__(device, f"circuit_current_{index}")
+        super().__init__(device, "circuit_current")

         self._attr_unique_id = f"{self._device.name}_circuit_current_{index+1}"
         self._attr_name = f"Circuit Current {index+1:02d}"
@@ -322,7 +343,7 @@ class ChannelPowerSensor(EcoflowSensor):

     def __init__(self, device, index):
         """Initialize the sensor."""
-        super().__init__(device, f"channel_power_{index}")
+        super().__init__(device, "channel_power")

         self._attr_unique_id = f"{self._device.name}_channel_power_{index+1}"
         self._attr_name = f"Channel Power {index+1}"
```

But that added 3 dummy unavailable sensors in my device entities...
state: CHANGES_REQUESTED
author_association: OWNER
submitted_at: 2025-03-02T00:48:02Z
user: login: GnoX
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-02T01:03:35Z
user: login: GnoX
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-02T01:07:04Z
user: login: GnoX
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-02T01:10:38Z
user: login: rabits
state: COMMENTED
author_association: OWNER
submitted_at: 2025-03-02T01:10:52Z
user: login: rabits
state: COMMENTED
author_association: OWNER
submitted_at: 2025-03-02T01:14:47Z
user: login: rabits
state: COMMENTED
author_association: OWNER
submitted_at: 2025-03-02T01:15:23Z
user: login: GnoX
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-02T01:24:25Z
user: login: GnoX
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-02T01:30:54Z
user: login: GnoX
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-02T01:40:14Z
user: login: GnoX
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-02T02:00:03Z
user: login: rabits
state: COMMENTED
author_association: OWNER
submitted_at: 2025-03-02T04:22:28Z
user: login: rabits
state: COMMENTED
author_association: OWNER
submitted_at: 2025-03-02T04:22:59Z
user: login: rabits
state: COMMENTED
author_association: OWNER
submitted_at: 2025-03-02T04:23:34Z
user: login: rabits
body: Looks good! Thank you) Will be great if someone with River 3 / Plus will be able to confirm, because I have just SHP2/DPU, but since you've tested on River 3 - I think it should work well.

For me it created another battery entity on restart, but when I deleted the device and re-added it picked up the history data.
state: APPROVED
author_association: OWNER
submitted_at: 2025-03-02T04:34:21Z
user: login: rabits
body: Oh forgot it's fixed just for me... But overall it looks good! Thank you) Will be great if someone with River 3 / Plus will be able to confirm, because I have just SHP2/DPU, but since you've tested on River 3 - I think it should work well.

For me it created another battery entity on restart, but when I deleted the device and re-added it picked up the history data.

state: CHANGES_REQUESTED
author_association: OWNER
submitted_at: 2025-03-02T04:36:59Z
user: login: GnoX
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-02T05:39:35Z
user: login: rabits
state: COMMENTED
author_association: OWNER
submitted_at: 2025-03-02T05:41:14Z
user: login: rabits
body: LGTM
state: APPROVED
author_association: OWNER
submitted_at: 2025-03-02T05:41:32Z

Review comments:
diff_hunk: @@ -100,45 +258,18 @@ def available(self) -> bool:
     @property
     def native_value(self) -> int | float | bool:
         """Return the value of the sensor."""
-        return getattr(self._device, self.ef_dev_property, None)
+        return getattr(self._device, self._sensor, None)
 
     async def async_added_to_hass(self):
         """Run when this Entity has been added to HA."""
-        if self.ef_dev_property != "UNDEFINED":
-            self._device.register_callback(
-                self.async_write_ha_state, self.ef_dev_property
-            )
-        else:
-            self._device.register_callback(self.async_write_ha_state, None)
+        self._device.register_callback(self.async_write_ha_state, self._sensor)
path: custom_components/ef_ble/sensor.py
user: login: GnoX
body: In https://github.com/rabits/ha-ef-ble/issues/5#issuecomment-2691478193 I noted that we can keep updating all sensors on each packet, but in the end, I decided to make all sensors only update when the value changes. 
created_at: 2025-03-01T09:12:56Z
author_association: COLLABORATOR
diff_hunk: @@ -100,45 +258,18 @@ def available(self) -> bool:
     @property
     def native_value(self) -> int | float | bool:
         """Return the value of the sensor."""
-        return getattr(self._device, self.ef_dev_property, None)
+        return getattr(self._device, self._sensor, None)
 
     async def async_added_to_hass(self):
         """Run when this Entity has been added to HA."""
-        if self.ef_dev_property != "UNDEFINED":
-            self._device.register_callback(
-                self.async_write_ha_state, self.ef_dev_property
-            )
-        else:
-            self._device.register_callback(self.async_write_ha_state, None)
+        self._device.register_callback(self.async_write_ha_state, self._sensor)
path: custom_components/ef_ble/sensor.py
user: login: rabits
body: Let me try the same logic without partial update - maybe we don't need such complication since MEASUREMENT is now here.
created_at: 2025-03-02T00:14:26Z
author_association: OWNER
diff_hunk: @@ -0,0 +1 @@
+*.pyc
path: .gitignore
user: login: rabits
body: Do you think we really need it here? I think it's worth to be added if the repo is used directly in HA or running logic to produce compiled files, but for now I'd say it's more related to the development environment of the developer rather then the project repo itself.
created_at: 2025-03-02T00:16:29Z
author_association: OWNER
diff_hunk: @@ -10,6 +10,7 @@ number of EcoFlow devices through bluetooth and monitor their status / control p
 Recognized devices:
 * Smart Home Panel 2 (EF-HD3####, FW Version: 4.0.0.122, WiFi Version: 2.0.1.20)
 * Delta Pro Ultra (EF-YJ####, FW Version: 5.0.0.25, WiFi Version: 2.0.2.4)
+* River 3 (EF-R3####, FW Version: 1.0.0.0)
path: README.md
user: login: rabits
body: I heard it's supporting River 3 Plus/Max as well?
created_at: 2025-03-02T00:20:23Z
author_association: OWNER
diff_hunk: @@ -0,0 +1,119 @@
+from collections.abc import Sequence
+import logging
+from typing import Any
+
+from bleak.backends.device import BLEDevice
+from bleak.backends.scanner import AdvertisementData
+from google.protobuf.message import Message
+
+from ..commands import TimeCommands
+from ..device_properties import Field, ProtobufField, ProtobufListField, UpdatableProps
+from ..devicebase import DeviceBase
+from ..packet import Packet
+from ..pb import pr705_pb2
+
+_LOGGER = logging.getLogger(__name__)
+
+class _StatField[T](ProtobufListField[T]):
+    _stat_enum = pr705_pb2.STATISTICS_OBJECT # type: ignore[attr-defined]
+
+    @property
+    def list_name(self):
+        return "display_statistics_sum"
+
+    def get_list(self, message: Any) -> Sequence[Message]:
+        return message.list_info
+
+    def should_update(self, message: Any) -> bool:
+        return self._stat_enum.Name(message.statistics_object) == self.pb_field_name
+
+    def get_item_value(self, message: Any) -> T | None:
+        return message.statistics_content
+
+
+def _out_power(x):
+    return -round(x, 2) if x != 0 else 0
+
+class Device(DeviceBase, UpdatableProps):
+    """River 3"""
+    
path: custom_components/ef_ble/eflib/devices/river3.py
user: login: rabits
body: Sorry, apparently I screwed the code validation in `.github/workflows/validate-code-style.yaml` - could you please change `black .` to `black --check .` there? Also it's worth to execute black here to fix a number of small things.
created_at: 2025-03-02T00:39:13Z
author_association: OWNER
diff_hunk: @@ -0,0 +1 @@
+*.pyc
path: .gitignore
user: login: GnoX
body: I can replace it for a [more general gitignore](https://www.toptal.com/developers/gitignore/api/visualstudiocode,homeassistant,python). Or do you mean that we don't need it at all?
created_at: 2025-03-02T01:03:35Z
author_association: COLLABORATOR
diff_hunk: @@ -10,6 +10,7 @@ number of EcoFlow devices through bluetooth and monitor their status / control p
 Recognized devices:
 * Smart Home Panel 2 (EF-HD3####, FW Version: 4.0.0.122, WiFi Version: 2.0.1.20)
 * Delta Pro Ultra (EF-YJ####, FW Version: 5.0.0.25, WiFi Version: 2.0.2.4)
+* River 3 (EF-R3####, FW Version: 1.0.0.0)
path: README.md
user: login: GnoX
body: Yeah, they both use same protocol buffers but the Plus version has a little bit more attributes. 
created_at: 2025-03-02T01:07:04Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,119 @@
+from collections.abc import Sequence
+import logging
+from typing import Any
+
+from bleak.backends.device import BLEDevice
+from bleak.backends.scanner import AdvertisementData
+from google.protobuf.message import Message
+
+from ..commands import TimeCommands
+from ..device_properties import Field, ProtobufField, ProtobufListField, UpdatableProps
+from ..devicebase import DeviceBase
+from ..packet import Packet
+from ..pb import pr705_pb2
+
+_LOGGER = logging.getLogger(__name__)
+
+class _StatField[T](ProtobufListField[T]):
+    _stat_enum = pr705_pb2.STATISTICS_OBJECT # type: ignore[attr-defined]
+
+    @property
+    def list_name(self):
+        return "display_statistics_sum"
+
+    def get_list(self, message: Any) -> Sequence[Message]:
+        return message.list_info
+
+    def should_update(self, message: Any) -> bool:
+        return self._stat_enum.Name(message.statistics_object) == self.pb_field_name
+
+    def get_item_value(self, message: Any) -> T | None:
+        return message.statistics_content
+
+
+def _out_power(x):
+    return -round(x, 2) if x != 0 else 0
+
+class Device(DeviceBase, UpdatableProps):
+    """River 3"""
+    
path: custom_components/ef_ble/eflib/devices/river3.py
user: login: GnoX
body: Will do. I normally use pre-commit and ruff in my projects so I am not used to running them manually :)
created_at: 2025-03-02T01:10:38Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1 @@
+*.pyc
path: .gitignore
user: login: rabits
body: Yeah I believe general is for sure an overkill - maybe it works for homeassistant repo, but not for this integration. I'm saying that no automation in this project actually creates those pyc files, so the fact that they are here depends on the development environment you're in. So I prefer to keep such dev env gitignores on the dev env itself rather then in each project we working with. For example if you use vscode or eclipse or idea - it doesn't mean that the project should contain gitignore file where those IDE project configs need to be ignored - I usually use more global gitignore for such dev-env specific ignores.
created_at: 2025-03-02T01:10:52Z
author_association: OWNER
diff_hunk: @@ -10,6 +10,7 @@ number of EcoFlow devices through bluetooth and monitor their status / control p
 Recognized devices:
 * Smart Home Panel 2 (EF-HD3####, FW Version: 4.0.0.122, WiFi Version: 2.0.1.20)
 * Delta Pro Ultra (EF-YJ####, FW Version: 5.0.0.25, WiFi Version: 2.0.2.4)
+* River 3 (EF-R3####, FW Version: 1.0.0.0)
path: README.md
user: login: rabits
body: Yep, so probably we need to mention those Rivers here as well - so users know what to expect from this integration.
created_at: 2025-03-02T01:14:47Z
author_association: OWNER
diff_hunk: @@ -0,0 +1,119 @@
+from collections.abc import Sequence
+import logging
+from typing import Any
+
+from bleak.backends.device import BLEDevice
+from bleak.backends.scanner import AdvertisementData
+from google.protobuf.message import Message
+
+from ..commands import TimeCommands
+from ..device_properties import Field, ProtobufField, ProtobufListField, UpdatableProps
+from ..devicebase import DeviceBase
+from ..packet import Packet
+from ..pb import pr705_pb2
+
+_LOGGER = logging.getLogger(__name__)
+
+class _StatField[T](ProtobufListField[T]):
+    _stat_enum = pr705_pb2.STATISTICS_OBJECT # type: ignore[attr-defined]
+
+    @property
+    def list_name(self):
+        return "display_statistics_sum"
+
+    def get_list(self, message: Any) -> Sequence[Message]:
+        return message.list_info
+
+    def should_update(self, message: Any) -> bool:
+        return self._stat_enum.Name(message.statistics_object) == self.pb_field_name
+
+    def get_item_value(self, message: Any) -> T | None:
+        return message.statistics_content
+
+
+def _out_power(x):
+    return -round(x, 2) if x != 0 else 0
+
+class Device(DeviceBase, UpdatableProps):
+    """River 3"""
+    
path: custom_components/ef_ble/eflib/devices/river3.py
user: login: rabits
body: Good practice)
created_at: 2025-03-02T01:15:23Z
author_association: OWNER
diff_hunk: @@ -0,0 +1 @@
+*.pyc
path: .gitignore
user: login: GnoX
body: Well, I think that it is still good to have a general gitignore especially for public repos as most of the contributors will not have these rules by default and it's then unnecessary for reviewers to check that no dev specific files were added to the repo.

I do respect your workflow though so I removed it entirely.
[32b1aa4](https://github.com/rabits/ha-ef-ble/pull/6/commits/32b1aa41d7bcc04346612be2a7574c87c1951be6)
created_at: 2025-03-02T01:24:25Z
author_association: COLLABORATOR
diff_hunk: @@ -10,6 +10,7 @@ number of EcoFlow devices through bluetooth and monitor their status / control p
 Recognized devices:
 * Smart Home Panel 2 (EF-HD3####, FW Version: 4.0.0.122, WiFi Version: 2.0.1.20)
 * Delta Pro Ultra (EF-YJ####, FW Version: 5.0.0.25, WiFi Version: 2.0.2.4)
+* River 3 (EF-R3####, FW Version: 1.0.0.0)
path: README.md
user: login: GnoX
body: I added Plus to the readme. I did not add max as it is a Plus bundled with extension battery.

[32b1aa4](https://github.com/rabits/ha-ef-ble/pull/6/commits/32b1aa41d7bcc04346612be2a7574c87c1951be6)
created_at: 2025-03-02T01:30:54Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,119 @@
+from collections.abc import Sequence
+import logging
+from typing import Any
+
+from bleak.backends.device import BLEDevice
+from bleak.backends.scanner import AdvertisementData
+from google.protobuf.message import Message
+
+from ..commands import TimeCommands
+from ..device_properties import Field, ProtobufField, ProtobufListField, UpdatableProps
+from ..devicebase import DeviceBase
+from ..packet import Packet
+from ..pb import pr705_pb2
+
+_LOGGER = logging.getLogger(__name__)
+
+class _StatField[T](ProtobufListField[T]):
+    _stat_enum = pr705_pb2.STATISTICS_OBJECT # type: ignore[attr-defined]
+
+    @property
+    def list_name(self):
+        return "display_statistics_sum"
+
+    def get_list(self, message: Any) -> Sequence[Message]:
+        return message.list_info
+
+    def should_update(self, message: Any) -> bool:
+        return self._stat_enum.Name(message.statistics_object) == self.pb_field_name
+
+    def get_item_value(self, message: Any) -> T | None:
+        return message.statistics_content
+
+
+def _out_power(x):
+    return -round(x, 2) if x != 0 else 0
+
+class Device(DeviceBase, UpdatableProps):
+    """River 3"""
+    
path: custom_components/ef_ble/eflib/devices/river3.py
user: login: GnoX
body: CI fixed and black was applied

[c077e6b](https://github.com/rabits/ha-ef-ble/pull/6/commits/c077e6bee42a923402b57e96ccae14240ce60bce)
[1a5893e](https://github.com/rabits/ha-ef-ble/pull/6/commits/1a5893e48556551d23eca912bcedf382787ea48c)
created_at: 2025-03-02T01:40:14Z
author_association: COLLABORATOR
diff_hunk: @@ -100,45 +258,18 @@ def available(self) -> bool:
     @property
     def native_value(self) -> int | float | bool:
         """Return the value of the sensor."""
-        return getattr(self._device, self.ef_dev_property, None)
+        return getattr(self._device, self._sensor, None)
 
     async def async_added_to_hass(self):
         """Run when this Entity has been added to HA."""
-        if self.ef_dev_property != "UNDEFINED":
-            self._device.register_callback(
-                self.async_write_ha_state, self.ef_dev_property
-            )
-        else:
-            self._device.register_callback(self.async_write_ha_state, None)
+        self._device.register_callback(self.async_write_ha_state, self._sensor)
path: custom_components/ef_ble/sensor.py
user: login: GnoX
body: I looked at how `async_write_ha_state` is implemented and it is doing a good amount of operations before it decides to abort it due to values being the same. I already udpated everything to use partial updates and it was quite easy change so would you mind if I left it in the present state?
created_at: 2025-03-02T02:00:02Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1 @@
+*.pyc
path: .gitignore
user: login: rabits
body: Thank you)
created_at: 2025-03-02T04:22:28Z
author_association: OWNER
diff_hunk: @@ -10,6 +10,7 @@ number of EcoFlow devices through bluetooth and monitor their status / control p
 Recognized devices:
 * Smart Home Panel 2 (EF-HD3####, FW Version: 4.0.0.122, WiFi Version: 2.0.1.20)
 * Delta Pro Ultra (EF-YJ####, FW Version: 5.0.0.25, WiFi Version: 2.0.2.4)
+* River 3 (EF-R3####, FW Version: 1.0.0.0)
path: README.md
user: login: rabits
body: Yep, looks great!)
created_at: 2025-03-02T04:22:59Z
author_association: OWNER
diff_hunk: @@ -0,0 +1,119 @@
+from collections.abc import Sequence
+import logging
+from typing import Any
+
+from bleak.backends.device import BLEDevice
+from bleak.backends.scanner import AdvertisementData
+from google.protobuf.message import Message
+
+from ..commands import TimeCommands
+from ..device_properties import Field, ProtobufField, ProtobufListField, UpdatableProps
+from ..devicebase import DeviceBase
+from ..packet import Packet
+from ..pb import pr705_pb2
+
+_LOGGER = logging.getLogger(__name__)
+
+class _StatField[T](ProtobufListField[T]):
+    _stat_enum = pr705_pb2.STATISTICS_OBJECT # type: ignore[attr-defined]
+
+    @property
+    def list_name(self):
+        return "display_statistics_sum"
+
+    def get_list(self, message: Any) -> Sequence[Message]:
+        return message.list_info
+
+    def should_update(self, message: Any) -> bool:
+        return self._stat_enum.Name(message.statistics_object) == self.pb_field_name
+
+    def get_item_value(self, message: Any) -> T | None:
+        return message.statistics_content
+
+
+def _out_power(x):
+    return -round(x, 2) if x != 0 else 0
+
+class Device(DeviceBase, UpdatableProps):
+    """River 3"""
+    
path: custom_components/ef_ble/eflib/devices/river3.py
user: login: rabits
body: Thank you very much - that makes our life easier)
created_at: 2025-03-02T04:23:34Z
author_association: OWNER
diff_hunk: @@ -100,45 +258,18 @@ def available(self) -> bool:
     @property
     def native_value(self) -> int | float | bool:
         """Return the value of the sensor."""
-        return getattr(self._device, self.ef_dev_property, None)
+        return getattr(self._device, self._sensor, None)
 
     async def async_added_to_hass(self):
         """Run when this Entity has been added to HA."""
-        if self.ef_dev_property != "UNDEFINED":
-            self._device.register_callback(
-                self.async_write_ha_state, self.ef_dev_property
-            )
-        else:
-            self._device.register_callback(self.async_write_ha_state, None)
+        self._device.register_callback(self.async_write_ha_state, self._sensor)
path: custom_components/ef_ble/sensor.py
user: login: rabits
body: Ok, let's keep it there then) Mixins are not my favorites (makes the logic quite  bit complicated), but since it's working - I'm good with that)
created_at: 2025-03-02T04:31:10Z
author_association: OWNER
diff_hunk: @@ -46,40 +218,30 @@ async def async_setup_entry(
     if hasattr(device, "circuit_current"):
         for i in range(len(device.circuit_current)):
             new_sensors.append(CircuitCurrentSensor(device, i))
-    if hasattr(device, "grid_power"):
-        new_sensors.append(GridPowerSensor(device))
-    if hasattr(device, "in_use_power"):
-        new_sensors.append(InUsePowerSensor(device))
     if hasattr(device, "channel_power"):
         for i in range(len(device.channel_power)):
             new_sensors.append(ChannelPowerSensor(device, i))
 
-    # DPU sensors
-    if hasattr(device, "hv_solar_power"):
-        new_sensors.append(HVSolarPowerSensor(device))
-    if hasattr(device, "lv_solar_power"):
-        new_sensors.append(LVSolarPowerSensor(device))
-    if hasattr(device, "input_power"):
-        new_sensors.append(InputPowerSensor(device))
-    if hasattr(device, "output_power"):
-        new_sensors.append(OutputPowerSensor(device))
-
     if new_sensors:
         async_add_entities(new_sensors)
 
 
-class SensorBase(SensorEntity):
+class EcoflowSensor(SensorEntity):
     """Base representation of a sensor."""
 
     _attr_has_entity_name = True
-    _attr_state_class = SensorStateClass.MEASUREMENT
 
-    # Name of the property to use to get a native value
-    ef_dev_property = "UNDEFINED"
-
-    def __init__(self, device):
+    def __init__(self, device: DeviceBase, sensor: str):
         """Initialize the sensor."""
         self._device = device
+        self._sensor = sensor
+        self._attr_unique_id = f"{device.name}_{sensor}"
+
+        if sensor in SENSOR_TYPES:
+            self.entity_description = SENSOR_TYPES[sensor]
+
+        if self.entity_description.state_class is None:
path: custom_components/ef_ble/sensor.py
user: login: rabits
body: Oh yeah, sorry, forgot it need to be fixed...
created_at: 2025-03-02T04:36:26Z
author_association: OWNER
diff_hunk: @@ -46,40 +218,30 @@ async def async_setup_entry(
     if hasattr(device, "circuit_current"):
         for i in range(len(device.circuit_current)):
             new_sensors.append(CircuitCurrentSensor(device, i))
-    if hasattr(device, "grid_power"):
-        new_sensors.append(GridPowerSensor(device))
-    if hasattr(device, "in_use_power"):
-        new_sensors.append(InUsePowerSensor(device))
     if hasattr(device, "channel_power"):
         for i in range(len(device.channel_power)):
             new_sensors.append(ChannelPowerSensor(device, i))
 
-    # DPU sensors
-    if hasattr(device, "hv_solar_power"):
-        new_sensors.append(HVSolarPowerSensor(device))
-    if hasattr(device, "lv_solar_power"):
-        new_sensors.append(LVSolarPowerSensor(device))
-    if hasattr(device, "input_power"):
-        new_sensors.append(InputPowerSensor(device))
-    if hasattr(device, "output_power"):
-        new_sensors.append(OutputPowerSensor(device))
-
     if new_sensors:
         async_add_entities(new_sensors)
 
 
-class SensorBase(SensorEntity):
+class EcoflowSensor(SensorEntity):
     """Base representation of a sensor."""
 
     _attr_has_entity_name = True
-    _attr_state_class = SensorStateClass.MEASUREMENT
 
-    # Name of the property to use to get a native value
-    ef_dev_property = "UNDEFINED"
-
-    def __init__(self, device):
+    def __init__(self, device: DeviceBase, sensor: str):
         """Initialize the sensor."""
         self._device = device
+        self._sensor = sensor
+        self._attr_unique_id = f"{device.name}_{sensor}"
+
+        if sensor in SENSOR_TYPES:
+            self.entity_description = SENSOR_TYPES[sensor]
+
+        if self.entity_description.state_class is None:
path: custom_components/ef_ble/sensor.py
user: login: GnoX
body: Oops, missed that one. Should be fixed now.
[a1229cd](https://github.com/rabits/ha-ef-ble/pull/6/commits/a1229cd2c498c864156314f7d24b22cae11b0539)
created_at: 2025-03-02T05:39:35Z
author_association: COLLABORATOR
diff_hunk: @@ -46,40 +218,30 @@ async def async_setup_entry(
     if hasattr(device, "circuit_current"):
         for i in range(len(device.circuit_current)):
             new_sensors.append(CircuitCurrentSensor(device, i))
-    if hasattr(device, "grid_power"):
-        new_sensors.append(GridPowerSensor(device))
-    if hasattr(device, "in_use_power"):
-        new_sensors.append(InUsePowerSensor(device))
     if hasattr(device, "channel_power"):
         for i in range(len(device.channel_power)):
             new_sensors.append(ChannelPowerSensor(device, i))
 
-    # DPU sensors
-    if hasattr(device, "hv_solar_power"):
-        new_sensors.append(HVSolarPowerSensor(device))
-    if hasattr(device, "lv_solar_power"):
-        new_sensors.append(LVSolarPowerSensor(device))
-    if hasattr(device, "input_power"):
-        new_sensors.append(InputPowerSensor(device))
-    if hasattr(device, "output_power"):
-        new_sensors.append(OutputPowerSensor(device))
-
     if new_sensors:
         async_add_entities(new_sensors)
 
 
-class SensorBase(SensorEntity):
+class EcoflowSensor(SensorEntity):
     """Base representation of a sensor."""
 
     _attr_has_entity_name = True
-    _attr_state_class = SensorStateClass.MEASUREMENT
 
-    # Name of the property to use to get a native value
-    ef_dev_property = "UNDEFINED"
-
-    def __init__(self, device):
+    def __init__(self, device: DeviceBase, sensor: str):
         """Initialize the sensor."""
         self._device = device
+        self._sensor = sensor
+        self._attr_unique_id = f"{device.name}_{sensor}"
+
+        if sensor in SENSOR_TYPES:
+            self.entity_description = SENSOR_TYPES[sensor]
+
+        if self.entity_description.state_class is None:
path: custom_components/ef_ble/sensor.py
user: login: rabits
body: Yep, just a quick fix, but works
created_at: 2025-03-02T05:41:14Z
author_association: OWNER

PR comments:
user: login: rabits
created_at: 2025-03-01T23:55:39Z
body: Thank you @GnoX , will check it quickly
author_association: OWNER
user: login: rabits
created_at: 2025-03-02T01:23:35Z
body: Another issue I see right now on my SHP2:
```
ValueError: Sensor sensor.ef_hd30377_channel_power has device class 'power', state class 'measurement' unit 'W' and suggested precision '2' thus indicating it has a numeric value; however, it has the non-numeric value: '[-481.0, -498.5, 0.0]' (<class 'list'>)
2025-03-01 20:19:46.595 WARNING (MainThread) [aioecowitt.server] Unhandled sensor type console_batt value 3.00
```

So we can't actually process those arrays as sensor value... Now I'm worrying we trying to change too much stuff at the same time((
author_association: OWNER
user: login: GnoX
created_at: 2025-03-02T01:26:57Z
body: > Another issue I see right now on my SHP2:
> 
> ```
> ValueError: Sensor sensor.ef_hd30377_channel_power has device class 'power', state class 'measurement' unit 'W' and suggested precision '2' thus indicating it has a numeric value; however, it has the non-numeric value: '[-481.0, -498.5, 0.0]' (<class 'list'>)
> 2025-03-01 20:19:46.595 WARNING (MainThread) [aioecowitt.server] Unhandled sensor type console_batt value 3.00
> ```
> 
> So we can't actually process those arrays as sensor value...

Ah, right when I thought I solved the problem elegantly. Should I revert it to how it looked before and leave it for you to update?
author_association: COLLABORATOR
user: login: rabits
created_at: 2025-03-02T01:30:40Z
body: Yeah, let's try the simpler approach to first add new device and then move to more complicated refactoring things if you don't mind - worrying that will make me to spend much more time than I expected to spend on this change) So small steps will be better. And let's not use partial update - maybe you actually right and it doesn't make sense to be used now.
author_association: OWNER
user: login: GnoX
created_at: 2025-03-02T01:38:25Z
body: Actually, can you try my latest changes? I thought that error was raised after my fix, but that was with your suggested change, right?
I added a check in this commit [43652b5](https://github.com/rabits/ha-ef-ble/pull/6/commits/43652b503cf7d44bc03ea8ed6bbef4b41a8d4ecc) that should have fixed the first error.
author_association: COLLABORATOR
user: login: rabits
created_at: 2025-03-02T02:05:04Z
body: Yeah sure, will be back in ~3 hours...
author_association: OWNER
user: login: rabits
created_at: 2025-03-02T04:18:57Z
body: Sorry, but seems not that simple, because you using it right the next line: `if self.entity_description.state_class is None:`
```
2025-03-01 23:04:13.202 ERROR (MainThread) [homeassistant.components.sensor] Error while setting up ef_ble platform for sensor
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/entity_platform.py", line 366, in _async_setup_platform
    await asyncio.shield(awaitable)
  File "/config/custom_components/ef_ble/sensor.py", line 217, in async_setup_entry
    new_sensors.append(CircuitPowerSensor(device, i))
                       ~~~~~~~~~~~~~~~~~~^^^^^^^^^^^
  File "/config/custom_components/ef_ble/sensor.py", line 285, in __init__
    super().__init__(device, f"circuit_power_{index}")
    ~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/ef_ble/sensor.py", line 243, in __init__
    if self.entity_description.state_class is None:
       ^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'CircuitPowerSensor' object has no attribute 'entity_description'
2025-03-01 23:04:13.207 INFO (MainThread) [homeassistant.components.binary_sensor] Setting up ef_ble.binary_sensor
2025-03-01 23:04:13.207 ERROR (MainThread) [homeassistant.components.binary_sensor] Error while setting up ef_ble platform for binary_sensor
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/entity_platform.py", line 366, in _async_setup_platform
    await asyncio.shield(awaitable)
  File "/config/custom_components/ef_ble/binary_sensor.py", line 26, in async_setup_entry
    new_sensors.append(ErrorDetectedSensor(device, "error_happened"))
                       ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/ef_ble/binary_sensor.py", line 40, in __init__
    super().__init__(device, sensor)
    ~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^
  File "/config/custom_components/ef_ble/sensor.py", line 243, in __init__
    if self.entity_description.state_class is None:
       ^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'ErrorDetectedSensor' object has no attribute 'entity_description'
```

So I had to add this change to make it work - and seems with it it works quite well:
```diff
diff --git a/custom_components/ef_ble/sensor.py b/custom_components/ef_ble/sensor.py
index 18cd0ea..6aa5fe4 100644
--- a/custom_components/ef_ble/sensor.py
+++ b/custom_components/ef_ble/sensor.py
@@ -239,8 +239,9 @@ class EcoflowSensor(SensorEntity):

         if sensor in SENSOR_TYPES:
             self.entity_description = SENSOR_TYPES[sensor]
-
-        if self.entity_description.state_class is None:
+            if self.entity_description.state_class is None:
+                self._attr_state_class = SensorStateClass.MEASUREMENT
+        else:
             self._attr_state_class = SensorStateClass.MEASUREMENT

     @property
```
author_association: OWNER
user: login: GnoX
created_at: 2025-03-02T06:11:07Z
body: Great! Thanks for the review and also huge thanks for doing a great job of making this integration and providing good documentation. I thought it would take me several weeks to add River 3 to HA but it only took me a weekend.

BTW, I don't have the permission to merge it so feel free to merge it anytime.
author_association: COLLABORATOR
user: login: rabits
created_at: 2025-03-02T18:41:11Z
body: Thank you for contribution! I will release a new version of the integration today.
author_association: OWNER