Skip to content

Commit

Permalink
General fix
Browse files Browse the repository at this point in the history
- reviewed reconection algorithm
- fixed sensor states issue for some devices
- minor fix
  • Loading branch information
ollo69 committed Jun 10, 2020
1 parent ea2c144 commit 684a2d3
Show file tree
Hide file tree
Showing 9 changed files with 175 additions and 57 deletions.
51 changes: 47 additions & 4 deletions custom_components/smartthinq_sensors/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
MAX_RETRIES = 3
MAX_CONN_RETRIES = 2
MAX_LOOP_WARN = 3
MAX_UPDATE_FAIL_ALLOWED = 10
# not stress to match cloud if multiple call
MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=10)

Expand Down Expand Up @@ -244,6 +245,9 @@ def __init__(self, device, name):
self._retry_count = 0
self._disconnected = True
self._not_logged = False
self._update_fail_count = 0
self._not_logged_count = 0
self._refresh_gateway = False

@property
def available(self) -> bool:
Expand Down Expand Up @@ -297,9 +301,14 @@ def init_device(self):
def _restart_monitor(self):
"""Restart the device monitor"""

refresh_gateway = False
if self._refresh_gateway:
refresh_gateway = True
self._refresh_gateway = False

try:
if self._not_logged:
self._device.client.refresh()
self._device.client.refresh(refresh_gateway)
self._not_logged = False
self._disconnected = True

Expand All @@ -311,11 +320,11 @@ def _restart_monitor(self):
self._disconnected = True

except NotLoggedInError:
_LOGGER.info("ThinQ Session expired. Refreshing.")
_LOGGER.debug("ThinQ Session expired. Refreshing.")
self._not_logged = True

except (reqExc.ConnectionError, reqExc.ConnectTimeout, reqExc.ReadTimeout):
_LOGGER.error("Connection to ThinQ failed. Network connection error")
_LOGGER.debug("Connection to ThinQ failed. Network connection error")
self._disconnected = True
self._not_logged = True

Expand All @@ -328,6 +337,14 @@ def device_update(self):
"""Update device state"""
_LOGGER.debug("Updating smartthinq device %s.", self.name)

if self._disconnected or self._not_logged:
if self._update_fail_count < MAX_UPDATE_FAIL_ALLOWED:
self._update_fail_count += 1
if self._not_logged:
self._not_logged_count += 1
else:
self._not_logged_count = 0

for iteration in range(MAX_RETRIES):
_LOGGER.debug("Polling...")

Expand All @@ -339,10 +356,35 @@ def device_update(self):
self._retry_count = 0
self._restart_monitor()

if self._disconnected or self._not_logged:
if self._update_fail_count >= MAX_UPDATE_FAIL_ALLOWED:
if self._state.is_on:
_LOGGER.warning(
"Connection to ThinQ for device %s failed. Reset device status.",
self.name,
)
self._not_logged_count = 0
self._state = self._device.reset_status()
return
elif (
self._not_logged_count == MAX_UPDATE_FAIL_ALLOWED or (
self._not_logged_count > 0 and
self._not_logged_count % 60 == 0
)
):
_LOGGER.error(
"Connection to ThinQ for device %s is not available. Connection will be retried...",
self.name,
)
if self._not_logged_count >= 60:
self._refresh_gateway = True
self._not_logged_count += 1

if self._disconnected:
return

if not (self._disconnected or self._not_logged):

try:
state = self._device.poll()

Expand All @@ -355,7 +397,7 @@ def device_update(self):
# time.sleep(1)

except (reqExc.ConnectionError, reqExc.ConnectTimeout, reqExc.ReadTimeout):
_LOGGER.error("Connection to ThinQ failed. Network connection error")
_LOGGER.debug("Connection to ThinQ failed. Network connection error")
self._not_logged = True
return

Expand All @@ -369,6 +411,7 @@ def device_update(self):
# l = dir(state)
# _LOGGER.debug('Status attributes: %s', l)

self._update_fail_count = 0
self._retry_count = 0
self._state = state

