From 928ff2bf5db0b564bc8264e5bf90c305c576a161 Mon Sep 17 00:00:00 2001 From: Patrick762 Date: Sat, 17 Feb 2024 20:09:59 +0100 Subject: [PATCH] added ac300 --- .../bluetti_bt_lib/devices/ac200m.py | 6 +- .../bluetti_bt_lib/devices/ac300.py | 68 +++++++++++++++ .../bluetti_bt_lib/field_attributes.py | 82 +++++++++++++++++-- .../bluetti_bt/bluetti_bt_lib/field_enums.py | 12 +++ 4 files changed, 158 insertions(+), 10 deletions(-) create mode 100644 custom_components/bluetti_bt/bluetti_bt_lib/devices/ac300.py diff --git a/custom_components/bluetti_bt/bluetti_bt_lib/devices/ac200m.py b/custom_components/bluetti_bt/bluetti_bt_lib/devices/ac200m.py index b2df3ee..f1193e6 100644 --- a/custom_components/bluetti_bt/bluetti_bt_lib/devices/ac200m.py +++ b/custom_components/bluetti_bt/bluetti_bt_lib/devices/ac200m.py @@ -31,18 +31,18 @@ class AC200M(ProtocolV1Device): @property def pack_num_max(self): return 3 - + @property def polling_commands(self) -> List[ReadHoldingRegisters]: return super().polling_commands + [ ReadHoldingRegisters(70, 4), ReadHoldingRegisters(86, 3), ] - + @property def writable_ranges(self) -> List[range]: return super().writable_ranges + [range(3060, 3061)] - + @property def pack_polling_commands(self) -> List[ReadHoldingRegisters]: return super().pack_polling_commands + [ReadHoldingRegisters(105, 16)] diff --git a/custom_components/bluetti_bt/bluetti_bt_lib/devices/ac300.py b/custom_components/bluetti_bt/bluetti_bt_lib/devices/ac300.py new file mode 100644 index 0000000..8e61af9 --- /dev/null +++ b/custom_components/bluetti_bt/bluetti_bt_lib/devices/ac300.py @@ -0,0 +1,68 @@ +"""AC300 fields.""" + +from typing import List + +from ..utils.commands import ReadHoldingRegisters +from ..field_enums import AutoSleepMode, OutputMode, SplitPhaseMachineType, UpsMode +from ..base_devices.ProtocolV1Device import ProtocolV1Device + + +class AC300(ProtocolV1Device): + def __init__(self, address: str, sn: str): + super().__init__(address, "AC300", sn) + + # Details + self.struct.add_enum_field('ac_output_mode', 70, OutputMode) + self.struct.add_uint_field('internal_ac_voltage', 71) + 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, 1) + self.struct.add_decimal_field('internal_current_two', 75, 1) + self.struct.add_uint_field('internal_power_two', 76) + self.struct.add_decimal_field('ac_input_voltage', 77, 1) + self.struct.add_decimal_field('internal_current_three', 78, 1, (0, 100)) + self.struct.add_uint_field('internal_power_three', 79) + self.struct.add_decimal_field('ac_input_frequency', 80, 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_decimal_array_field('cell_voltages', 105, 16, 2) # internal + self.struct.add_version_field('pack_bms_version', 201) + + # Controls + self.struct.add_enum_field('ups_mode', 3001, UpsMode) + self.struct.add_bool_field('split_phase_on', 3004) + self.struct.add_enum_field('split_phase_machine_mode', 3005, SplitPhaseMachineType) + self.struct.add_bool_field('grid_charge_on', 3011) + self.struct.add_bool_field('time_control_on', 3013) + self.struct.add_uint_field('battery_range_start', 3015) + self.struct.add_uint_field('battery_range_end', 3016) + self.struct.add_enum_field('auto_sleep_mode', 3061, AutoSleepMode) + + + @property + def pack_num_max(self): + return 4 + + @property + def polling_commands(self) -> List[ReadHoldingRegisters]: + return super().polling_commands + [ + ReadHoldingRegisters(70, 10), + ReadHoldingRegisters(86, 3), + ] + + @property + def writable_ranges(self) -> List[range]: + return super().writable_ranges + [ + range(3001, 3016), + 3061, + ] + + @property + def pack_polling_commands(self) -> List[ReadHoldingRegisters]: + return super().pack_polling_commands + [ + ReadHoldingRegisters(105, 16), + ReadHoldingRegisters(201, 2), + ] diff --git a/custom_components/bluetti_bt/bluetti_bt_lib/field_attributes.py b/custom_components/bluetti_bt/bluetti_bt_lib/field_attributes.py index dda171d..56fd903 100644 --- a/custom_components/bluetti_bt/bluetti_bt_lib/field_attributes.py +++ b/custom_components/bluetti_bt/bluetti_bt_lib/field_attributes.py @@ -3,7 +3,7 @@ from dataclasses import dataclass from enum import Enum, auto, unique -from .field_enums import AutoSleepMode, OutputMode +from .field_enums import AutoSleepMode, OutputMode, SplitPhaseMachineType, UpsMode @unique @@ -45,6 +45,13 @@ class CurrentFieldAttributes(FieldAttributes): device_class = 'current' state_class = 'measurement' +@dataclass +class FrequencyFieldAttributes(FieldAttributes): + type = FieldType.NUMERIC, + unit_of_measurement = 'Hz', + device_class = 'frequency', + state_class ='measurement', + @dataclass(frozen=True) class OutletFieldAttributes(FieldAttributes): type = FieldType.BOOL @@ -87,6 +94,8 @@ FIELD_ATTRIBUTES = { 'dc_output_on': OutletFieldAttributes( name = 'DC Output', ), + + # Controls 'ac_output_on_switch': OutletFieldAttributes( name = 'AC Output', setter = True, @@ -111,12 +120,26 @@ FIELD_ATTRIBUTES = { 'internal_power_one': PowerFieldAttributes( name = 'Internal Power Sensor 1', ), - 'internal_ac_frequency': FieldAttributes( - type = FieldType.NUMERIC, + 'internal_ac_frequency': FrequencyFieldAttributes( name = 'Internal AC Frequency', - unit_of_measurement = 'Hz', - device_class = 'frequency', - state_class ='measurement', + ), + 'internal_current_two': CurrentFieldAttributes( + name = 'Internal Current Sensor 2', + ), + 'internal_power_two': PowerFieldAttributes( + name = 'Internal Power Sensor 2', + ), + 'ac_input_voltage': VoltageFieldAttributes( + name = 'AC Input Voltage', + ), + 'internal_current_three': CurrentFieldAttributes( + name = 'Internal Current Sensor 3', + ), + 'internal_power_three': PowerFieldAttributes( + name = 'Internal Power Sensor 3', + ), + 'ac_input_frequency': FrequencyFieldAttributes( + name = 'AC Input Frequency', ), 'internal_dc_input_voltage': VoltageFieldAttributes( name = 'Internal DC Input Voltage', @@ -127,6 +150,8 @@ FIELD_ATTRIBUTES = { 'internal_dc_input_current': CurrentFieldAttributes( name = 'Internal DC Input Current', ), + + # Device specific controls 'power_off': FieldAttributes( type = FieldType.BUTTON, setter = True, @@ -138,6 +163,45 @@ FIELD_ATTRIBUTES = { name = 'Screen Auto Sleep Mode', options = AutoSleepMode, ), + 'ups_mode': FieldAttributes( + type = FieldType.ENUM, + setter = False, # Disabled for safety reasons + name = 'UPS Working Mode', + options = UpsMode, + ), + 'split_phase_on': FieldAttributes( + type = FieldType.BOOL, + setter = False, # Disabled for safety reasons + name = 'Split Phase', + ), + 'split_phase_machine_mode': FieldAttributes( + type = FieldType.ENUM, + setter = False, # Disabled for safety reasons + name = 'Split Phase Machine Type', + options = SplitPhaseMachineType, + ), + 'grid_charge_on': FieldAttributes( + type = FieldType.BOOL, + setter = False, # Disabled for safety reasons + name = 'Grid Charge', + ), + 'time_control_on': FieldAttributes( + type = FieldType.BOOL, + setter = False, # Disabled for safety reasons + name = 'Time Control', + ), + 'battery_range_start': FieldAttributes( + type = FieldType.NUMERIC, + setter = False, # Disabled + name = 'Battery Range Start', + unit_of_measurement = '%', + ), + 'battery_range_end': FieldAttributes( + type = FieldType.NUMERIC, + setter = False, # Disabled + name = 'Battery Range End', + unit_of_measurement = '%', + ), } def PACK_FIELD_ATTRIBUTES(pack: int): @@ -146,10 +210,14 @@ def PACK_FIELD_ATTRIBUTES(pack: int): name = f'Battery Pack {pack} Voltage', ), 'pack_battery_percent': FieldAttributes( - type = FieldType, + type = FieldType.NUMERIC, name = f'Battery Pack {pack} Percent', unit_of_measurement = '%', device_class ='battery', state_class ='measurement', ), + 'pack_bms_version': FieldAttributes( + type = FieldType.NUMERIC, + name = f'Battery Pack {pack} BMS Version', + ), } diff --git a/custom_components/bluetti_bt/bluetti_bt_lib/field_enums.py b/custom_components/bluetti_bt/bluetti_bt_lib/field_enums.py index b1aecfc..8040c97 100644 --- a/custom_components/bluetti_bt/bluetti_bt_lib/field_enums.py +++ b/custom_components/bluetti_bt/bluetti_bt_lib/field_enums.py @@ -18,3 +18,15 @@ class AutoSleepMode(Enum): ONE_MINUTE = 3 FIVE_MINUTES = 4 NEVER = 5 + +@unique +class UpsMode(Enum): + CUSTOMIZED = 1 + PV_PRIORITY = 2 + STANDARD = 3 + TIME_CONTROL = 4 + +@unique +class SplitPhaseMachineType(Enum): + SLAVE = 0 + MASTER = 1