diff --git a/README.md b/README.md index f865ea6..1807142 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ After the installation, you can use this button to install the integration: - AC60 - AC180 (basic data) - AC180P (basic data) +- AC200L (untested) - AC200M - AC300 (tested) - AC500 diff --git a/custom_components/bluetti_bt/bluetti_bt_lib/devices/ac200l.py b/custom_components/bluetti_bt/bluetti_bt_lib/devices/ac200l.py new file mode 100644 index 0000000..ab80a10 --- /dev/null +++ b/custom_components/bluetti_bt/bluetti_bt_lib/devices/ac200l.py @@ -0,0 +1,59 @@ +"""AC200L fields.""" + +from typing import List + +from ..utils.commands import ReadHoldingRegisters +from ..field_enums import AutoSleepMode, OutputMode +from ..base_devices.ProtocolV1Device import ProtocolV1Device + + +class AC200L(ProtocolV1Device): + def __init__(self, address: str, sn: str): + super().__init__(address, "AC200L", sn) + + # Details + self.struct.add_enum_field("ac_output_mode", 70, OutputMode) + self.struct.add_decimal_field("internal_ac_voltage", 71, 1) + self.struct.add_decimal_field("internal_current_one", 72, 1) + self.struct.add_uint_field("internal_power_one", 73) + self.struct.add_decimal_field("internal_ac_frequency", 74, 2) + self.struct.add_uint_field("internal_dc_input_voltage", 86) + self.struct.add_decimal_field("internal_dc_input_power", 87, 1) + self.struct.add_decimal_field("internal_dc_input_current", 88, 2) + + # Battery packs + self.struct.add_uint_field("pack_num_max", 91) # internal + self.struct.add_decimal_field("total_battery_voltage", 92, 1) + self.struct.add_uint_field("pack_num", 96) # internal + self.struct.add_decimal_field("pack_voltage", 98, 2) # Full pack voltage + self.struct.add_uint_field("pack_battery_percent", 99) + self.struct.add_decimal_array_field("cell_voltages", 105, 16, 2) # internal + + # Controls + self.struct.add_bool_field("power_off", 3060) + self.struct.add_enum_field("auto_sleep_mode", 3061, AutoSleepMode) + + @property + def pack_num_max(self): + return 3 + + @property + def polling_commands(self) -> List[ReadHoldingRegisters]: + return super().polling_commands + [ + ReadHoldingRegisters(70, 5), + ReadHoldingRegisters(86, 3), + ReadHoldingRegisters(3060, 2), + ] + + @property + def writable_ranges(self) -> List[range]: + return super().writable_ranges + [range(3060, 3062)] + + @property + def pack_polling_commands(self) -> List[ReadHoldingRegisters]: + return [ + ReadHoldingRegisters(91, 2), + ReadHoldingRegisters(96, 1), + ReadHoldingRegisters(98, 2), + ReadHoldingRegisters(105, 16) + ] diff --git a/custom_components/bluetti_bt/bluetti_bt_lib/utils/device_builder.py b/custom_components/bluetti_bt/bluetti_bt_lib/utils/device_builder.py index c113422..e0e56c7 100644 --- a/custom_components/bluetti_bt/bluetti_bt_lib/utils/device_builder.py +++ b/custom_components/bluetti_bt/bluetti_bt_lib/utils/device_builder.py @@ -5,6 +5,7 @@ import re from ..devices.ac60 import AC60 from ..devices.ac180 import AC180 from ..devices.ac180p import AC180P +from ..devices.ac200l import AC200L from ..devices.ac200m import AC200M from ..devices.ac300 import AC300 from ..devices.ac500 import AC500 @@ -16,7 +17,7 @@ from ..devices.ep760 import EP760 from ..devices.ep800 import EP800 DEVICE_NAME_RE = re.compile( - r"^(AC60|AC180|AC180P|AC200M|AC300|AC500|EB3A|EP500|EP500P|EP600|EP760|EP800)(\d+)$" + r"^(AC60|AC180|AC180P|AC200L|AC200M|AC300|AC500|EB3A|EP500|EP500P|EP600|EP760|EP800)(\d+)$" ) @@ -28,6 +29,8 @@ def build_device(address: str, name: str): return AC180(address, match[2]) if match[1] == "AC180P": return AC180P(address, match[2]) + if match[1] == "AC200L": + return AC200L(address, match[2]) if match[1] == "AC200M": return AC200M(address, match[2]) if match[1] == "AC300": diff --git a/custom_components/bluetti_bt/manifest.json b/custom_components/bluetti_bt/manifest.json index 34342ea..c11b1bf 100644 --- a/custom_components/bluetti_bt/manifest.json +++ b/custom_components/bluetti_bt/manifest.json @@ -4,6 +4,7 @@ "bluetooth": [ { "local_name": "AC60*" }, { "local_name": "AC180*" }, + { "local_name": "AC200L*" }, { "local_name": "AC200M*" }, { "local_name": "AC300*" }, { "local_name": "AC500*" },