Skip to content

fix: token 失效时自动刷新并自愈网关连接 - #278

Open
yangkghjh wants to merge 3 commits into
banto6:masterfrom
yangkghjh:fix/token-refresh-self-heal
Open

fix: token 失效时自动刷新并自愈网关连接#278
yangkghjh wants to merge 3 commits into
banto6:masterfrom
yangkghjh:fix/token-refresh-self-heal

Conversation

@yangkghjh

Copy link
Copy Markdown

问题

设备过一段时间后全部变为 unavailable,直到手动重新配置账户才能恢复。

根因

  1. token 有效期约 10 天expires_in=863999s)。token 失效后,海尔 WebSocket 网关拒绝连接,插件把所有实体标记为不可用。
  2. token 刷新链路脆弱token_updater 每 1 小时才检查一次,且验证 token 时若 get_user_info() 抛出非 HaierClientException 的异常(网络波动、超时等),try_update_token 直接中断,token 永远不会被刷新
  3. 网关重连使用旧 tokenHaierDeviceGateway 在初始化时固定 token,WS 断线后每 30 秒重连都使用旧 token。即使 token 已被刷新并保存到 config entry,重连依然失败,实体持续不可用。

修复

  • __init__.py
    • try_update_token 捕获所有异常(不仅是 HaierClientException),网络波动时同样尝试刷新,刷新成功会保存新 token。
    • 网关断线时通过 EVENT_TOKEN_REFRESH_REQUESTED 事件立即触发 token 刷新(带 5 分钟节流,避免断线重试风暴),不再等待下一个整点。
    • 初始 token 刷新失败不再导致集成加载失败。
  • core/device_gateway.py
    • 网关断线时 fire EVENT_TOKEN_REFRESH_REQUESTED 请求立即刷新。
    • 每次重连前从 config entry 读取最新 token(通过新增的 _get_latest_token()),并同步给 client,确保 token 刷新后重连立即生效。
  • core/client.py:新增 HaierClient.update_token() 方法。
  • core/event.py:新增 EVENT_TOKEN_REFRESH_REQUESTED 事件。

效果

token 失效后,网关断线 → 立即触发刷新 → 重连使用新 token → 设备自动恢复,无需人工干预。

测试

  • 4 个改动文件均通过 py_compile
  • 单元测试(stub HA 环境)验证:断线事件只 fire 一次、最新 token 读取、无 config_entry 回退、_connect 使用最新 token 构造 WS URL。

修复设备过一段时间后全部变为 unavailable 的问题。

根因:
- token 有效期约10天,失效后海尔 WebSocket 网关拒绝连接
- token_updater 每小时才检查一次,且 get_user_info 验证失败
  (网络波动等非 HaierClientException 异常)时直接中断刷新流程
- 网关重连永远使用初始化时的旧 token,token 已刷新也不生效

修复:
- token_updater 捕获所有验证异常,网络波动时同样尝试刷新
- 网关断线时 fire EVENT_TOKEN_REFRESH_REQUESTED,立即触发 token
  刷新(5分钟节流,避免重试风暴),不再等待整点
- 网关每次重连前从 config entry 读取最新 token 并同步给 client,
  确保 token 刷新后重连立即生效
- 新增 HaierClient.update_token() 方法
发现上一版修复的盲区:网关断线触发刷新时,try_update_token
先调用 get_user_info 验证 token 有效性。海尔 WS 网关对 token
的校验比 REST 接口更严格——token 在 REST 层仍返回 200(有效),
但 WebSocket 网关已拒绝该 token。此时验证通过 → 不刷新 →
gateway 永远用被拒的 token 重连,设备持续 unavailable。

修复:try_update_token 增加 force 参数,网关断线触发的刷新
强制跳过 token 有效性检查直接刷新。
@banto6

banto6 commented Aug 15, 2026

Copy link
Copy Markdown
Owner

try_update_token 捕获所有异常这点是可以的,但是device_gateway去刷新token我觉得不太合理,因为ws本身属于长连接,就算token失效后连接有不会立马断开,且每小时刷新token后会自动重载集成,这个时候gateway就会自动使用最新的token

至于提到的设备过一段时间后全部变为 unavailable,直到手动重新配置账户才能恢复, 这点我在本地无法复现呢

@yangkghjh

Copy link
Copy Markdown
Author

现象是每过一段时间设备会变的不可用(几天),需要手动触发更新账户才能重新使用

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants