diff --git a/custom_components/bluetti_bt/__init__.py b/custom_components/bluetti_bt/__init__.py index 9ef157b..46be53c 100644 --- a/custom_components/bluetti_bt/__init__.py +++ b/custom_components/bluetti_bt/__init__.py @@ -4,6 +4,7 @@ from __future__ import annotations import re import logging +from typing import List from homeassistant.components import bluetooth from homeassistant.config_entries import ConfigEntry @@ -25,7 +26,7 @@ from .const import ( ) from .coordinator import PollingCoordinator -PLATFORMS: [Platform] = [Platform.BINARY_SENSOR, Platform.SENSOR] +PLATFORMS: List[Platform] = [Platform.BINARY_SENSOR, Platform.SENSOR] _LOGGER = logging.getLogger(__name__) 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 new file mode 100644 index 0000000..f549558 --- /dev/null +++ b/custom_components/bluetti_bt/bluetti_bt_lib/utils/device_builder.py @@ -0,0 +1,34 @@ +"""Device builder functions.""" + +import re + +from ..devices.ac60 import AC60 +from ..devices.ac200m import AC200M +from ..devices.ac300 import AC300 +from ..devices.ac500 import AC500 +from ..devices.eb3a import EB3A +from ..devices.ep500 import EP500 +from ..devices.ep500p import EP500P +from ..devices.ep600 import EP600 + +DEVICE_NAME_RE = re.compile(r"^(AC60|AC200M|AC300|AC500|EB3A|EP500|EP500P|EP600)(\d+)$") + + +def build_device(address: str, name: str): + match = DEVICE_NAME_RE.match(name) + if match[1] == "AC60": + return AC60(address, match[2]) + if match[1] == "AC200M": + return AC200M(address, match[2]) + if match[1] == "AC300": + return AC300(address, match[2]) + if match[1] == "AC500": + return AC500(address, match[2]) + if match[1] == "EB3A": + return EB3A(address, match[2]) + if match[1] == "EP500": + return EP500(address, match[2]) + if match[1] == "EP500P": + return EP500P(address, match[2]) + if match[1] == "EP600": + return EP600(address, match[2]) diff --git a/custom_components/bluetti_bt/devices/ep600.py b/custom_components/bluetti_bt/devices/ep600.py deleted file mode 100644 index 3ea91a7..0000000 --- a/custom_components/bluetti_bt/devices/ep600.py +++ /dev/null @@ -1,113 +0,0 @@ -"""EP600 Field definitions. - -Changes made here are only temporary and should also be -contributed to https://github.com/warhammerkid/bluetti_mqtt -""" - -from typing import List - -from bluetti_mqtt.core.devices.bluetti_device import BluettiDevice -from bluetti_mqtt.core.devices.struct import DeviceStruct -from bluetti_mqtt.core.commands import ReadHoldingRegisters - -class EP600(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_uint_field('battery_range_start', 2022) - self.struct.add_uint_field('battery_range_end', 2023) - self.struct.add_uint_field('max_ac_input_power', 2213) - self.struct.add_uint_field('max_ac_input_current', 2214) - self.struct.add_uint_field('max_ac_output_power', 2215) - self.struct.add_uint_field('max_ac_output_current', 2216) - 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) - self.struct.add_version_field('bmu_version', 6178) - self.struct.add_version_field('safety_module_version', 6181) - self.struct.add_version_field('high_voltage_module_version', 6184) - - # DC Solar Input (copied from PR https://github.com/warhammerkid/bluetti_mqtt/pull/87 by KM011092) - self.struct.add_uint_field('pv_input_power1', 1212) # MPP 1 in - value * 0.1 - #self.struct.add_uint_field('pv_input_voltage1', 1213) # MPP 1 in - value * 0.1 - #self.struct.add_uint_field('pv_input_current1', 1214) # MPP 1 in - self.struct.add_uint_field('pv_input_power2', 1220) # MPP 2 in - value * 0.1 - #self.struct.add_uint_field('pv_input_voltage2', 1221) # MPP 2 in - value * 0.1 - #self.struct.add_uint_field('pv_input_current2', 1222) # MPP 2 in - - # ADL400 Smart Meter for AC Solar - self.struct.add_uint_field("adl400_ac_input_power_phase1", 1228) - self.struct.add_uint_field("adl400_ac_input_power_phase2", 1236) - self.struct.add_uint_field("adl400_ac_input_power_phase3", 1244) - self.struct.add_decimal_field("adl400_ac_input_voltage_phase1", 1229, 1) - self.struct.add_decimal_field("adl400_ac_input_voltage_phase2", 1237, 1) - self.struct.add_decimal_field("adl400_ac_input_voltage_phase3", 1245, 1) - - # Grid Input - self.struct.add_decimal_field("grid_input_frequency", 1300, 1) - self.struct.add_uint_field("grid_input_power_phase1", 1313) - self.struct.add_uint_field("grid_input_power_phase2", 1319) - self.struct.add_uint_field("grid_input_power_phase3", 1325) - self.struct.add_decimal_field("grid_input_voltage_phase1", 1314, 1) - self.struct.add_decimal_field("grid_input_voltage_phase2", 1320, 1) - self.struct.add_decimal_field("grid_input_voltage_phase3", 1326, 1) - self.struct.add_decimal_field("grid_input_current_phase1", 1315, 1) - self.struct.add_decimal_field("grid_input_current_phase2", 1321, 1) - self.struct.add_decimal_field("grid_input_current_phase3", 1327, 1) - - # EP600 AC Output - self.struct.add_decimal_field("ac_output_frequency", 1500, 1) - self.struct.add_uint_field("ac_output_power_phase1", 1510) - self.struct.add_uint_field("ac_output_power_phase2", 1517) - self.struct.add_uint_field("ac_output_power_phase3", 1524) - self.struct.add_decimal_field("ac_output_voltage_phase1", 1511, 1) - self.struct.add_decimal_field("ac_output_voltage_phase2", 1518, 1) - self.struct.add_decimal_field("ac_output_voltage_phase3", 1525, 1) - self.struct.add_decimal_field("ac_output_current_phase1", 1512, 1) - self.struct.add_decimal_field("ac_output_current_phase2", 1519, 1) - self.struct.add_decimal_field("ac_output_current_phase3", 1526, 1) - - super().__init__(address, 'EP600', sn) - - @property - def polling_commands(self) -> List[ReadHoldingRegisters]: - return [ - ReadHoldingRegisters(100, 62), - ReadHoldingRegisters(1228, 19), - ReadHoldingRegisters(1300, 28), - ReadHoldingRegisters(1500, 27), - ReadHoldingRegisters(2022, 6), - ReadHoldingRegisters(2213, 4), - ReadHoldingRegisters(1212, 11), - # Battery - ReadHoldingRegisters(6101, 7), - ReadHoldingRegisters(6175, 11), - ] - - @property - def pack_polling_commands(self) -> List[ReadHoldingRegisters]: - return [] - - @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, 89), - ReadHoldingRegisters(2200, 41), - ReadHoldingRegisters(2300, 36), - ReadHoldingRegisters(6000, 32), - ReadHoldingRegisters(6100, 100), - ReadHoldingRegisters(6300, 100), - ] diff --git a/custom_components/bluetti_bt/utils.py b/custom_components/bluetti_bt/utils.py index a42f928..2062f12 100644 --- a/custom_components/bluetti_bt/utils.py +++ b/custom_components/bluetti_bt/utils.py @@ -1,11 +1,11 @@ """Tools.""" -from bluetti_mqtt.bluetooth import build_device as orig_build_device +from .bluetti_bt_lib.utils.device_builder import build_device as orig_build_device from .const import DEVICE_NAME_RE -from .devices.ep600 import EP600 from .devices.ep760 import EP760 + def mac_loggable(mac: str) -> str: """Remove parts of the mac address for logging.""" splitted = mac.split(":") @@ -21,7 +21,5 @@ def build_device(address: str, name: str): match = DEVICE_NAME_RE.match(name) if match[1] == 'EP760': return EP760(address, match[2]) - elif match[1] == 'EP600': - return EP600(address, match[2]) else: return orig_build_device(address, name)