Allow some failures of updates before reporting an error
This commit is contained in:
parent
7f5cc8c30f
commit
949edc6b41
|
|
@ -722,8 +722,8 @@ class TuyaDevice:
|
||||||
self.last_pong = time.time()
|
self.last_pong = time.time()
|
||||||
|
|
||||||
async def async_update_state(self, state_message, _):
|
async def async_update_state(self, state_message, _):
|
||||||
|
_LOGGER.info("Received updated state {}: {}").format(self, self._dps)
|
||||||
self._dps.update(state_message.payload["dps"])
|
self._dps.update(state_message.payload["dps"])
|
||||||
_LOGGER.info("Received updated state {}: {}".format(self, self._dps))
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def state(self):
|
def state(self):
|
||||||
|
|
@ -757,15 +757,16 @@ class TuyaDevice:
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if retries == 0:
|
if retries == 0:
|
||||||
if isinstance(e, socket.error):
|
if isinstance(e, socket.error):
|
||||||
_LOGGER.error("Connection to {} failed: {}".format(self, e))
|
|
||||||
self._dps["106"] = "CONNECTION_FAILED"
|
|
||||||
asyncio.ensure_future(self.async_disconnect())
|
asyncio.ensure_future(self.async_disconnect())
|
||||||
|
raise ConnectionException(
|
||||||
|
"Connection to {} failed: {}".format(self, e)
|
||||||
|
)
|
||||||
elif isinstance(e, asyncio.IncompleteReadError):
|
elif isinstance(e, asyncio.IncompleteReadError):
|
||||||
_LOGGER.error("Incomplete read from: {} : {}".format(self, e))
|
raise InvalidMessage(
|
||||||
|
"Incomplete read from: {} : {}".format(self, e)
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
_LOGGER.error("Failed to send data to {}".format(self))
|
raise TuyaException("Failed to send data to {}".format(self))
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
if isinstance(e, socket.error):
|
if isinstance(e, socket.error):
|
||||||
_LOGGER.debug(
|
_LOGGER.debug(
|
||||||
|
|
@ -775,8 +776,8 @@ class TuyaDevice:
|
||||||
)
|
)
|
||||||
elif isinstance(e, asyncio.IncompleteReadError):
|
elif isinstance(e, asyncio.IncompleteReadError):
|
||||||
_LOGGER.debug(
|
_LOGGER.debug(
|
||||||
"Retrying send due to error.Incomplete read from: {} : {}".format(
|
"Retrying send due to error. Incomplete read from: {} : {}. Partial data recieved: {}".format(
|
||||||
self, e
|
self, e, e.partial
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,7 @@ from homeassistant.const import (
|
||||||
STATE_UNAVAILABLE,
|
STATE_UNAVAILABLE,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from .tuyalocalapi import TuyaException
|
||||||
from .const import CONF_VACS, DOMAIN
|
from .const import CONF_VACS, DOMAIN
|
||||||
|
|
||||||
from .errors import getErrorMessage
|
from .errors import getErrorMessage
|
||||||
|
|
@ -85,6 +86,7 @@ ATTR_MODE = "mode"
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
REFRESH_RATE = 20
|
REFRESH_RATE = 20
|
||||||
SCAN_INTERVAL = timedelta(seconds=REFRESH_RATE)
|
SCAN_INTERVAL = timedelta(seconds=REFRESH_RATE)
|
||||||
|
UPDATE_RETRIES = 3
|
||||||
|
|
||||||
|
|
||||||
class TUYA_CODES(StrEnum):
|
class TUYA_CODES(StrEnum):
|
||||||
|
|
@ -99,6 +101,7 @@ class TUYA_CODES(StrEnum):
|
||||||
DO_NOT_DISTURB = "107"
|
DO_NOT_DISTURB = "107"
|
||||||
BOOST_IQ = "118"
|
BOOST_IQ = "118"
|
||||||
|
|
||||||
|
|
||||||
TUYA_CONSUMABLES_CODES = ["142", "116"]
|
TUYA_CONSUMABLES_CODES = ["142", "116"]
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -191,11 +194,20 @@ class RoboVacEntity(StateVacuumEntity):
|
||||||
def state(self) -> str | None:
|
def state(self) -> str | None:
|
||||||
if self.tuya_state is None:
|
if self.tuya_state is None:
|
||||||
return STATE_UNAVAILABLE
|
return STATE_UNAVAILABLE
|
||||||
elif type(self.error_code) is not None and self.error_code and self.error_code not in [
|
elif (
|
||||||
0,
|
type(self.error_code) is not None
|
||||||
"no_error",
|
and self.error_code
|
||||||
]:
|
and self.error_code
|
||||||
_LOGGER.debug("State changed to error. Error message: {}".format(getErrorMessage(self.error_code)))
|
not in [
|
||||||
|
0,
|
||||||
|
"no_error",
|
||||||
|
]
|
||||||
|
):
|
||||||
|
_LOGGER.debug(
|
||||||
|
"State changed to error. Error message: {}".format(
|
||||||
|
getErrorMessage(self.error_code)
|
||||||
|
)
|
||||||
|
)
|
||||||
return STATE_ERROR
|
return STATE_ERROR
|
||||||
elif self.tuya_state == "Charging" or self.tuya_state == "completed":
|
elif self.tuya_state == "Charging" or self.tuya_state == "completed":
|
||||||
return STATE_DOCKED
|
return STATE_DOCKED
|
||||||
|
|
@ -254,6 +266,8 @@ class RoboVacEntity(StateVacuumEntity):
|
||||||
self._attr_ip_address = item[CONF_IP_ADDRESS]
|
self._attr_ip_address = item[CONF_IP_ADDRESS]
|
||||||
self._attr_access_token = item[CONF_ACCESS_TOKEN]
|
self._attr_access_token = item[CONF_ACCESS_TOKEN]
|
||||||
|
|
||||||
|
self.update_failures = 0
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.vacuum = RoboVac(
|
self.vacuum = RoboVac(
|
||||||
device_id=self.unique_id,
|
device_id=self.unique_id,
|
||||||
|
|
@ -295,40 +309,50 @@ class RoboVacEntity(StateVacuumEntity):
|
||||||
self.error_code = "IP_ADDRESS"
|
self.error_code = "IP_ADDRESS"
|
||||||
return
|
return
|
||||||
|
|
||||||
await self.vacuum.async_get()
|
try:
|
||||||
self.tuyastatus = self.vacuum._dps
|
await self.vacuum.async_get()
|
||||||
|
|
||||||
# for 15C
|
self.update_failures = 0
|
||||||
self._attr_battery_level = self.tuyastatus.get(TUYA_CODES.BATTERY_LEVEL)
|
self.tuyastatus = self.vacuum._dps
|
||||||
self.tuya_state = self.tuyastatus.get(TUYA_CODES.STATE)
|
|
||||||
self.error_code = self.tuyastatus.get(TUYA_CODES.ERROR_CODE)
|
# for 15C
|
||||||
self._attr_mode = self.tuyastatus.get(TUYA_CODES.MODE)
|
self._attr_battery_level = self.tuyastatus.get(TUYA_CODES.BATTERY_LEVEL)
|
||||||
self._attr_fan_speed = self.tuyastatus.get(TUYA_CODES.FAN_SPEED)
|
self.tuya_state = self.tuyastatus.get(TUYA_CODES.STATE)
|
||||||
if self.fan_speed == "No_suction":
|
self.error_code = self.tuyastatus.get(TUYA_CODES.ERROR_CODE)
|
||||||
self._attr_fan_speed = "No Suction"
|
self._attr_mode = self.tuyastatus.get(TUYA_CODES.MODE)
|
||||||
elif self.fan_speed == "Boost_IQ":
|
self._attr_fan_speed = self.tuyastatus.get(TUYA_CODES.FAN_SPEED)
|
||||||
self._attr_fan_speed = "Boost IQ"
|
if self.fan_speed == "No_suction":
|
||||||
elif self.fan_speed == "Quiet":
|
self._attr_fan_speed = "No Suction"
|
||||||
self._attr_fan_speed = "Pure"
|
elif self.fan_speed == "Boost_IQ":
|
||||||
# for G30
|
self._attr_fan_speed = "Boost IQ"
|
||||||
self._attr_cleaning_area = self.tuyastatus.get(TUYA_CODES.CLEANING_AREA)
|
elif self.fan_speed == "Quiet":
|
||||||
self._attr_cleaning_time = self.tuyastatus.get(TUYA_CODES.CLEANING_TIME)
|
self._attr_fan_speed = "Pure"
|
||||||
self._attr_auto_return = self.tuyastatus.get(TUYA_CODES.AUTO_RETURN)
|
# for G30
|
||||||
self._attr_do_not_disturb = self.tuyastatus.get(TUYA_CODES.DO_NOT_DISTURB)
|
self._attr_cleaning_area = self.tuyastatus.get(TUYA_CODES.CLEANING_AREA)
|
||||||
self._attr_boost_iq = self.tuyastatus.get(TUYA_CODES.BOOST_IQ)
|
self._attr_cleaning_time = self.tuyastatus.get(TUYA_CODES.CLEANING_TIME)
|
||||||
# self.map_data = self.tuyastatus.get("121")
|
self._attr_auto_return = self.tuyastatus.get(TUYA_CODES.AUTO_RETURN)
|
||||||
# self.erro_msg? = self.tuyastatus.get("124")
|
self._attr_do_not_disturb = self.tuyastatus.get(TUYA_CODES.DO_NOT_DISTURB)
|
||||||
if self.robovac_supported & RoboVacEntityFeature.CONSUMABLES:
|
self._attr_boost_iq = self.tuyastatus.get(TUYA_CODES.BOOST_IQ)
|
||||||
for CONSUMABLE_CODE in TUYA_CONSUMABLES_CODES:
|
# self.map_data = self.tuyastatus.get("121")
|
||||||
if (
|
# self.erro_msg? = self.tuyastatus.get("124")
|
||||||
CONSUMABLE_CODE in self.tuyastatus
|
if self.robovac_supported & RoboVacEntityFeature.CONSUMABLES:
|
||||||
and self.tuyastatus.get(CONSUMABLE_CODE) is not None
|
for CONSUMABLE_CODE in TUYA_CONSUMABLES_CODES:
|
||||||
):
|
if (
|
||||||
self._attr_consumables = ast.literal_eval(
|
CONSUMABLE_CODE in self.tuyastatus
|
||||||
base64.b64decode(self.tuyastatus.get(CONSUMABLE_CODE)).decode(
|
and self.tuyastatus.get(CONSUMABLE_CODE) is not None
|
||||||
"ascii"
|
):
|
||||||
)
|
self._attr_consumables = ast.literal_eval(
|
||||||
)["consumable"]["duration"]
|
base64.b64decode(
|
||||||
|
self.tuyastatus.get(CONSUMABLE_CODE)
|
||||||
|
).decode("ascii")
|
||||||
|
)["consumable"]["duration"]
|
||||||
|
except TuyaException as e:
|
||||||
|
self.update_failures += 1
|
||||||
|
_LOGGER.debug("Update errored. Current failure count: {}. Reason: {}".format(self.update_failures, e))
|
||||||
|
if self.update_failures == UPDATE_RETRIES:
|
||||||
|
self.update_failures = 0
|
||||||
|
self.error_code = "CONNECTION_FAILED"
|
||||||
|
raise e
|
||||||
|
|
||||||
async def async_locate(self, **kwargs):
|
async def async_locate(self, **kwargs):
|
||||||
"""Locate the vacuum cleaner."""
|
"""Locate the vacuum cleaner."""
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue