Merge pull request #104 from Patrick762/values-fix-2

Values and pack polling fix
This commit is contained in:
Patrick762 authored and GitHub committed 2024-05-31 17:02:07 +02:00
commit 5a762266c0
15 files changed
+71 -65

No files matched your search

@@ -36,7 +36,7 @@ async def async_setup_entry(
device_name = entry.data.get(CONF_NAME) device_name = entry.data.get(CONF_NAME)
address = entry.data.get(CONF_ADDRESS) address = entry.data.get(CONF_ADDRESS)
use_controls = entry.data.get(CONF_USE_CONTROLS) use_controls = entry.data.get(CONF_USE_CONTROLS, False)
if address is None: if address is None:
_LOGGER.error("Device has no address") _LOGGER.error("Device has no address")
@@ -52,12 +52,7 @@ async def async_setup_entry(
for field_key, field_config in all_fields.items(): for field_key, field_config in all_fields.items():
if bluetti_device.has_field(field_key): if bluetti_device.has_field(field_key):
if field_config.type == FieldType.BOOL: if field_config.type == FieldType.BOOL:
category = None
if field_config.setter is True: if field_config.setter is True:
category = EntityCategory.DIAGNOSTIC
# Ignore setters if controls enabled
if field_config.setter is True and use_controls is True:
continue continue
sensors_to_add.append( sensors_to_add.append(
@@ -67,7 +62,6 @@ async def async_setup_entry(
address, address,
field_key, field_key,
field_config.name, field_config.name,
category=category,
) )
) )
@@ -84,7 +78,6 @@ class BluettiBinarySensor(CoordinatorEntity, BinarySensorEntity):
address, address,
response_key: str, response_key: str,
name: str, name: str,
category: EntityCategory | None = None,
): ):
"""Init battery entity.""" """Init battery entity."""
super().__init__(coordinator) super().__init__(coordinator)
@@ -98,7 +91,6 @@ class BluettiBinarySensor(CoordinatorEntity, BinarySensorEntity):
self._attr_name = name self._attr_name = name
self._attr_available = False self._attr_available = False
self._attr_unique_id = get_unique_id(e_name) self._attr_unique_id = get_unique_id(e_name)
self._attr_entity_category = category
@property @property
def available(self) -> bool: def available(self) -> bool:
@@ -43,6 +43,11 @@ class BluettiDevice:
"""The address ranges that are writable""" """The address ranges that are writable"""
return [] return []
@property
def pack_num_field(self) -> List[ReadHoldingRegisters]:
"""The address 'range' of the pack num result. Matches pack_num_result"""
return []
def has_field(self, field: str): def has_field(self, field: str):
return any(f.name == field for f in self.struct.fields) return any(f.name == field for f in self.struct.fields)
@@ -56,3 +56,9 @@ class ProtocolV1Device(BluettiDevice):
@property @property
def writable_ranges(self) -> List[range]: def writable_ranges(self) -> List[range]:
return [range(3006, 3009)] return [range(3006, 3009)]
@property
def pack_num_field(self) -> List[ReadHoldingRegisters]:
return [
ReadHoldingRegisters(96, 1),
]
@@ -97,20 +97,20 @@ class DeviceReader:
_LOGGER.warning("Got a parse exception") _LOGGER.warning("Got a parse exception")
# Execute pack polling commands # Execute pack polling commands
if len(pack_commands) > 0: if len(pack_commands) > 0 and len(self.bluetti_device.pack_num_field) == 1:
_LOGGER.debug("Polling battery packs") _LOGGER.debug("Polling battery packs")
for pack in range(1, self.bluetti_device.pack_num_max + 1): for pack in range(1, self.bluetti_device.pack_num_max + 1):
_LOGGER.debug("Setting pack_num to %i", pack)
# Set current pack number # Set current pack number
await self._async_send_command( command = self.bluetti_device.build_setter_command(
self.bluetti_device.build_setter_command(
"pack_num", pack "pack_num", pack
) )
body = command.parse_response(
await self._async_send_command(command)
) )
_LOGGER.debug("Raw data set: %s", body)
# We need to wait after switching packs for the data to be available # b'\x00\x02' b'\x00\x03' here (seems like result)
await asyncio.sleep(5)
pack_ok = False
for command in pack_commands: for command in pack_commands:
# Request & parse result for each pack # Request & parse result for each pack
@@ -123,20 +123,6 @@ class DeviceReader:
) )
_LOGGER.debug("Parsed data: %s", parsed) _LOGGER.debug("Parsed data: %s", parsed)
if not pack_ok: # Only check this once
pack_number = parsed.get("pack_num")
if (
not isinstance(pack_number, int)
or pack_number != pack
):
_LOGGER.debug(
"Parsed pack_num(%s) does not match expected '%s'",
pack_number,
pack,
)
continue
pack_ok = True
for key, value in parsed.items(): for key, value in parsed.items():
parsed_data.update({key + str(pack): value}) parsed_data.update({key + str(pack): value})
@@ -187,9 +173,9 @@ class DeviceReader:
return cast(bytes, res) return cast(bytes, res)
except TimeoutError: except TimeoutError:
_LOGGER.warning("Polling single command timed out") _LOGGER.debug("Polling single command timed out")
except ModbusError as err: except ModbusError as err:
_LOGGER.warning( _LOGGER.debug(
"Got an invalid request error for %s: %s", "Got an invalid request error for %s: %s",
command, command,
err, err,
@@ -24,7 +24,7 @@ class AC200L(ProtocolV1Device):
# Battery packs # Battery packs
self.struct.add_uint_field("pack_num_max", 91) # internal self.struct.add_uint_field("pack_num_max", 91) # internal
self.struct.add_decimal_field("total_battery_voltage", 92, 1) self.struct.add_decimal_field("total_battery_voltage", 92, 1)
self.struct.add_uint_field("pack_num", 96) # internal self.struct.add_uint_field("pack_num_result", 96) # internal
self.struct.add_decimal_field("pack_voltage", 98, 2) # Full pack voltage self.struct.add_decimal_field("pack_voltage", 98, 2) # Full pack voltage
self.struct.add_uint_field("pack_battery_percent", 99) self.struct.add_uint_field("pack_battery_percent", 99)
self.struct.add_decimal_array_field("cell_voltages", 105, 16, 2) # internal self.struct.add_decimal_array_field("cell_voltages", 105, 16, 2) # internal
@@ -42,6 +42,7 @@ class AC200L(ProtocolV1Device):
return super().polling_commands + [ return super().polling_commands + [
ReadHoldingRegisters(70, 5), ReadHoldingRegisters(70, 5),
ReadHoldingRegisters(86, 3), ReadHoldingRegisters(86, 3),
ReadHoldingRegisters(92, 1),
ReadHoldingRegisters(3060, 2), ReadHoldingRegisters(3060, 2),
] ]
@@ -24,7 +24,7 @@ class AC200M(ProtocolV1Device):
# Battery packs # Battery packs
self.struct.add_uint_field("pack_num_max", 91) # internal self.struct.add_uint_field("pack_num_max", 91) # internal
self.struct.add_decimal_field("total_battery_voltage", 92, 1) self.struct.add_decimal_field("total_battery_voltage", 92, 1)
self.struct.add_uint_field("pack_num", 96) # internal self.struct.add_uint_field("pack_num_result", 96) # internal
self.struct.add_decimal_field("pack_voltage", 98, 2) # Full pack voltage self.struct.add_decimal_field("pack_voltage", 98, 2) # Full pack voltage
self.struct.add_uint_field("pack_battery_percent", 99) self.struct.add_uint_field("pack_battery_percent", 99)
self.struct.add_decimal_array_field("cell_voltages", 105, 16, 2) # internal self.struct.add_decimal_array_field("cell_voltages", 105, 16, 2) # internal
@@ -42,6 +42,7 @@ class AC200M(ProtocolV1Device):
return super().polling_commands + [ return super().polling_commands + [
ReadHoldingRegisters(70, 5), ReadHoldingRegisters(70, 5),
ReadHoldingRegisters(86, 3), ReadHoldingRegisters(86, 3),
ReadHoldingRegisters(92, 1),
ReadHoldingRegisters(3060, 2), ReadHoldingRegisters(3060, 2),
] ]
@@ -15,22 +15,22 @@ class AC300(ProtocolV1Device):
self.struct.add_enum_field("ac_output_mode", 70, OutputMode) self.struct.add_enum_field("ac_output_mode", 70, OutputMode)
self.struct.add_decimal_field("internal_ac_voltage", 71, 1) self.struct.add_decimal_field("internal_ac_voltage", 71, 1)
self.struct.add_decimal_field("internal_current_one", 72, 1) self.struct.add_decimal_field("internal_current_one", 72, 1)
self.struct.add_uint_field("internal_power_one", 73) self.struct.add_int_field("internal_power_one", 73)
self.struct.add_decimal_field("internal_ac_frequency", 74, 2) self.struct.add_decimal_field("internal_ac_frequency", 74, 2)
self.struct.add_decimal_field("internal_current_two", 75, 1) self.struct.add_decimal_field("internal_current_two", 75, 1)
self.struct.add_uint_field("internal_power_two", 76) self.struct.add_int_field("internal_power_two", 76)
self.struct.add_decimal_field("ac_input_voltage", 77, 1) 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_decimal_field("internal_current_three", 78, 1, (0, 100))
self.struct.add_uint_field("internal_power_three", 79) self.struct.add_int_field("internal_power_three", 79)
self.struct.add_decimal_field("ac_input_frequency", 80, 2) self.struct.add_decimal_field("ac_input_frequency", 80, 2)
self.struct.add_uint_field("internal_dc_input_voltage", 86, scale=.1) self.struct.add_uint_field("pv_input_voltage1", 86, multiplier=.1)
self.struct.add_decimal_field("internal_dc_input_power", 87, 1) self.struct.add_decimal_field("pv_input_power1", 87, 1, multiplier=10)
self.struct.add_decimal_field("internal_dc_input_current", 88, 2) self.struct.add_decimal_field("pv_input_current1", 88, 2, multiplier=10)
# Battery packs # Battery packs
self.struct.add_uint_field("pack_num_max", 91) # internal self.struct.add_uint_field("pack_num_max", 91) # internal
self.struct.add_decimal_field("total_battery_voltage", 92, 1) self.struct.add_decimal_field("total_battery_voltage", 92, 1)
self.struct.add_uint_field("pack_num", 96) # internal self.struct.add_uint_field("pack_num_result", 96) # internal
self.struct.add_decimal_field("pack_voltage", 98, 2) # Full pack voltage self.struct.add_decimal_field("pack_voltage", 98, 2) # Full pack voltage
self.struct.add_uint_field("pack_battery_percent", 99) self.struct.add_uint_field("pack_battery_percent", 99)
self.struct.add_decimal_array_field("cell_voltages", 105, 16, 2) # internal self.struct.add_decimal_array_field("cell_voltages", 105, 16, 2) # internal
@@ -57,6 +57,7 @@ class AC300(ProtocolV1Device):
return super().polling_commands + [ return super().polling_commands + [
ReadHoldingRegisters(70, 11), ReadHoldingRegisters(70, 11),
ReadHoldingRegisters(86, 3), ReadHoldingRegisters(86, 3),
ReadHoldingRegisters(92, 1),
ReadHoldingRegisters(3001, 1), ReadHoldingRegisters(3001, 1),
ReadHoldingRegisters(3004, 2), ReadHoldingRegisters(3004, 2),
ReadHoldingRegisters(3011, 1), ReadHoldingRegisters(3011, 1),
@@ -15,22 +15,22 @@ class AC500(ProtocolV1Device):
self.struct.add_enum_field("ac_output_mode", 70, OutputMode) self.struct.add_enum_field("ac_output_mode", 70, OutputMode)
self.struct.add_decimal_field("internal_ac_voltage", 71, 1) self.struct.add_decimal_field("internal_ac_voltage", 71, 1)
self.struct.add_decimal_field("internal_current_one", 72, 1) self.struct.add_decimal_field("internal_current_one", 72, 1)
self.struct.add_uint_field("internal_power_one", 73) self.struct.add_int_field("internal_power_one", 73)
self.struct.add_decimal_field("internal_ac_frequency", 74, 2) self.struct.add_decimal_field("internal_ac_frequency", 74, 2)
self.struct.add_decimal_field("internal_current_two", 75, 1) self.struct.add_decimal_field("internal_current_two", 75, 1)
self.struct.add_uint_field("internal_power_two", 76) self.struct.add_int_field("internal_power_two", 76)
self.struct.add_decimal_field("ac_input_voltage", 77, 1) 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_decimal_field("internal_current_three", 78, 1, (0, 100))
self.struct.add_uint_field("internal_power_three", 79) self.struct.add_int_field("internal_power_three", 79)
self.struct.add_decimal_field("ac_input_frequency", 80, 2) self.struct.add_decimal_field("ac_input_frequency", 80, 2)
self.struct.add_uint_field("internal_dc_input_voltage", 86, scale=.1) self.struct.add_uint_field("pv_input_voltage1", 86, multiplier=.1)
self.struct.add_decimal_field("internal_dc_input_power", 87, 1) self.struct.add_decimal_field("pv_input_power1", 87, 1, multiplier=10)
self.struct.add_decimal_field("internal_dc_input_current", 88, 2) self.struct.add_decimal_field("pv_input_current1", 88, 2, multiplier=10)
# Battery packs # Battery packs
self.struct.add_uint_field("pack_num_max", 91) # internal self.struct.add_uint_field("pack_num_max", 91) # internal
self.struct.add_decimal_field("total_battery_voltage", 92, 1) self.struct.add_decimal_field("total_battery_voltage", 92, 1)
self.struct.add_uint_field("pack_num", 96) # internal self.struct.add_uint_field("pack_num_result", 96) # internal
self.struct.add_decimal_field("pack_voltage", 98, 2) # Full pack voltage self.struct.add_decimal_field("pack_voltage", 98, 2) # Full pack voltage
self.struct.add_uint_field("pack_battery_percent", 99) self.struct.add_uint_field("pack_battery_percent", 99)
self.struct.add_decimal_array_field("cell_voltages", 105, 16, 2) # internal self.struct.add_decimal_array_field("cell_voltages", 105, 16, 2) # internal
@@ -56,6 +56,7 @@ class AC500(ProtocolV1Device):
return super().polling_commands + [ return super().polling_commands + [
ReadHoldingRegisters(70, 11), ReadHoldingRegisters(70, 11),
ReadHoldingRegisters(86, 3), ReadHoldingRegisters(86, 3),
ReadHoldingRegisters(92, 1),
ReadHoldingRegisters(3001, 1), ReadHoldingRegisters(3001, 1),
ReadHoldingRegisters(3004, 2), ReadHoldingRegisters(3004, 2),
ReadHoldingRegisters(3011, 1), ReadHoldingRegisters(3011, 1),
@@ -30,7 +30,7 @@ class EP500(ProtocolV1Device):
# Battery packs # Battery packs
self.struct.add_uint_field("pack_num_max", 91) # internal self.struct.add_uint_field("pack_num_max", 91) # internal
self.struct.add_decimal_field("total_battery_voltage", 92, 1) self.struct.add_decimal_field("total_battery_voltage", 92, 1)
self.struct.add_uint_field("pack_num", 96) # internal self.struct.add_uint_field("pack_num_result", 96) # internal
self.struct.add_decimal_field("pack_voltage", 98, 2) # Full pack voltage self.struct.add_decimal_field("pack_voltage", 98, 2) # Full pack voltage
self.struct.add_uint_field("pack_battery_percent", 99) self.struct.add_uint_field("pack_battery_percent", 99)
self.struct.add_decimal_array_field("cell_voltages", 105, 16, 2) # internal self.struct.add_decimal_array_field("cell_voltages", 105, 16, 2) # internal
@@ -52,6 +52,7 @@ class EP500(ProtocolV1Device):
return super().polling_commands + [ return super().polling_commands + [
ReadHoldingRegisters(70, 11), ReadHoldingRegisters(70, 11),
ReadHoldingRegisters(86, 3), ReadHoldingRegisters(86, 3),
ReadHoldingRegisters(92, 1),
ReadHoldingRegisters(3001, 1), ReadHoldingRegisters(3001, 1),
ReadHoldingRegisters(3004, 2), ReadHoldingRegisters(3004, 2),
ReadHoldingRegisters(3011, 1), ReadHoldingRegisters(3011, 1),
@@ -30,7 +30,7 @@ class EP500P(ProtocolV1Device):
# Battery packs # Battery packs
self.struct.add_uint_field("pack_num_max", 91) # internal self.struct.add_uint_field("pack_num_max", 91) # internal
self.struct.add_decimal_field("total_battery_voltage", 92, 1) self.struct.add_decimal_field("total_battery_voltage", 92, 1)
self.struct.add_uint_field("pack_num", 96) # internal self.struct.add_uint_field("pack_num_result", 96) # internal
self.struct.add_decimal_field("pack_voltage", 98, 2) # Full pack voltage self.struct.add_decimal_field("pack_voltage", 98, 2) # Full pack voltage
self.struct.add_uint_field("pack_battery_percent", 99) self.struct.add_uint_field("pack_battery_percent", 99)
self.struct.add_decimal_array_field("cell_voltages", 105, 16, 2) # internal self.struct.add_decimal_array_field("cell_voltages", 105, 16, 2) # internal
@@ -52,6 +52,7 @@ class EP500P(ProtocolV1Device):
return super().polling_commands + [ return super().polling_commands + [
ReadHoldingRegisters(70, 11), ReadHoldingRegisters(70, 11),
ReadHoldingRegisters(86, 3), ReadHoldingRegisters(86, 3),
ReadHoldingRegisters(92, 1),
ReadHoldingRegisters(3001, 1), ReadHoldingRegisters(3001, 1),
ReadHoldingRegisters(3004, 2), ReadHoldingRegisters(3004, 2),
ReadHoldingRegisters(3011, 1), ReadHoldingRegisters(3011, 1),
@@ -53,6 +53,6 @@ def build_device(address: str, name: str):
def get_type_by_bt_name(bt_name: str): def get_type_by_bt_name(bt_name: str):
match = DEVICE_NAME_RE.match(bt_name) match = DEVICE_NAME_RE.match(bt_name)
if match is None or len(match) < 2: if match is None:
return "Unknown" return "Unknown"
return match[1] return match[1]
@@ -30,15 +30,15 @@ class DeviceField:
class UintField(DeviceField): class UintField(DeviceField):
def __init__(self, name: str, address: int, range: Optional[Tuple[int, int]], scale: int): def __init__(self, name: str, address: int, range: Optional[Tuple[int, int]], multiplier: float):
self.range = range self.range = range
self.scale = scale self.multiplier = multiplier
super().__init__(name, address, 1) super().__init__(name, address, 1)
def parse(self, data: bytes) -> int: def parse(self, data: bytes) -> int:
val = struct.unpack("!H", data)[0] val = struct.unpack("!H", data)[0]
return val * self.scale return val * self.multiplier
def in_range(self, val: int) -> bool: def in_range(self, val: int) -> bool:
if self.range is None: if self.range is None:
@@ -82,15 +82,16 @@ class EnumField(DeviceField):
class DecimalField(DeviceField): class DecimalField(DeviceField):
def __init__( def __init__(
self, name: str, address: int, scale: int, range: Optional[Tuple[int, int]] self, name: str, address: int, scale: int, range: Optional[Tuple[int, int]], multiplier: float
): ):
self.scale = scale self.scale = scale
self.range = range self.range = range
self.multiplier = multiplier
super().__init__(name, address, 1) super().__init__(name, address, 1)
def parse(self, data: bytes) -> Decimal: def parse(self, data: bytes) -> Decimal:
val = Decimal(struct.unpack("!H", data)[0]) val = Decimal(struct.unpack("!H", data)[0])
return val / 10 ** self.scale return (val / 10 ** self.scale) * self.multiplier
def in_range(self, val: Decimal) -> bool: def in_range(self, val: Decimal) -> bool:
if self.range is None: if self.range is None:
@@ -147,8 +148,8 @@ class DeviceStruct:
def __init__(self): def __init__(self):
self.fields = [] self.fields = []
def add_uint_field(self, name: str, address: int, range: Tuple[int, int] = None, scale: int = 1): def add_uint_field(self, name: str, address: int, range: Tuple[int, int] = None, multiplier: float = 1):
self.fields.append(UintField(name, address, range, scale)) self.fields.append(UintField(name, address, range, multiplier))
def add_int_field(self, name: str, address: int, range: Tuple[int, int] = None): def add_int_field(self, name: str, address: int, range: Tuple[int, int] = None):
self.fields.append(IntField(name, address, range)) self.fields.append(IntField(name, address, range))
@@ -160,9 +161,9 @@ class DeviceStruct:
self.fields.append(EnumField(name, address, enum)) self.fields.append(EnumField(name, address, enum))
def add_decimal_field( def add_decimal_field(
self, name: str, address: int, scale: int, range: Tuple[int, int] = None self, name: str, address: int, scale: int, range: Tuple[int, int] = None, multiplier: float = 1
): ):
self.fields.append(DecimalField(name, address, scale, range)) self.fields.append(DecimalField(name, address, scale, range, multiplier))
def add_decimal_array_field(self, name: str, address: int, size: int, scale: int): def add_decimal_array_field(self, name: str, address: int, size: int, scale: int):
self.fields.append(DecimalArrayField(name, address, size, scale)) self.fields.append(DecimalArrayField(name, address, size, scale))
+11 -1
View File
@@ -14,7 +14,7 @@ from homeassistant.components.bluetooth import (
BluetoothServiceInfoBleak, BluetoothServiceInfoBleak,
async_discovered_service_info, async_discovered_service_info,
) )
from homeassistant.const import CONF_ADDRESS, CONF_NAME from homeassistant.const import CONF_ADDRESS, CONF_NAME, CONF_TYPE
from homeassistant.data_entry_flow import FlowResult from homeassistant.data_entry_flow import FlowResult
from homeassistant.helpers import selector from homeassistant.helpers import selector
@@ -48,11 +48,20 @@ class BluettiConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
await self.async_set_unique_id(discovery_info.address) await self.async_set_unique_id(discovery_info.address)
self._abort_if_unique_id_configured() self._abort_if_unique_id_configured()
if isinstance(discovery_info.name, str):
name = re.sub("[^A-Z0-9]+", "", discovery_info.name)
discovery_info.manufacturer_data = {
CONF_TYPE: get_type_by_bt_name(name)
}
# Get device type if needed # Get device type if needed
if isinstance(discovery_info.name, str) and discovery_info.name.startswith("PBOX"): if isinstance(discovery_info.name, str) and discovery_info.name.startswith("PBOX"):
bleak_device = BleakClient(discovery_info.device) bleak_device = BleakClient(discovery_info.device)
device_type = await recognize_device(bleak_device, self.hass.loop.create_future) device_type = await recognize_device(bleak_device, self.hass.loop.create_future)
_LOGGER.info("Device identified as %s", device_type) _LOGGER.info("Device identified as %s", device_type)
discovery_info.manufacturer_data = {
CONF_TYPE: device_type.strip(),
}
discovery_info.name = discovery_info.name.replace("PBOX", device_type.strip()) discovery_info.name = discovery_info.name.replace("PBOX", device_type.strip())
self._discovery_info = discovery_info self._discovery_info = discovery_info
@@ -76,6 +85,7 @@ class BluettiConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
data={ data={
CONF_ADDRESS: discovery_info.address, CONF_ADDRESS: discovery_info.address,
CONF_NAME: name, CONF_NAME: name,
CONF_TYPE: discovery_info.manufacturer_data.get(CONF_TYPE, "Unknown"),
}, },
) )
+1 -1
View File
@@ -23,5 +23,5 @@
"iot_class": "local_polling", "iot_class": "local_polling",
"issue_tracker": "https://github.com/Patrick762/hassio-bluetti-bt/issues", "issue_tracker": "https://github.com/Patrick762/hassio-bluetti-bt/issues",
"requirements": [], "requirements": [],
"version": "0.0.24" "version": "0.0.25"
} }
+2 -2
View File
@@ -57,7 +57,7 @@ async def async_setup_entry(
all_fields.update({name+str(pack): field}) all_fields.update({name+str(pack): field})
for field_key, field_config in all_fields.items(): for field_key, field_config in all_fields.items():
if bluetti_device.has_field(field_key): if bluetti_device.has_field(field_key) or (len(bluetti_device.pack_polling_commands) > 0 and field_key.startswith("pack_")):
category = None category = None
if field_config.setter is True or field_key in DIAGNOSTIC_FIELDS: if field_config.setter is True or field_key in DIAGNOSTIC_FIELDS:
category = EntityCategory.DIAGNOSTIC category = EntityCategory.DIAGNOSTIC
@@ -156,7 +156,7 @@ class BluettiSensor(CoordinatorEntity, SensorEntity):
response_data = self.coordinator.data.get(self._response_key) response_data = self.coordinator.data.get(self._response_key)
if response_data is None: if response_data is None:
_LOGGER.warning("No data for available for (%s)", self._response_key) _LOGGER.debug("No data for available for (%s)", self._response_key)
self._attr_available = False self._attr_available = False
self.async_write_ha_state() self.async_write_ha_state()
return return