Skip to content

Commit

Permalink
Support wss credentials renewal, add missing data error support
Browse files Browse the repository at this point in the history
  • Loading branch information
Jezza34000 committed Nov 14, 2022
1 parent d7e9746 commit 3b24971
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 45 deletions.
35 changes: 24 additions & 11 deletions custom_components/weback_vacuum/VacDevice.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@


class VacDevice(WebackWssCtrl):
def __init__(self, thing_name, thing_nickname, sub_type, thing_status, wss_url, region_name, jwt_token):
def __init__(self, thing_name, thing_nickname, sub_type, thing_status,
user, password, region, country, app, client_id, api_version):
_LOGGER.debug("WebackApi RobotController __init__")
super().__init__(wss_url, region_name, jwt_token)
super().__init__(user, password, region, country, app, client_id, api_version)
self.name = thing_name
self.nickname = thing_nickname
self.sub_type = sub_type
Expand All @@ -33,9 +34,11 @@ async def watch_state(self):
# -> Properties

@property
def current_mode(self) -> str:
def current_mode(self):
""" Raw working_status field string """
return self.robot_status['working_status']
if 'working_status' in self.robot_status:
return self.robot_status['working_status']
return self.IDLE_MODE

@property
def raw_status(self) -> str:
Expand All @@ -52,7 +55,9 @@ def is_cleaning(self) -> bool:
@property
def is_available(self):
""" Boolean define if robot is connected to cloud """
return self.robot_status['connected'] == 'true'
if 'connected' in self.robot_status:
return self.robot_status['connected'] == 'true'
return False

@property
def is_charging(self):
Expand All @@ -62,22 +67,28 @@ def is_charging(self):
@property
def error_info(self):
""" Raw error_info field string """
return self.robot_status["error_info"]
if 'error_info' in self.robot_status:
return self.robot_status['error_info']
return None

@property
def battery_level(self):
""" Raw battery_level field integer """
return int(self.robot_status["battery_level"])
if 'battery_level' in self.robot_status:
return int(self.robot_status['battery_level'])
return 0

@property
def fan_status(self):
""" Raw fan_status field string """
return self.robot_status["fan_status"]
if 'fan_status' in self.robot_status:
return self.robot_status['fan_status']

@property
def mop_status(self):
""" Raw fan_status field string """
return self.robot_status["water_level"]
if 'water_level' in self.robot_status:
return self.robot_status['water_level']

@property
def fan_speed_list(self):
Expand All @@ -92,12 +103,14 @@ def mop_level_list(self):
@property
def clean_time(self):
"""Return clean time"""
return self.robot_status["clean_time"]
if 'clean_time' in self.robot_status:
return self.robot_status['clean_time']

@property
def clean_area(self):
"""Return clean area in square meter"""
return self.robot_status["clean_area"]
if 'clean_area' in self.robot_status:
return self.robot_status['clean_area']

@property
def vacuum_or_mop(self) -> int:
Expand Down
67 changes: 44 additions & 23 deletions custom_components/weback_vacuum/WebackApi.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,26 +156,26 @@ def save_token_file(self):
try:
config = configparser.ConfigParser()
config.add_section('weback_token')
config.set('weback_token', 'jwt_token', self.jwt_token)
config.set('weback_token', 'token_exp', self.token_exp)
config.set('weback_token', 'api_url', self.api_url)
config.set('weback_token', 'wss_url', self.wss_url)
config.set('weback_token', 'region_name', self.region_name)
config.set('weback_token', 'jwt_token', str(self.jwt_token))
config.set('weback_token', 'token_exp', str(self.token_exp))
config.set('weback_token', 'api_url', str(self.api_url))
config.set('weback_token', 'wss_url', str(self.wss_url))
config.set('weback_token', 'region_name', str(self.region_name))
with open('weback_creds', 'w') as configfile:
config.write(configfile)
_LOGGER.debug(f"WebackApi saved new creds")
except:
_LOGGER.debug(f"WebackApi failed to saved new creds")
except Exception as e:
_LOGGER.debug(f"WebackApi failed to saved new creds details={e}")

@staticmethod
def check_token_is_valid(token: str) -> bool:
def check_token_is_valid(token) -> bool:
"""
Check if token validity is still OK or not
"""
_LOGGER.debug(f"WebackApi checking token validity : {token}")
try:
now_date = datetime.today()
dt_token = datetime.strptime(token, "%Y-%d-%m %H:%M:%S.%f")
now_date = datetime.today() - timedelta(minutes=15)
dt_token = datetime.strptime(str(token), "%Y-%m-%d %H:%M:%S.%f")
if now_date < dt_token:
_LOGGER.debug(f"WebackApi token is valid")
return True
Expand Down Expand Up @@ -239,7 +239,7 @@ async def send_http(url, **params):
# _LOGGER.debug(f"WebackVacuumApi (WSS) null_callback: {message}")


class WebackWssCtrl:
class WebackWssCtrl(WebackApi):

# Clean mode
CLEAN_MODE_AUTO = 'AutoClean'
Expand Down Expand Up @@ -267,7 +267,7 @@ class WebackWssCtrl:

# Idle state
IDLE_MODE_HIBERNATING = 'Hibernating'
IDLE_MODE = "Idle"
IDLE_MODE = 'Idle'

