Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

请求api返回小米账号登录信息失效时,自动重新登陆 #508

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions custom_components/xiaomi_miot_raw/__init__.py
Original file line number Diff line number Diff line change
@@ -195,6 +195,7 @@ async def async_remove_entry(hass, entry):
async def _setup_micloud_entry(hass, config_entry):
"""Thanks to @AlexxIT """
data: dict = config_entry.data.copy()
hass.data[DOMAIN]['micloud_config'] = data
server_location = data.get('server_location') or 'cn'

session = aiohttp_client.async_create_clientsession(hass, auto_cleanup=False)
57 changes: 54 additions & 3 deletions custom_components/xiaomi_miot_raw/basic_dev_class.py
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@
import json
import time
import logging
from datetime import timedelta
from datetime import timedelta, datetime
from functools import partial
from dataclasses import dataclass

@@ -62,7 +62,9 @@

class GenericMiotDevice(Entity):
"""通用 MiOT 设备"""


lastAutoUpdateAccountTime=datetime.now()-timedelta(seconds=3600)

def __init__(self, device, config, device_info, hass = None, mi_type = None):
"""Initialize the entity."""

@@ -506,7 +508,56 @@ def pre_process_data(key, value):
statedict[key] = pre_process_data(key, dict1[value['siid']][value['piid']])

else:
pass
# auth err
# 小米账号登录信息失效
# 自动重新登录,间隔3600秒
lostTime=(datetime.now()-GenericMiotDevice.lastAutoUpdateAccountTime).total_seconds()
_LOGGER.debug("miaccount auth err:lostTime:%d" % (lostTime))
if (lostTime>3600):
_LOGGER.warning("auto update mi_account token")
GenericMiotDevice.lastAutoUpdateAccountTime=datetime.now()

config=self.hass.data[DOMAIN]['micloud_config']
#_LOGGER.debug(f"self.hass.data[DOMAIN]['config']: {json.dumps (config)}")
if 'username' in config:
cloud=self._cloud_instance
resp = await cloud.login(config['username'],
config['password'])
if resp == (0, None):
#让新 token 实时生效
for item in self.hass.data[DOMAIN]['cloud_instance_list']:
mc = item['cloud_instance']
mc.login_by_credientals(
cloud.auth["user_id"],
cloud.auth['service_token'],
cloud.auth['ssecurity']
)

if self.hass.config_entries.async_entries(DOMAIN): #更新每个设备的token
_LOGGER.warning("Found existing config entries")
for entry in self.hass.config_entries.async_entries(DOMAIN):
if (
entry.data.get("update_from_cloud")
):
_LOGGER.warning("Updating existing entry")
update_from_cloud=entry.data.get("update_from_cloud")
update_from_cloud_new={
"did": update_from_cloud["did"],
"userId": update_from_cloud["userId"],
"serviceToken": cloud.auth['service_token'],
"ssecurity": cloud.auth['ssecurity'],
"server_location": update_from_cloud["server_location"]
}
entry_data_new=dict(entry.data)
entry_data_new.update({"update_from_cloud":update_from_cloud_new})
entry_id = entry.entry_id
self.hass.data[DOMAIN]['configs'][entry_id] = entry_data_new
self.hass.config_entries.async_update_entry( #保存新token到文件
entry,
data=entry_data_new,
)
else:
_LOGGER.error("config.data no username")

self._fail_count = 0
self._state_attrs.update(statedict)
37 changes: 37 additions & 0 deletions custom_components/xiaomi_miot_raw/config_flow.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import json
import re

import logging
import asyncio
from types import coroutine
from typing import OrderedDict
@@ -40,6 +41,8 @@
from .deps.special_devices import SPECIAL_DEVICES
from .deps.xiaomi_cloud_new import MiCloud

_LOGGER = logging.getLogger(__name__)

SERVERS = {
'cn': "China",
'de': "Europe",
@@ -735,6 +738,40 @@ async def async_step_update_xiaomi_account(self, user_input=None, error=None, hi
if resp == (0, None):
self._all_config.update(user_input)
self._all_config.update(cloud.auth)

#让新 token 实时生效
for item in self.hass.data[DOMAIN]['cloud_instance_list']:
mc = item['cloud_instance']
mc.login_by_credientals(
cloud.auth["user_id"],
cloud.auth['service_token'],
cloud.auth['ssecurity']
)

if self.hass.config_entries.async_entries(DOMAIN): #更新每个设备的token
_LOGGER.info("Found existing config entries")
for entry in self.hass.config_entries.async_entries(DOMAIN):
if (
entry.data.get("update_from_cloud")
):
_LOGGER.info("Updating existing entry")
update_from_cloud=entry.data.get("update_from_cloud")
update_from_cloud_new={
"did": update_from_cloud["did"],
"userId": update_from_cloud["userId"],
"serviceToken": cloud.auth['service_token'],
"ssecurity": cloud.auth['ssecurity'],
"server_location": update_from_cloud["server_location"]
}
entry_data_new=dict(entry.data)
entry_data_new.update({"update_from_cloud":update_from_cloud_new})
entry_id = entry.entry_id
self.hass.data[DOMAIN]['configs'][entry_id] = entry_data_new
self.hass.config_entries.async_update_entry( #保存新token到文件
entry,
data=entry_data_new,
)

self._steps.pop(0)
return await self._steps[0]
elif resp[0] == -2:
8 changes: 6 additions & 2 deletions custom_components/xiaomi_miot_raw/deps/xiaomi_cloud_new.py
Original file line number Diff line number Diff line change
@@ -78,6 +78,7 @@ async def login(self, username: str, password: str):
'ssecurity': data['ssecurity'],
'service_token': token
}
_LOGGER.info(f"user_id:{data['userId']},service_token: {token}")
return (0, None)

except Exception as e:
@@ -160,6 +161,7 @@ async def get_devices(self, server: str):
except Exception:
loc = "en_US"
try:
_LOGGER.info(f"user_id:{self.auth['user_id']},token:{self.auth['service_token']}")
r = await self.session.post(baseurl + url, cookies={
'userId': self.auth['user_id'],
'serviceToken': self.auth['service_token'],
@@ -171,7 +173,7 @@ async def get_devices(self, server: str):
'signature': signature,
'_nonce': nonce,
'data': data
}, timeout=5)
}, timeout=30)

resp = await r.json(content_type=None)
assert resp['code'] == 0, resp
@@ -203,6 +205,7 @@ async def request_miot_api(self, api, data = None, server: str = None):
'cache-control': "no-cache",
}
try:
_LOGGER.info(f"user_id:{self.auth['user_id']},token:{self.auth['service_token']}")
r = await self.session.post(url, cookies={
'userId': self.auth['user_id'],
'serviceToken': self.auth['service_token'],
@@ -213,7 +216,7 @@ async def request_miot_api(self, api, data = None, server: str = None):
'signature': signature,
'_nonce': nonce,
'data': data
}, timeout=5)
}, timeout=30)

self._fail_count = 0
resp = await r.json(content_type=None)
@@ -230,6 +233,7 @@ async def request_miot_api(self, api, data = None, server: str = None):
return resp

except (asyncio.TimeoutError, ClientConnectorError) as ex:
_LOGGER.exception("request_miot_api:")
if self._fail_count < 3 and api == "/miotspec/prop/get":
self._fail_count += 1
_LOGGER.info(f"Error while requesting MIoT api {api} : {ex} ({self._fail_count})")