From 730153b2cb1313ff2bfdc9ca8344c46b8f877be9 Mon Sep 17 00:00:00 2001 From: Maylon Pedroso Date: Thu, 12 Dec 2024 11:08:11 -0500 Subject: [PATCH] WIP: add AC2A support --- bluetti_mqtt/bluetooth/__init__.py | 6 ++-- bluetti_mqtt/core/__init__.py | 1 + bluetti_mqtt/core/devices/ac2a.py | 57 ++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 bluetti_mqtt/core/devices/ac2a.py diff --git a/bluetti_mqtt/bluetooth/__init__.py b/bluetti_mqtt/bluetooth/__init__.py index 5d5bea8..e2bfe20 100644 --- a/bluetti_mqtt/bluetooth/__init__.py +++ b/bluetti_mqtt/bluetooth/__init__.py @@ -3,13 +3,13 @@ from typing import Set from bleak import BleakScanner from bleak.backends.device import BLEDevice -from bluetti_mqtt.core import BluettiDevice, AC200M, AC300, AC500, AC60, EP500, EP500P, EP600, EB3A +from bluetti_mqtt.core import BluettiDevice, AC200M, AC300, AC500, AC60, EP500, EP500P, EP600, EB3A, AC2A from .client import BluetoothClient from .exc import BadConnectionError, ModbusError, ParseError from .manager import MultiDeviceManager -DEVICE_NAME_RE = re.compile(r'^(AC200M|AC300|AC500|AC60|EP500P|EP500|EP600|EB3A)(\d+)$') +DEVICE_NAME_RE = re.compile(r'^(AC200M|AC300|AC500|AC60|AC2A|EP500P|EP500|EP600|EB3A)(\d+)$') async def scan_devices(): @@ -41,6 +41,8 @@ def build_device(address: str, name: str): return EP600(address, match[2]) if match[1] == 'EB3A': return EB3A(address, match[2]) + if match[1] == 'AC2A': + return AC2A(address, match[2]) async def check_addresses(addresses: Set[str]): diff --git a/bluetti_mqtt/core/__init__.py b/bluetti_mqtt/core/__init__.py index 2d16d41..5d8295c 100644 --- a/bluetti_mqtt/core/__init__.py +++ b/bluetti_mqtt/core/__init__.py @@ -7,6 +7,7 @@ from .devices.ep500p import EP500P from .devices.ep600 import EP600 from .devices.eb3a import EB3A +from .devices.ac2a import AC2A from .commands import ( DeviceCommand, ReadHoldingRegisters, diff --git a/bluetti_mqtt/core/devices/ac2a.py b/bluetti_mqtt/core/devices/ac2a.py new file mode 100644 index 0000000..7417a8f --- /dev/null +++ b/bluetti_mqtt/core/devices/ac2a.py @@ -0,0 +1,57 @@ +from typing import List +from ..commands import ReadHoldingRegisters +from .bluetti_device import BluettiDevice +from .struct import DeviceStruct + + +class AC2A(BluettiDevice): + def __init__(self, address: str, sn: str): + self.struct = DeviceStruct() + + # Core device properties + self.struct.add_uint_field('total_battery_percent', 102) + self.struct.add_swap_string_field('device_type', 110, 6) + self.struct.add_sn_field('serial_number', 116) + self.struct.add_decimal_field('power_generation', 154, 1) + + # AC/DC output on/off states found in bit 3/4 + # self.struct.add_uint_field('ac_output_on', 1131) # bit 3 + # self.struct.add_uint_field('dc_output_on', 1131) # bit 4 + + # Input power + self.struct.add_uint_field('dc_input_power', 1200) + self.struct.add_uint_field('ac_input_power', 1313) + + # Output power + self.struct.add_uint_field('dc_output_power', 1400) + self.struct.add_uint_field('ac_output_power', 1420) + + # ac_output_power_on is the electrical relay (delay of ~1s to ac_output_on) + # self.struct.add_bool_field('ac_output_power_on', 1509) + # self.struct.add_uint_field('ac_output_power', 1510) + + # Output buttons + self.struct.add_bool_field('dc_output_on', 2012) + self.struct.add_bool_field('ac_output_on', 2011) + + super().__init__(address, "AC2A", sn) + + @property + def logging_commands(self) -> List[ReadHoldingRegisters]: + return [ + ReadHoldingRegisters(100, 62), # Device info + # ReadHoldingRegisters(1100, 51), # AC/DC output on/off + ReadHoldingRegisters(1200, 90), # DC input power + ReadHoldingRegisters(1300, 31), # AC input power + + ReadHoldingRegisters(1400, 48), # AC/DC output power + + # ReadHoldingRegisters(1500, 30), # AC output power and on/of + + ReadHoldingRegisters(2000, 67), # DC output on/off + + # ReadHoldingRegisters(2200, 29), + # ReadHoldingRegisters(6000, 31), + # ReadHoldingRegisters(6100, 100), + # ReadHoldingRegisters(6300, 52), + ]