# Standby/Paused state
CLEAN_MODE_STOP = 'Standby'
Expand Down Expand Up @@ -302,7 +302,10 @@ class WebackWssCtrl:
MOP_ON = 2

# Error state
ROBOT_ERROR = "Malfunction"
ROBOT_ERROR = 'Malfunction'

# Unknow state
ROBOT_UNKNOWN = 'unknown'

# Robot Error codes
ROBOT_ERROR_NO = "NoError"
Expand Down Expand Up @@ -379,25 +382,42 @@ class WebackWssCtrl:
WebSocket Weback API controller
Handle websocket to send/receive robot control
"""
def __init__(self, wss_url, region_name, jwt_token):
def __init__(self, user, password, region, country, app, client_id, api_version):
super().__init__(user, password, region, country, app, client_id, api_version)
_LOGGER.debug("WebackApi WSS Control __init__")
self.ws = None
self.authorization = "Basic KG51bGwpOihudWxsKQ=="
self.socket_state = SOCK_CLOSE
self.jwt_token = jwt_token
self.region_name = region_name
self.wss_url = wss_url
self.robot_status = None
self.subscriber = []
self.wst = None
self.ws = None
self._refresh_time = 60
self.sent_counter = 0

async def check_credentials(self):
"""
Check if credentials for WSS link are OK
"""
_LOGGER.debug(f"WebackApi (WSS) Checking credentials...")
if not self.region_name or not self.jwt_token or not self.check_token_is_valid(self.token_exp):
_LOGGER.debug(f"WebackApi (WSS) Credentials need renewal")
# Cred renewal necessary
if await self.login():
return True
else:
return False
_LOGGER.debug(f"WebackApi (WSS) Credentials are OK")
return True

async def open_wss_thread(self):
"""
Connect WebSocket to Weback Server and create a thread to maintain connexion alive
"""
if not await self.check_credentials():
_LOGGER.error(f"WebackApi (WSS) Failed to obtain WSS credentials")
return False

_LOGGER.debug(f"WebackApi (WSS) Addr={self.wss_url} / Region={self.region_name} / Token={self.jwt_token}")

try:
Expand Down Expand Up @@ -569,12 +589,13 @@ async def update_status(self, thing_name, sub_type):
def adapt_refresh_time(self, status):
"""Adapt refreshing time depending on robot status"""
_LOGGER.debug(f"WebackApi (WSS) adapt for : {status}")
if status['working_status'] in self.DOCKED_STATES:
_LOGGER.debug("WebackApi (WSS) > Set refreshing to 120s")
self._refresh_time = 120
else:
_LOGGER.debug("WebackApi (WSS) > Set refreshing to 5s")
self._refresh_time = 5
if 'working_status' in status:
if status['working_status'] not in self.DOCKED_STATES:
_LOGGER.debug("WebackApi (WSS) > Set refreshing to 5s")
self._refresh_time = 5
return
_LOGGER.debug("WebackApi (WSS) > Set refreshing to 120s")
self._refresh_time = 120

async def refresh_handler(self, thing_name, sub_type):
_LOGGER.debug("WebackApi (WSS) Start refresh_handler")
Expand Down
11 changes: 8 additions & 3 deletions custom_components/weback_vacuum/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,14 @@ async def async_setup(hass, config):
robot["thing_nickname"],
robot["sub_type"],
robot["thing_status"],
weback_api.wss_url,
weback_api.region_name,
weback_api.jwt_token)
config[DOMAIN].get(CONF_USERNAME),
config[DOMAIN].get(CONF_PASSWORD),
config[DOMAIN].get(CONF_REGION),
config[DOMAIN].get(CONF_LANGUAGE),
config[DOMAIN].get(CONF_APP),
config[DOMAIN].get(CONF_CLIENT_ID),
config[DOMAIN].get(CONF_API_VERSION),
)
hass.data[DOMAIN].append(vacuum_device)

if hass.data[DOMAIN]:
Expand Down
11 changes: 3 additions & 8 deletions custom_components/weback_vacuum/vacuum.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ def __init__(self, device: VacDevice):
self.device.subscribe(lambda vacdevice: self.schedule_update_ha_state(False))
self._error = None

BASE_FEATURES = (
self._attr_supported_features = (
VacuumEntityFeature.TURN_ON
| VacuumEntityFeature.TURN_OFF
| VacuumEntityFeature.STATUS
Expand All @@ -84,13 +84,8 @@ def __init__(self, device: VacDevice):
| VacuumEntityFeature.LOCATE
| VacuumEntityFeature.START
| VacuumEntityFeature.SEND_COMMAND
| VacuumEntityFeature.FAN_SPEED
)

if self.device.vacuum_or_mop != 0:
_LOGGER.debug(f"Add fan_speed features for this robot")
supported_features = BASE_FEATURES | VacuumEntityFeature.FAN_SPEED

self._attr_supported_features = supported_features
_LOGGER.info(f"Vacuum initialized: {self.name}")

@property
Expand All @@ -109,7 +104,7 @@ def name(self):

@property
def available(self):
_LOGGER.debug("Vacuum: available", self.device.is_available)
_LOGGER.debug(f"Vacuum: available={self.device.is_available}")
"""Returns true if vacuum is online"""
return self.device.is_available

Expand Down

0 comments on commit 3b24971

Please sign in to comment.