diff --git a/custom_components/bluetti_bt/bluetti_bt_lib/base_devices/ProtocolV1Device.py b/custom_components/bluetti_bt/bluetti_bt_lib/base_devices/ProtocolV1Device.py index 6dd4dd0..7f1f585 100644 --- a/custom_components/bluetti_bt/bluetti_bt_lib/base_devices/ProtocolV1Device.py +++ b/custom_components/bluetti_bt/bluetti_bt_lib/base_devices/ProtocolV1Device.py @@ -29,13 +29,6 @@ class ProtocolV1Device(BluettiDevice): # Battery self.struct.add_uint_field("total_battery_percent", 43) - # 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) - # Output state self.struct.add_bool_field("ac_output_on", 48) self.struct.add_bool_field("dc_output_on", 49) @@ -56,20 +49,10 @@ class ProtocolV1Device(BluettiDevice): ReadHoldingRegisters(36, 4), ReadHoldingRegisters(41, 1), ReadHoldingRegisters(43, 1), - ReadHoldingRegisters(91, 2), - ReadHoldingRegisters(96, 1), - ReadHoldingRegisters(98, 2), ReadHoldingRegisters(48, 2), + ReadHoldingRegisters(3007, 2), ] @property def writable_ranges(self) -> List[range]: return [range(3006, 3009)] - - @property - def pack_polling_commands(self) -> List[ReadHoldingRegisters]: - return [ - ReadHoldingRegisters(91, 2), - ReadHoldingRegisters(96, 1), - ReadHoldingRegisters(98, 2), - ] 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 f5fa41a..79feaea 100644 --- a/custom_components/bluetti_bt/bluetti_bt_lib/devices/ac200m.py +++ b/custom_components/bluetti_bt/bluetti_bt_lib/devices/ac200m.py @@ -13,15 +13,20 @@ class AC200M(ProtocolV1Device): # 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_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, 1) + 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 @@ -35,14 +40,20 @@ class AC200M(ProtocolV1Device): @property def polling_commands(self) -> List[ReadHoldingRegisters]: return super().polling_commands + [ - ReadHoldingRegisters(70, 4), + ReadHoldingRegisters(70, 5), ReadHoldingRegisters(86, 3), + ReadHoldingRegisters(3060, 2), ] @property def writable_ranges(self) -> List[range]: - return super().writable_ranges + [range(3060, 3061)] + return super().writable_ranges + [range(3060, 3062)] @property def pack_polling_commands(self) -> List[ReadHoldingRegisters]: - return super().pack_polling_commands + [ReadHoldingRegisters(105, 16)] + return [ + ReadHoldingRegisters(91, 2), + ReadHoldingRegisters(96, 1), + ReadHoldingRegisters(98, 2), + 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 index 3ceae5c..b94bd5f 100644 --- a/custom_components/bluetti_bt/bluetti_bt_lib/devices/ac300.py +++ b/custom_components/bluetti_bt/bluetti_bt_lib/devices/ac300.py @@ -11,12 +11,12 @@ class AC300(ProtocolV1Device): def __init__(self, address: str, sn: str): super().__init__(address, "AC300", sn) - # Details (matches EP500 + AC500) + # 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_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, 1) + self.struct.add_decimal_field("internal_ac_frequency", 74, 2) 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) @@ -28,10 +28,15 @@ class AC300(ProtocolV1Device): 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 self.struct.add_version_field("pack_bms_version", 201) - # Controls (matches EP500 + AC500) + # Controls self.struct.add_enum_field("ups_mode", 3001, UpsMode) self.struct.add_bool_field("split_phase_on", 3004) self.struct.add_enum_field( @@ -50,20 +55,29 @@ class AC300(ProtocolV1Device): @property def polling_commands(self) -> List[ReadHoldingRegisters]: return super().polling_commands + [ - ReadHoldingRegisters(70, 10), + ReadHoldingRegisters(70, 11), ReadHoldingRegisters(86, 3), + ReadHoldingRegisters(3001, 1), + ReadHoldingRegisters(3004, 2), + ReadHoldingRegisters(3011, 1), + ReadHoldingRegisters(3013, 1), + ReadHoldingRegisters(3015, 2), + ReadHoldingRegisters(3061, 1), ] @property def writable_ranges(self) -> List[range]: return super().writable_ranges + [ - range(3001, 3016), + range(3001, 3017), range(3061), ] @property def pack_polling_commands(self) -> List[ReadHoldingRegisters]: - return super().pack_polling_commands + [ + return [ + ReadHoldingRegisters(91, 2), + ReadHoldingRegisters(96, 1), + ReadHoldingRegisters(98, 2), ReadHoldingRegisters(105, 16), ReadHoldingRegisters(201, 2), ] diff --git a/custom_components/bluetti_bt/bluetti_bt_lib/devices/ac500.py b/custom_components/bluetti_bt/bluetti_bt_lib/devices/ac500.py index ca0dcc9..e9b6832 100644 --- a/custom_components/bluetti_bt/bluetti_bt_lib/devices/ac500.py +++ b/custom_components/bluetti_bt/bluetti_bt_lib/devices/ac500.py @@ -11,12 +11,12 @@ class AC500(ProtocolV1Device): def __init__(self, address: str, sn: str): super().__init__(address, "AC500", sn) - # Details (matches EP500 + AC300) + # 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_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, 1) + self.struct.add_decimal_field("internal_ac_frequency", 74, 2) 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) @@ -27,10 +27,15 @@ class AC500(ProtocolV1Device): self.struct.add_decimal_field("internal_dc_input_power", 87, 1) self.struct.add_decimal_field("internal_dc_input_current", 88, 2) - # Battery packs (matches EP500) + # 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 (matches EP500 + AC300) + # Controls self.struct.add_enum_field("ups_mode", 3001, UpsMode) self.struct.add_bool_field("split_phase_on", 3004) self.struct.add_enum_field( @@ -49,19 +54,28 @@ class AC500(ProtocolV1Device): @property def polling_commands(self) -> List[ReadHoldingRegisters]: return super().polling_commands + [ - ReadHoldingRegisters(70, 10), + ReadHoldingRegisters(70, 11), ReadHoldingRegisters(86, 3), + ReadHoldingRegisters(3001, 1), + ReadHoldingRegisters(3004, 2), + ReadHoldingRegisters(3011, 1), + ReadHoldingRegisters(3013, 1), + ReadHoldingRegisters(3015, 2), + ReadHoldingRegisters(3061, 1), ] @property def writable_ranges(self) -> List[range]: return super().writable_ranges + [ - range(3001, 3016), + range(3001, 3017), range(3061), ] @property def pack_polling_commands(self) -> List[ReadHoldingRegisters]: - return super().pack_polling_commands + [ + return [ + ReadHoldingRegisters(91, 2), + ReadHoldingRegisters(96, 1), + ReadHoldingRegisters(98, 2), ReadHoldingRegisters(105, 16), ] diff --git a/custom_components/bluetti_bt/bluetti_bt_lib/devices/ep500.py b/custom_components/bluetti_bt/bluetti_bt_lib/devices/ep500.py index c95c60e..0f374c6 100644 --- a/custom_components/bluetti_bt/bluetti_bt_lib/devices/ep500.py +++ b/custom_components/bluetti_bt/bluetti_bt_lib/devices/ep500.py @@ -11,12 +11,12 @@ class EP500(ProtocolV1Device): def __init__(self, address: str, sn: str): super().__init__(address, "EP500", sn) - # Details (matches AC500 + AC300) + # 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_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, 1) + self.struct.add_decimal_field("internal_ac_frequency", 74, 2) 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) @@ -27,10 +27,15 @@ class EP500(ProtocolV1Device): self.struct.add_decimal_field("internal_dc_input_power", 87, 1) self.struct.add_decimal_field("internal_dc_input_current", 88, 2) - # Battery packs (matches AC500) + # 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 (matches AC500 + AC300) + # Controls self.struct.add_enum_field("ups_mode", 3001, UpsMode) self.struct.add_bool_field("split_phase_on", 3004) self.struct.add_enum_field( @@ -45,19 +50,28 @@ class EP500(ProtocolV1Device): @property def polling_commands(self) -> List[ReadHoldingRegisters]: return super().polling_commands + [ - ReadHoldingRegisters(70, 10), + ReadHoldingRegisters(70, 11), ReadHoldingRegisters(86, 3), + ReadHoldingRegisters(3001, 1), + ReadHoldingRegisters(3004, 2), + ReadHoldingRegisters(3011, 1), + ReadHoldingRegisters(3013, 1), + ReadHoldingRegisters(3015, 2), + ReadHoldingRegisters(3061, 1), ] @property def writable_ranges(self) -> List[range]: return super().writable_ranges + [ - range(3001, 3016), + range(3001, 3017), range(3061), ] @property def pack_polling_commands(self) -> List[ReadHoldingRegisters]: - return super().pack_polling_commands + [ + return [ + ReadHoldingRegisters(91, 2), + ReadHoldingRegisters(96, 1), + ReadHoldingRegisters(98, 2), ReadHoldingRegisters(105, 16), ] diff --git a/custom_components/bluetti_bt/bluetti_bt_lib/devices/ep500p.py b/custom_components/bluetti_bt/bluetti_bt_lib/devices/ep500p.py index af462cb..872874c 100644 --- a/custom_components/bluetti_bt/bluetti_bt_lib/devices/ep500p.py +++ b/custom_components/bluetti_bt/bluetti_bt_lib/devices/ep500p.py @@ -11,12 +11,12 @@ class EP500P(ProtocolV1Device): def __init__(self, address: str, sn: str): super().__init__(address, "EP500P", sn) - # Details (matches AC500 + AC300) + # 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_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, 1) + self.struct.add_decimal_field("internal_ac_frequency", 74, 2) 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) @@ -27,10 +27,15 @@ class EP500P(ProtocolV1Device): self.struct.add_decimal_field("internal_dc_input_power", 87, 1) self.struct.add_decimal_field("internal_dc_input_current", 88, 2) - # Battery packs (matches AC500) + # 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 (matches AC500 + AC300) + # Controls self.struct.add_enum_field("ups_mode", 3001, UpsMode) self.struct.add_bool_field("split_phase_on", 3004) self.struct.add_enum_field( @@ -45,19 +50,28 @@ class EP500P(ProtocolV1Device): @property def polling_commands(self) -> List[ReadHoldingRegisters]: return super().polling_commands + [ - ReadHoldingRegisters(70, 10), + ReadHoldingRegisters(70, 11), ReadHoldingRegisters(86, 3), + ReadHoldingRegisters(3001, 1), + ReadHoldingRegisters(3004, 2), + ReadHoldingRegisters(3011, 1), + ReadHoldingRegisters(3013, 1), + ReadHoldingRegisters(3015, 2), + ReadHoldingRegisters(3061, 1), ] @property def writable_ranges(self) -> List[range]: return super().writable_ranges + [ - range(3001, 3016), + range(3001, 3017), range(3061), ] @property def pack_polling_commands(self) -> List[ReadHoldingRegisters]: - return super().pack_polling_commands + [ + return [ + ReadHoldingRegisters(91, 2), + ReadHoldingRegisters(96, 1), + ReadHoldingRegisters(98, 2), ReadHoldingRegisters(105, 16), ] diff --git a/custom_components/bluetti_bt/bluetti_bt_lib/devices/ep600.py b/custom_components/bluetti_bt/bluetti_bt_lib/devices/ep600.py index bfbc861..c59485b 100644 --- a/custom_components/bluetti_bt/bluetti_bt_lib/devices/ep600.py +++ b/custom_components/bluetti_bt/bluetti_bt_lib/devices/ep600.py @@ -79,10 +79,6 @@ class EP600(ProtocolV2Device): self.struct.add_version_field("safety_module_version", 6181) # internal self.struct.add_version_field("high_voltage_module_version", 6184) # internal - # @property - # def pack_num_max(self): - # return 16 - @property def polling_commands(self) -> List[ReadHoldingRegisters]: return super().polling_commands + [ @@ -105,10 +101,3 @@ class EP600(ProtocolV2Device): ReadHoldingRegisters(156, 1), ReadHoldingRegisters(158, 1), ] - - # @property - # def pack_polling_commands(self) -> List[ReadHoldingRegisters]: - # return super().pack_polling_commands + [ - # ReadHoldingRegisters(6101, 10), - # ReadHoldingRegisters(6175, 12), - # ] diff --git a/custom_components/bluetti_bt/manifest.json b/custom_components/bluetti_bt/manifest.json index f261fe9..0ed9d77 100644 --- a/custom_components/bluetti_bt/manifest.json +++ b/custom_components/bluetti_bt/manifest.json @@ -22,5 +22,5 @@ "iot_class": "local_polling", "issue_tracker": "https://github.com/Patrick762/hassio-bluetti-bt/issues", "requirements": [], - "version": "0.0.20" + "version": "0.0.21" } diff --git a/custom_components/bluetti_bt/sensor.py b/custom_components/bluetti_bt/sensor.py index d024a38..9390b8e 100644 --- a/custom_components/bluetti_bt/sensor.py +++ b/custom_components/bluetti_bt/sensor.py @@ -175,10 +175,9 @@ class BluettiSensor(CoordinatorEntity, SensorEntity): if ( self._options is not None and isinstance(response_data, Enum) - and response_data.value < len(self._options) ): # Enum - self._attr_native_value = self._options[response_data.value] + self._attr_native_value = response_data.name else: # Numeric self._attr_native_value = response_data