Expand Down
2 changes: 1 addition & 1 deletion custom_components/smartthinq_sensors/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Support to interface with LGE ThinQ Devices.
"""

__version__ = "0.5.0"
__version__ = "0.5.1"
PROJECT_URL = "https://github.com/ollo69/ha-smartthinq-sensors/"
ISSUE_URL = "{}issues".format(PROJECT_URL)

Expand Down
11 changes: 10 additions & 1 deletion custom_components/smartthinq_sensors/wideq/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,11 @@ def refresh(self):
new_access_token = refresh_auth(self.gateway.oauth_root, self.refresh_token)
return Auth(self.gateway, new_access_token, self.refresh_token)

def refresh_gateway(self, gateway):
"""Refresh the gateway.
"""
self.gateway = gateway

def dump(self):
return {"access_token": self.access_token, "refresh_token": self.refresh_token}

Expand Down Expand Up @@ -573,7 +578,11 @@ def dump(self) -> Dict[str, Any]:

return out

def refresh(self) -> None:
def refresh(self, refresh_gateway=False) -> None:
if refresh_gateway:
self._gateway = None
if not self._gateway:
self._auth.refresh_gateway(self.gateway)
self._auth = self.auth.refresh()
self._session, self._devices = self.auth.start_session()

Expand Down
11 changes: 10 additions & 1 deletion custom_components/smartthinq_sensors/wideq/core_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,11 @@ def refresh(self):
self.user_number,
)

def refresh_gateway(self, gateway):
"""Refresh the gateway.
"""
self.gateway = gateway

def dump(self):
return {
"access_token": self.access_token,
Expand Down Expand Up @@ -692,7 +697,11 @@ def dump(self) -> Dict[str, Any]:

return out

def refresh(self) -> None:
def refresh(self, refresh_gateway=False) -> None:
if refresh_gateway:
self._gateway = None
if not self._gateway:
self._auth.refresh_gateway(self.gateway)
self._auth = self.auth.refresh()
self._session = self.auth.start_session()
# self._device = None
Expand Down
10 changes: 9 additions & 1 deletion custom_components/smartthinq_sensors/wideq/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -684,6 +684,10 @@ def status(self):
return None
return self._status

def reset_status(self):
self._status = None
return self._status

def _set_control(self, key, value):
"""Set a device's control for `key` to `value`.
"""
Expand Down Expand Up @@ -841,7 +845,11 @@ def int_or_none(value):

@property
def has_data(self):
return self._data is not None
return True if self._data else False

@property
def is_on(self) -> bool:
return False

@property
def is_info_v2(self):
Expand Down
47 changes: 31 additions & 16 deletions custom_components/smartthinq_sensors/wideq/dishwasher.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,17 @@
)

STATE_DISHWASHER_POWER_OFF = "@DW_STATE_POWER_OFF_W"
STATE_DISHWASHER_COMPLETE = "@DW_STATE_COMPLETE_W"
STATE_DISHWASHER_ERROR_NO_ERROR = "No_Error"
STATE_DISHWASHER_END = [
"@DW_STATE_END_W",
"@DW_STATE_COMPLETE_W",
]
STATE_DISHWASHER_ERROR_OFF = "OFF"
STATE_DISHWASHER_ERROR_NO_ERROR = [
"ERROR_NOERROR",
"ERROR_NOERROR_TITLE",
"No Error",
"No_Error",
]

_LOGGER = logging.getLogger(__name__)

Expand All @@ -21,6 +29,10 @@ class DishWasherDevice(Device):
def __init__(self, client, device):
super().__init__(client, device, DishWasherStatus(self, None))

def reset_status(self):
self._status = DishWasherStatus(self, None)
return self._status

def poll(self) -> Optional["DishWasherStatus"]:
"""Poll the device's current state."""

Expand Down Expand Up @@ -48,24 +60,27 @@ def _get_run_state(self):
if not self._run_state:
state = self.lookup_enum(["State", "state"])
if not state:
return STATE_DISHWASHER_POWER_OFF
self._run_state = state
self._run_state = STATE_DISHWASHER_POWER_OFF
else:
self._run_state = state
return self._run_state

def _get_process(self):
if not self._process:
process = self.lookup_enum(["Process", "process"])
if not process:
return STATE_OPTIONITEM_NONE
self._process = process
self._process = STATE_OPTIONITEM_NONE
else:
self._process = process
return self._process

def _get_error(self):
if not self._error:
error = self.lookup_reference(["Error", "error"], ref_key="title")
if not error:
return STATE_DISHWASHER_ERROR_OFF
self._error = error
self._error = STATE_DISHWASHER_ERROR_OFF
else:
self._error = error
return self._error

@property
Expand All @@ -77,18 +92,20 @@ def is_on(self):
def is_run_completed(self):
run_state = self._get_run_state()
process = self._get_process()
if run_state == STATE_DISHWASHER_COMPLETE or (
run_state == STATE_DISHWASHER_POWER_OFF and process == STATE_DISHWASHER_COMPLETE
if run_state in STATE_DISHWASHER_END or (
run_state == STATE_DISHWASHER_POWER_OFF and process in STATE_DISHWASHER_END
):
return True
return False

@property
def is_error(self):
if not self.is_on:
return False
error = self._get_error()
if error != STATE_DISHWASHER_ERROR_NO_ERROR and error != STATE_DISHWASHER_ERROR_OFF:
return True
return False
if error in STATE_DISHWASHER_ERROR_NO_ERROR or error == STATE_DISHWASHER_ERROR_OFF:
return False
return True

@property
def run_state(self):
Expand All @@ -106,11 +123,9 @@ def process_state(self):

@property
def error_state(self):
if not self.is_on:
if not self.is_error:
return STATE_OPTIONITEM_NONE
error = self._get_error()
if error == STATE_DISHWASHER_ERROR_NO_ERROR:
return STATE_OPTIONITEM_NONE
return self._device.get_enum_text(error)

@property
Expand Down
Loading

0 comments on commit 684a2d3

Please sign in to comment.