From 12cd2719d211823c4e87b862d8befedfea1fa1c7 Mon Sep 17 00:00:00 2001 From: Patrick762 Date: Tue, 1 Aug 2023 20:37:52 +0200 Subject: [PATCH 1/2] added dummy device class to append new fields --- custom_components/bluetti_bt/coordinator.py | 44 ++++++++++++++++++++- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/custom_components/bluetti_bt/coordinator.py b/custom_components/bluetti_bt/coordinator.py index e57aeca..c743ecd 100644 --- a/custom_components/bluetti_bt/coordinator.py +++ b/custom_components/bluetti_bt/coordinator.py @@ -1,6 +1,7 @@ """Coordinator for Bluetti integration.""" from __future__ import annotations +from typing import List import asyncio from datetime import timedelta @@ -23,10 +24,46 @@ from bluetti_mqtt.bluetooth import ( ParseError, build_device, ) +from bluetti_mqtt.core.devices.bluetti_device import BluettiDevice +from bluetti_mqtt.core.commands import ReadHoldingRegisters _LOGGER = logging.getLogger(__name__) +class DummyDevice(BluettiDevice): + """Dummy device. + + 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 + super().__init__(device.address, device.type, device.sn) + self._parent = device + + @property + def polling_commands(self) -> List[ReadHoldingRegisters]: + return self._parent.polling_commands + + @property + def pack_polling_commands(self) -> List[ReadHoldingRegisters]: + return self._parent.pack_logging_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.""" @@ -42,7 +79,10 @@ class PollingCoordinator(DataUpdateCoordinator): self.notify_future = None self.current_command = None self.notify_response = bytearray() - self.bluetti_device = build_device(address, device_name) + bluetti_device = build_device(address, device_name) + + # Add or modify device fields + self.bluetti_device = DummyDevice(bluetti_device) async def _async_update_data(self): """Fetch data from API endpoint. @@ -99,7 +139,7 @@ class PollingCoordinator(DataUpdateCoordinator): command.starting_address, body ) - self.logger.debug("Parsed data: %s", parsed) + self.logger.error("Parsed data: %s", parsed) parsed_data.update(parsed) except TimeoutError: From cc7891ed6a7c8c2d6af630a7e029f901fe54dd44 Mon Sep 17 00:00:00 2001 From: Patrick762 Date: Tue, 1 Aug 2023 21:20:02 +0200 Subject: [PATCH 2/2] added more fields --- README.md | 1 + custom_components/bluetti_bt/binary_sensor.py | 13 ++++++++--- custom_components/bluetti_bt/const.py | 22 ++++++++++++++++++ custom_components/bluetti_bt/coordinator.py | 11 ++++++++- custom_components/bluetti_bt/sensor.py | 23 +++++++++++-------- 5 files changed, 57 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 0be335a..e39bf62 100644 --- a/README.md +++ b/README.md @@ -22,3 +22,4 @@ Based on [bluetti_mqtt](https://github.com/warhammerkid/bluetti_mqtt). ### 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)) +excluding battery pack fields. diff --git a/custom_components/bluetti_bt/binary_sensor.py b/custom_components/bluetti_bt/binary_sensor.py index 58e5622..b03f6fe 100644 --- a/custom_components/bluetti_bt/binary_sensor.py +++ b/custom_components/bluetti_bt/binary_sensor.py @@ -20,10 +20,14 @@ from homeassistant.helpers.update_coordinator import ( ) from bluetti_mqtt.bluetooth import build_device -from bluetti_mqtt.mqtt_client import NORMAL_DEVICE_FIELDS, MqttFieldType +from bluetti_mqtt.mqtt_client import ( + NORMAL_DEVICE_FIELDS, + DC_INPUT_FIELDS, + MqttFieldType, +) from . import device_info as dev_info, get_unique_id -from .const import DOMAIN +from .const import DOMAIN, ADDITIONAL_DEVICE_FIELDS from .coordinator import PollingCoordinator _LOGGER = logging.getLogger(__name__) @@ -47,7 +51,10 @@ async def async_setup_entry( bluetti_device = build_device(address, device_name) sensors_to_add = [] - for field_key, field_config in NORMAL_DEVICE_FIELDS.items(): + all_fields = NORMAL_DEVICE_FIELDS + all_fields.update(DC_INPUT_FIELDS) + all_fields.update(ADDITIONAL_DEVICE_FIELDS) + for field_key, field_config in all_fields.items(): if bluetti_device.has_field(field_key): if field_config.type == MqttFieldType.BOOL: category = None diff --git a/custom_components/bluetti_bt/const.py b/custom_components/bluetti_bt/const.py index f25090c..008cc6d 100644 --- a/custom_components/bluetti_bt/const.py +++ b/custom_components/bluetti_bt/const.py @@ -1,6 +1,28 @@ """Constants for the Bluetti BT integration.""" +from bluetti_mqtt.mqtt_client import MqttFieldConfig, MqttFieldType + DOMAIN = "bluetti_bt" MANUFACTURER = "Bluetti" CONF_OPTIONS = "options" + +DIAGNOSTIC_FIELDS = [ + "bcu_version", + "safety_module_version", +] + +ADDITIONAL_DEVICE_FIELDS = { + "bcu_version": MqttFieldConfig( + type=MqttFieldType.NUMERIC, + setter=False, + advanced=False, + home_assistant_extra={"name": "BCU Version"}, + ), + "safety_module_version": MqttFieldConfig( + type=MqttFieldType.NUMERIC, + setter=False, + advanced=False, + home_assistant_extra={"name": "Safety Module Version"}, + ), +} diff --git a/custom_components/bluetti_bt/coordinator.py b/custom_components/bluetti_bt/coordinator.py index c743ecd..d90d02e 100644 --- a/custom_components/bluetti_bt/coordinator.py +++ b/custom_components/bluetti_bt/coordinator.py @@ -31,7 +31,7 @@ _LOGGER = logging.getLogger(__name__) class DummyDevice(BluettiDevice): - """Dummy device. + """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 @@ -45,6 +45,15 @@ class DummyDevice(BluettiDevice): @property def polling_commands(self) -> List[ReadHoldingRegisters]: + if self.type == "EP600": + return [ + ReadHoldingRegisters(100, 62), + ReadHoldingRegisters(2022, 6), + ReadHoldingRegisters(6101, 7), + ReadHoldingRegisters(6175, 2), + ReadHoldingRegisters(6181, 2), + ] + return self._parent.polling_commands @property diff --git a/custom_components/bluetti_bt/sensor.py b/custom_components/bluetti_bt/sensor.py index e72dcde..8fb2d8e 100644 --- a/custom_components/bluetti_bt/sensor.py +++ b/custom_components/bluetti_bt/sensor.py @@ -23,10 +23,14 @@ from homeassistant.helpers.update_coordinator import ( ) from bluetti_mqtt.bluetooth import build_device -from bluetti_mqtt.mqtt_client import NORMAL_DEVICE_FIELDS, MqttFieldType +from bluetti_mqtt.mqtt_client import ( + NORMAL_DEVICE_FIELDS, + DC_INPUT_FIELDS, + MqttFieldType, +) from . import device_info as dev_info, get_unique_id -from .const import DOMAIN, CONF_OPTIONS +from .const import DOMAIN, CONF_OPTIONS, DIAGNOSTIC_FIELDS, ADDITIONAL_DEVICE_FIELDS from .coordinator import PollingCoordinator _LOGGER = logging.getLogger(__name__) @@ -50,10 +54,13 @@ async def async_setup_entry( bluetti_device = build_device(address, device_name) sensors_to_add = [] - for field_key, field_config in NORMAL_DEVICE_FIELDS.items(): + all_fields = NORMAL_DEVICE_FIELDS + all_fields.update(DC_INPUT_FIELDS) + all_fields.update(ADDITIONAL_DEVICE_FIELDS) + for field_key, field_config in all_fields.items(): if bluetti_device.has_field(field_key): category = None - if field_config.setter is True: + if field_config.setter is True or field_key in DIAGNOSTIC_FIELDS: category = EntityCategory.DIAGNOSTIC if field_config.type == MqttFieldType.NUMERIC: sensors_to_add.append( @@ -63,11 +70,9 @@ async def async_setup_entry( address, field_key, field_config.home_assistant_extra.get(CONF_NAME, ""), - field_config.home_assistant_extra.get( - CONF_UNIT_OF_MEASUREMENT, "" - ), - field_config.home_assistant_extra.get(CONF_DEVICE_CLASS, ""), - field_config.home_assistant_extra.get(CONF_STATE_CLASS, ""), + field_config.home_assistant_extra.get(CONF_UNIT_OF_MEASUREMENT), + field_config.home_assistant_extra.get(CONF_DEVICE_CLASS), + field_config.home_assistant_extra.get(CONF_STATE_CLASS), category=category, ) )