Merge pull request #107 from Patrick762/next

Fixed values and improved unavailable handling
This commit is contained in:
Patrick762 authored and GitHub committed 2024-06-02 14:06:20 +02:00
commit 6478825503
5 files changed
+74 -24

No files matched your search

+32 -7
View File
@@ -97,6 +97,27 @@ class BluettiBinarySensor(CoordinatorEntity, BinarySensorEntity):
"""Return if entity is available."""
return self._attr_available
def _set_available(self):
"""Set sensor as available."""
self._attr_available = True
self._unavailable_counter = 0
self._attr_extra_state_attributes = {}
self.async_write_ha_state()
def _set_unavailable(self, cause: str = "Unknown"):
"""Set sensor as unavailable."""
self._unavailable_counter += 1
self._attr_extra_state_attributes = {
"unavailable_counter": self._unavailable_counter,
"unavailable_cause": cause,
}
if self._unavailable_counter >= 5:
self._attr_available = False
self.async_write_ha_state()
@callback
def _handle_coordinator_update(self) -> None:
"""Handle updated data from the coordinator."""
@@ -104,19 +125,24 @@ class BluettiBinarySensor(CoordinatorEntity, BinarySensorEntity):
if self.coordinator.reader.persistent_conn and not self.coordinator.reader.client.is_connected:
return
if self.coordinator.data is None:
_LOGGER.debug(
"Data from coordinator is None",
)
self._set_unavailable("Data is None")
return
_LOGGER.debug("Updating state of %s", unique_id_loggable(self._attr_unique_id))
if not isinstance(self.coordinator.data, dict):
_LOGGER.debug(
"Invalid data from coordinator (binary_sensor.%s)", unique_id_loggable(self._attr_unique_id)
)
self._attr_available = False
self.async_write_ha_state()
self._set_unavailable("Invalid data")
return
response_data = self.coordinator.data.get(self._response_key)
if response_data is None:
self._attr_available = False
self.async_write_ha_state()
self._set_unavailable("No data")
return
if not isinstance(response_data, bool):
@@ -125,10 +151,9 @@ class BluettiBinarySensor(CoordinatorEntity, BinarySensorEntity):
unique_id_loggable(self._attr_unique_id),
response_data,
)
self._attr_available = False
self.async_write_ha_state()
self._set_unavailable("Invalid data type")
return
self._attr_available = True
self._set_available()
self._attr_is_on = self.coordinator.data[self._response_key] is True
self.async_write_ha_state()
@@ -110,7 +110,12 @@ class DeviceReader:
await self._async_send_command(command)
)
_LOGGER.debug("Raw data set: %s", body)
# b'\x00\x02' b'\x00\x03' here (seems like result)
# Check set pack_num
set_pack = int.from_bytes(body, byteorder='big')
if set_pack is not pack:
_LOGGER.warning("Pack polling failed (pack_num %i doesn't match expected %i)", set_pack, pack)
continue
for command in pack_commands:
# Request & parse result for each pack
@@ -124,7 +129,9 @@ class DeviceReader:
_LOGGER.debug("Parsed data: %s", parsed)
for key, value in parsed.items():
parsed_data.update({key + str(pack): value})
# Ignore likely unavailable pack data
if value != 0:
parsed_data.update({key + str(pack): value})
except ParseError:
_LOGGER.warning("Got a parse exception...")
@@ -13,17 +13,17 @@ class AC200L(ProtocolV1Device):
# Details
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, multiplier=10)
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, 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_ac_frequency", 74, 2, multiplier=10)
self.struct.add_uint_field("internal_dc_input_voltage", 86, multiplier=.1)
self.struct.add_decimal_field("internal_dc_input_power", 87, 1, multiplier=10)
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_decimal_field("total_battery_voltage", 92, 1, multiplier=.1)
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_uint_field("pack_battery_percent", 99)
+1 -1
View File
@@ -23,5 +23,5 @@
"iot_class": "local_polling",
"issue_tracker": "https://github.com/Patrick762/hassio-bluetti-bt/issues",
"requirements": [],
"version": "0.1.0"
"version": "0.1.1"
}
+27 -9
View File
@@ -114,6 +114,7 @@ class BluettiSensor(CoordinatorEntity, SensorEntity):
e_name = f"{device_info.get('name')} {name}"
self._address = address
self._response_key = response_key
self._unavailable_counter = 0
self._attr_device_info = device_info
self._attr_name = name
@@ -130,6 +131,27 @@ class BluettiSensor(CoordinatorEntity, SensorEntity):
"""Return if entity is available."""
return self._attr_available
def _set_available(self):
"""Set sensor as available."""
self._attr_available = True
self._unavailable_counter = 0
self._attr_extra_state_attributes = {}
self.async_write_ha_state()
def _set_unavailable(self, cause: str = "Unknown"):
"""Set sensor as unavailable."""
self._unavailable_counter += 1
self._attr_extra_state_attributes = {
"unavailable_counter": self._unavailable_counter,
"unavailable_cause": cause,
}
if self._unavailable_counter >= 5:
self._attr_available = False
self.async_write_ha_state()
@callback
def _handle_coordinator_update(self) -> None:
"""Handle updated data from the coordinator."""
@@ -141,8 +163,7 @@ class BluettiSensor(CoordinatorEntity, SensorEntity):
_LOGGER.debug(
"Data from coordinator is None",
)
self._attr_available = False
self.async_write_ha_state()
self._set_unavailable("Data is None")
return
_LOGGER.debug("Updating state of %s", unique_id_loggable(self._attr_unique_id))
@@ -150,15 +171,13 @@ class BluettiSensor(CoordinatorEntity, SensorEntity):
_LOGGER.warning(
"Invalid data from coordinator (sensor.%s)", unique_id_loggable(self._attr_unique_id)
)
self._attr_available = False
self.async_write_ha_state()
self._set_unavailable("Invalid data")
return
response_data = self.coordinator.data.get(self._response_key)
if response_data is None:
_LOGGER.debug("No data for available for (%s)", self._response_key)
self._attr_available = False
self.async_write_ha_state()
self._set_unavailable("No data")
return
if (
@@ -174,11 +193,10 @@ class BluettiSensor(CoordinatorEntity, SensorEntity):
response_data,
type(response_data),
)
self._attr_available = False
self.async_write_ha_state()
self._set_unavailable("Invalid data type")
return
self._attr_available = True
self._set_available()
# Different for enum and numeric
if (