diff --git a/bluetti_mqtt/bluetooth/__init__.py b/bluetti_mqtt/bluetooth/__init__.py index 5d5bea8..321dd11 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, AC180, AC200M, AC300, AC500, AC60, EP500, EP500P, EP600, EB3A 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'^(AC180|AC200M|AC300|AC500|AC60|EP500P|EP500|EP600|EB3A)(\d+)$') async def scan_devices(): @@ -25,6 +25,9 @@ async def scan_devices(): def build_device(address: str, name: str): match = DEVICE_NAME_RE.match(name) + if match[1] == 'AC180': + return AC180(address, match[2]) + match = DEVICE_NAME_RE.match(name) if match[1] == 'AC200M': return AC200M(address, match[2]) if match[1] == 'AC300': diff --git a/bluetti_mqtt/core/__init__.py b/bluetti_mqtt/core/__init__.py index 2d16d41..6cc0751 100644 --- a/bluetti_mqtt/core/__init__.py +++ b/bluetti_mqtt/core/__init__.py @@ -1,4 +1,5 @@ from .devices.bluetti_device import BluettiDevice +from .devices.ac180 import AC180 from .devices.ac200m import AC200M from .devices.ac300 import AC300 from .devices.ac500 import AC500 diff --git a/bluetti_mqtt/core/devices/ac180.py b/bluetti_mqtt/core/devices/ac180.py new file mode 100644 index 0000000..0171623 --- /dev/null +++ b/bluetti_mqtt/core/devices/ac180.py @@ -0,0 +1,44 @@ +from typing import List +from ..commands import ReadHoldingRegisters +from .bluetti_device import BluettiDevice +from .struct import DeviceStruct + + +class AC180(BluettiDevice): + def __init__(self, address: str, sn: str): + self.struct = DeviceStruct() + + 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) # Total power generated since last reset (kwh) + self.struct.add_swap_string_field('device_type', 1101, 6) + self.struct.add_sn_field('serial_number', 1107) + self.struct.add_decimal_field('power_generation', 1202, 1) # Total power generated since last reset (kwh) + self.struct.add_swap_string_field('battery_type', 6101, 6) + self.struct.add_sn_field('battery_serial_number', 6107) + self.struct.add_version_field('bcu_version', 6175) + + super().__init__(address, 'AC180', sn) + + @property + def polling_commands(self) -> List[ReadHoldingRegisters]: + return [ + ReadHoldingRegisters(100, 62), + ] + + @property + def logging_commands(self) -> List[ReadHoldingRegisters]: + return [ + ReadHoldingRegisters(100, 62), + ReadHoldingRegisters(1100, 51), + ReadHoldingRegisters(1200, 90), + ReadHoldingRegisters(1300, 31), + ReadHoldingRegisters(1400, 48), + ReadHoldingRegisters(1500, 30), + ReadHoldingRegisters(2000, 67), + ReadHoldingRegisters(2200, 29), + ReadHoldingRegisters(6000, 31), + ReadHoldingRegisters(6100, 100), + ReadHoldingRegisters(6300, 52), + ]