From aa1c3ef4259a7a0cdd9f2c36489fcfd6cb04221d Mon Sep 17 00:00:00 2001 From: Patrick762 Date: Tue, 9 Jan 2024 20:35:49 +0100 Subject: [PATCH 1/7] Update issue templates --- .github/ISSUE_TEMPLATE/bug_report.md | 38 ++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..264aa98 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,38 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: bug +assignees: Patrick762 + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**Device** +[ ] AC60 +[ ] AC200M +[ ] AC300 +[ ] AC500 +[ ] EB3A +[ ] EP500 +[ ] EP500P +[ ] EP600 + +**Bluetooth connection** +[ ] USB Bluetooth dongle +[ ] ESPHome Bluetooth proxy + +**Integration settings (modify this if you changed those)** +[ ] Use controls +[ ] Persistent connection +Polling interval: 20 +Polling timeout: 45 +Max retries: 5 + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Additional context** +Add any other context like logs here. From 11716084c9e443e4fe6fe4348958b3315bea8c12 Mon Sep 17 00:00:00 2001 From: Patrick762 Date: Tue, 9 Jan 2024 20:39:17 +0100 Subject: [PATCH 2/7] Update issue templates --- .github/ISSUE_TEMPLATE/bug_report.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 264aa98..d5d28e7 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -11,6 +11,8 @@ assignees: Patrick762 A clear and concise description of what the bug is. **Device** +Add a "x" into the brackets to select + [ ] AC60 [ ] AC200M [ ] AC300 @@ -21,6 +23,8 @@ A clear and concise description of what the bug is. [ ] EP600 **Bluetooth connection** +Add a "x" into the brackets to select + [ ] USB Bluetooth dongle [ ] ESPHome Bluetooth proxy From dcc6131d02b5e808ec0571d22bd373df7beba2a5 Mon Sep 17 00:00:00 2001 From: Patrick762 Date: Tue, 9 Jan 2024 20:49:56 +0100 Subject: [PATCH 3/7] Create bug_report.yaml --- .github/ISSUE_TEMPLATE/bug_report.yaml | 70 ++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.yaml diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml new file mode 100644 index 0000000..0e2112b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yaml @@ -0,0 +1,70 @@ +name: Bug Report +description: File a bug report +title: "[Bug]: " +labels: ["bug"] +assignees: + - octocat +body: + - type: textarea + id: what-happened + attributes: + label: What happened? + description: Also tell us, what did you expect to happen? + placeholder: Tell us what you see! + value: "" + validations: + required: true + - type: dropdown + id: version + attributes: + label: Version + description: What version of our software are you running? + options: + - 0.0.11 + - 0.0.10 + - 0.0.9 + default: 0 + validations: + required: true + - type: dropdown + id: device + attributes: + label: What device are you seeing the problem on? + multiple: true + options: + - AC60 + - AC200M + - AC300 + - AC500 + - EB3A + - EP500 + - EP500P + - EP900 + - type: dropdown + id: bluetooth + attributes: + label: What bluetooth connection are you using? + multiple: false + options: + - USB dongle + - ESPHome bluetooth proxy + - type: dropdown + id: options-changed + attributes: + label: Have you changed the integration settings? + multiple: false + options: + - No + - Yes (Please write down the changed settings in the next step) + - type: textarea + id: options-details + attributes: + label: Integration settings (if you changed them) + description: Please use one line per option + render: text + - type: textarea + id: logs + attributes: + label: Relevant log output + description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks. + render: shell From 0420511d90121b16861bd795b3095233e9ba008b Mon Sep 17 00:00:00 2001 From: Patrick762 Date: Tue, 9 Jan 2024 20:53:24 +0100 Subject: [PATCH 4/7] Update and rename bug_report.md to bug_report_template.md --- .../{bug_report.md => bug_report_template.md} | 38 ++++++++++--------- 1 file changed, 20 insertions(+), 18 deletions(-) rename .github/ISSUE_TEMPLATE/{bug_report.md => bug_report_template.md} (53%) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report_template.md similarity index 53% rename from .github/ISSUE_TEMPLATE/bug_report.md rename to .github/ISSUE_TEMPLATE/bug_report_template.md index d5d28e7..0ecc125 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report_template.md @@ -1,5 +1,5 @@ --- -name: Bug report +name: Bug report Markdown about: Create a report to help us improve title: '' labels: bug @@ -7,36 +7,38 @@ assignees: Patrick762 --- -**Describe the bug** +### Describe the bug A clear and concise description of what the bug is. -**Device** +### Device Add a "x" into the brackets to select -[ ] AC60 -[ ] AC200M -[ ] AC300 -[ ] AC500 -[ ] EB3A -[ ] EP500 -[ ] EP500P -[ ] EP600 +- [ ] AC60 +- [ ] AC200M +- [ ] AC300 +- [ ] AC500 +- [ ] EB3A +- [ ] EP500 +- [ ] EP500P +- [ ] EP600 -**Bluetooth connection** +### Bluetooth connection Add a "x" into the brackets to select -[ ] USB Bluetooth dongle -[ ] ESPHome Bluetooth proxy +- [ ] USB Bluetooth dongle +- [ ] ESPHome Bluetooth proxy -**Integration settings (modify this if you changed those)** -[ ] Use controls -[ ] Persistent connection +### Integration settings (modify this if you changed those) +- [ ] Use controls +- [ ] Persistent connection Polling interval: 20 Polling timeout: 45 Max retries: 5 -**Screenshots** +### Screenshots + If applicable, add screenshots to help explain your problem. **Additional context** + Add any other context like logs here. From 9c7e5968bbff5040c86e2b3c78734ee1a654f125 Mon Sep 17 00:00:00 2001 From: Patrick762 Date: Tue, 9 Jan 2024 20:56:27 +0100 Subject: [PATCH 5/7] Update bug_report.yaml --- .github/ISSUE_TEMPLATE/bug_report.yaml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml index 0e2112b..b1196a2 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yaml +++ b/.github/ISSUE_TEMPLATE/bug_report.yaml @@ -11,7 +11,7 @@ body: label: What happened? description: Also tell us, what did you expect to happen? placeholder: Tell us what you see! - value: "" + value: "An exception appeared" validations: required: true - type: dropdown @@ -40,6 +40,8 @@ body: - EP500 - EP500P - EP900 + validations: + required: true - type: dropdown id: bluetooth attributes: @@ -48,6 +50,8 @@ body: options: - USB dongle - ESPHome bluetooth proxy + validations: + required: true - type: dropdown id: options-changed attributes: @@ -56,6 +60,8 @@ body: options: - No - Yes (Please write down the changed settings in the next step) + validations: + required: true - type: textarea id: options-details attributes: From e8b9db9a42faf595fa23316efcf250870e4ca8b2 Mon Sep 17 00:00:00 2001 From: Patrick762 Date: Tue, 9 Jan 2024 20:57:42 +0100 Subject: [PATCH 6/7] Delete old issue template --- .github/ISSUE_TEMPLATE/bug_report_template.md | 44 ------------------- 1 file changed, 44 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/bug_report_template.md diff --git a/.github/ISSUE_TEMPLATE/bug_report_template.md b/.github/ISSUE_TEMPLATE/bug_report_template.md deleted file mode 100644 index 0ecc125..0000000 --- a/.github/ISSUE_TEMPLATE/bug_report_template.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -name: Bug report Markdown -about: Create a report to help us improve -title: '' -labels: bug -assignees: Patrick762 - ---- - -### Describe the bug -A clear and concise description of what the bug is. - -### Device -Add a "x" into the brackets to select - -- [ ] AC60 -- [ ] AC200M -- [ ] AC300 -- [ ] AC500 -- [ ] EB3A -- [ ] EP500 -- [ ] EP500P -- [ ] EP600 - -### Bluetooth connection -Add a "x" into the brackets to select - -- [ ] USB Bluetooth dongle -- [ ] ESPHome Bluetooth proxy - -### Integration settings (modify this if you changed those) -- [ ] Use controls -- [ ] Persistent connection -Polling interval: 20 -Polling timeout: 45 -Max retries: 5 - -### Screenshots - -If applicable, add screenshots to help explain your problem. - -**Additional context** - -Add any other context like logs here. From 8eb09a32f00355665e98764e14e4141a3182f768 Mon Sep 17 00:00:00 2001 From: Patrick762 Date: Sat, 3 Feb 2024 17:57:49 +0100 Subject: [PATCH 7/7] added ep700, replaced dummy device --- README.md | 1 + custom_components/bluetti_bt/__init__.py | 16 +++ custom_components/bluetti_bt/binary_sensor.py | 6 +- custom_components/bluetti_bt/const.py | 4 + custom_components/bluetti_bt/coordinator.py | 100 +--------------- custom_components/bluetti_bt/devices/ep600.py | 113 ++++++++++++++++++ custom_components/bluetti_bt/devices/ep700.py | 67 +++++++++++ custom_components/bluetti_bt/manifest.json | 5 +- custom_components/bluetti_bt/sensor.py | 6 +- custom_components/bluetti_bt/switch.py | 6 +- 10 files changed, 212 insertions(+), 112 deletions(-) create mode 100644 custom_components/bluetti_bt/devices/ep600.py create mode 100644 custom_components/bluetti_bt/devices/ep700.py diff --git a/README.md b/README.md index ce86d3d..d02c746 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,7 @@ After the installation, you can use this button to install the integration: - EP500 - EP500P - EP600 (tested) +- EP700 (beta, untested) ### Available sensors: All sensors which are available in bluetti_mqtt (Based on [this file](https://github.com/warhammerkid/bluetti_mqtt/blob/main/bluetti_mqtt/mqtt_client.py)). diff --git a/custom_components/bluetti_bt/__init__.py b/custom_components/bluetti_bt/__init__.py index 8b69d58..5aeee6b 100644 --- a/custom_components/bluetti_bt/__init__.py +++ b/custom_components/bluetti_bt/__init__.py @@ -12,6 +12,8 @@ from homeassistant.core import HomeAssistant from homeassistant.helpers.entity import DeviceInfo from homeassistant.exceptions import ConfigEntryNotReady +from bluetti_mqtt.bluetooth import build_device as orig_build_device + from .const import ( CONF_MAX_RETRIES, CONF_PERSISTENT_CONN, @@ -20,10 +22,13 @@ from .const import ( CONF_USE_CONTROLS, DATA_COORDINATOR, DATA_POLLING_RUNNING, + DEVICE_NAME_RE, DOMAIN, MANUFACTURER, ) from .coordinator import PollingCoordinator +from .devices.ep600 import EP600 +from .devices.ep700 import EP700 PLATFORMS: [Platform] = [Platform.BINARY_SENSOR, Platform.SENSOR] _LOGGER = logging.getLogger(__name__) @@ -102,4 +107,15 @@ def get_type_by_bt_name(bt_name: str): dev_type = "EP500" elif bt_name.startswith("EP600"): dev_type = "EP600" + elif bt_name.startswith("EP700"): + dev_type = "EP700" return dev_type + +def build_device(address: str, name: str): + match = DEVICE_NAME_RE.match(name) + if match[1] == 'EP700': + return EP700(address, match[2]) + elif match[1] == 'EP600': + return EP600(address, match[2]) + else: + return orig_build_device(address, name) diff --git a/custom_components/bluetti_bt/binary_sensor.py b/custom_components/bluetti_bt/binary_sensor.py index a52a269..a508f31 100644 --- a/custom_components/bluetti_bt/binary_sensor.py +++ b/custom_components/bluetti_bt/binary_sensor.py @@ -18,16 +18,15 @@ from homeassistant.helpers.update_coordinator import ( CoordinatorEntity, ) -from bluetti_mqtt.bluetooth import build_device from bluetti_mqtt.mqtt_client import ( NORMAL_DEVICE_FIELDS, DC_INPUT_FIELDS, MqttFieldType, ) -from . import device_info as dev_info, get_unique_id +from . import device_info as dev_info, get_unique_id, build_device from .const import DATA_COORDINATOR, DOMAIN, ADDITIONAL_DEVICE_FIELDS -from .coordinator import PollingCoordinator, DummyDevice +from .coordinator import PollingCoordinator from .utils import unique_id_loggable _LOGGER = logging.getLogger(__name__) @@ -49,7 +48,6 @@ async def async_setup_entry( # Add sensors according to device_info bluetti_device = build_device(address, device_name) - bluetti_device = DummyDevice(bluetti_device) sensors_to_add = [] all_fields = NORMAL_DEVICE_FIELDS diff --git a/custom_components/bluetti_bt/const.py b/custom_components/bluetti_bt/const.py index 75c2406..e25a033 100644 --- a/custom_components/bluetti_bt/const.py +++ b/custom_components/bluetti_bt/const.py @@ -1,5 +1,7 @@ """Constants for the Bluetti BT integration.""" +import re + from bluetti_mqtt.mqtt_client import MqttFieldConfig, MqttFieldType DOMAIN = "bluetti_bt" @@ -15,6 +17,8 @@ CONF_MAX_RETRIES = "max_retries" DATA_COORDINATOR = "coordinator" DATA_POLLING_RUNNING = "polling_running" +DEVICE_NAME_RE = re.compile(r'^(AC200M|AC300|AC500|AC60|EP500P|EP500|EP600|EP700|EB3A)(\d+)$') + CONTROL_FIELDS = [ "ac_output_on", "dc_output_on", diff --git a/custom_components/bluetti_bt/coordinator.py b/custom_components/bluetti_bt/coordinator.py index 8239c64..304e1e7 100644 --- a/custom_components/bluetti_bt/coordinator.py +++ b/custom_components/bluetti_bt/coordinator.py @@ -21,110 +21,17 @@ from bluetti_mqtt.bluetooth import ( BadConnectionError, ModbusError, ParseError, - build_device, ) from bluetti_mqtt.core.devices.bluetti_device import BluettiDevice from bluetti_mqtt.core.commands import ReadHoldingRegisters +from . import build_device from .const import DATA_POLLING_RUNNING, DOMAIN from .utils import mac_loggable _LOGGER = logging.getLogger(__name__) -class DummyDevice(BluettiDevice): - """Dummy device used to add more fields to existing devices. - - Changes made here are only temporary and should also be - contributed to https://github.com/warhammerkid/bluetti_mqtt - """ - - def __init__(self, device: BluettiDevice): - """Init dummy device with real device.""" - self.struct = device.struct - - if device.type == "EP600": - # 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__(device.address, device.type, device.sn) - self._parent = device - - @property - def pack_num_max(self): - return self._parent.pack_num_max - - @property - def polling_commands(self) -> List[ReadHoldingRegisters]: - if self.type == "EP600": - 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), - ] - - return self._parent.polling_commands - - @property - def pack_polling_commands(self) -> List[ReadHoldingRegisters]: - if self.type == "EP600": - return [] - return self._parent.pack_polling_commands - - @property - def logging_commands(self) -> List[ReadHoldingRegisters]: - return self._parent.logging_commands - - @property - def pack_logging_commands(self) -> List[ReadHoldingRegisters]: - return self._parent.pack_logging_commands - - @property - def writable_ranges(self) -> List[range]: - return self._parent.writable_ranges - - class PollingCoordinator(DataUpdateCoordinator): """Polling coordinator.""" @@ -150,14 +57,11 @@ class PollingCoordinator(DataUpdateCoordinator): self.notify_future = None self.current_command = None self.notify_response = bytearray() - bluetti_device = build_device(address, device_name) + self.bluetti_device = build_device(address, device_name) self.persistent_conn = persistent_conn self.polling_timeout = polling_timeout self.max_retries = max_retries - # Add or modify device fields - self.bluetti_device = DummyDevice(bluetti_device) - # Create client self.logger.debug("Creating client") device = bluetooth.async_ble_device_from_address(hass, address) diff --git a/custom_components/bluetti_bt/devices/ep600.py b/custom_components/bluetti_bt/devices/ep600.py new file mode 100644 index 0000000..3ea91a7 --- /dev/null +++ b/custom_components/bluetti_bt/devices/ep600.py @@ -0,0 +1,113 @@ +"""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/devices/ep700.py b/custom_components/bluetti_bt/devices/ep700.py new file mode 100644 index 0000000..b6ae3f0 --- /dev/null +++ b/custom_components/bluetti_bt/devices/ep700.py @@ -0,0 +1,67 @@ +"""EP700 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 EP700(BluettiDevice): + def __init__(self, address: str, sn: str): + self.struct = DeviceStruct() + + # TODO has to be tested + + 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) + 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) + 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) + + super().__init__(address, 'EP700', sn) + + @property + def polling_commands(self) -> List[ReadHoldingRegisters]: + return [ + ReadHoldingRegisters(100, 62), + ReadHoldingRegisters(2022, 2), + ] + + @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/manifest.json b/custom_components/bluetti_bt/manifest.json index da4e654..81ad886 100644 --- a/custom_components/bluetti_bt/manifest.json +++ b/custom_components/bluetti_bt/manifest.json @@ -8,7 +8,8 @@ { "local_name": "AC60*" }, { "local_name": "EB3A*" }, { "local_name": "EP500*" }, - { "local_name": "EP600*" } + { "local_name": "EP600*" }, + { "local_name": "EP700*" } ], "codeowners": ["@Patrick762"], "config_flow": true, @@ -18,5 +19,5 @@ "iot_class": "local_polling", "issue_tracker": "https://github.com/Patrick762/hassio-bluetti-bt/issues", "requirements": ["bluetti_mqtt==0.15.0"], - "version": "0.0.11" + "version": "0.0.12" } diff --git a/custom_components/bluetti_bt/sensor.py b/custom_components/bluetti_bt/sensor.py index 428800e..5d16f15 100644 --- a/custom_components/bluetti_bt/sensor.py +++ b/custom_components/bluetti_bt/sensor.py @@ -22,7 +22,6 @@ from homeassistant.helpers.update_coordinator import ( CoordinatorEntity, ) -from bluetti_mqtt.bluetooth import build_device from bluetti_mqtt.mqtt_client import ( NORMAL_DEVICE_FIELDS, DC_INPUT_FIELDS, @@ -30,9 +29,9 @@ from bluetti_mqtt.mqtt_client import ( battery_pack_fields, ) -from . import device_info as dev_info, get_unique_id +from . import device_info as dev_info, get_unique_id, build_device from .const import DATA_COORDINATOR, DOMAIN, CONF_OPTIONS, DIAGNOSTIC_FIELDS, ADDITIONAL_DEVICE_FIELDS -from .coordinator import PollingCoordinator, DummyDevice +from .coordinator import PollingCoordinator from .utils import unique_id_loggable _LOGGER = logging.getLogger(__name__) @@ -54,7 +53,6 @@ async def async_setup_entry( # Add sensors according to device_info bluetti_device = build_device(address, device_name) - bluetti_device = DummyDevice(bluetti_device) sensors_to_add = [] all_fields = NORMAL_DEVICE_FIELDS diff --git a/custom_components/bluetti_bt/switch.py b/custom_components/bluetti_bt/switch.py index 62280e4..95fa189 100644 --- a/custom_components/bluetti_bt/switch.py +++ b/custom_components/bluetti_bt/switch.py @@ -23,7 +23,6 @@ from homeassistant.helpers.update_coordinator import ( CoordinatorEntity, ) -from bluetti_mqtt.bluetooth import build_device from bluetti_mqtt.bluetooth.client import BluetoothClient from bluetti_mqtt.core.devices.bluetti_device import BluettiDevice from bluetti_mqtt.mqtt_client import ( @@ -32,9 +31,9 @@ from bluetti_mqtt.mqtt_client import ( MqttFieldType, ) -from . import device_info as dev_info, get_unique_id +from . import device_info as dev_info, get_unique_id, build_device from .const import CONTROL_FIELDS, DATA_COORDINATOR, DOMAIN, ADDITIONAL_DEVICE_FIELDS -from .coordinator import PollingCoordinator, DummyDevice +from .coordinator import PollingCoordinator from .utils import mac_loggable, unique_id_loggable _LOGGER = logging.getLogger(__name__) @@ -56,7 +55,6 @@ async def async_setup_entry( # Add sensors according to device_info bluetti_device = build_device(address, device_name) - bluetti_device = DummyDevice(bluetti_device) sensors_to_add = [] all_fields = NORMAL_DEVICE_FIELDS