京东小家接入Home Assistant智能家居记录

2026-09-08 11:56:35 0点赞 0收藏 1评论

智能家居的人都知道,买家电最怕遇到生态孤岛。

最近家里添置了一台长虹空调,因为是在某东平台买的,强制要求绑定某东小家APP。作为一个智能家居折腾狂,我的终极目标是把所有设备接入 Home Assistant(HA)实现本地化统管。但在这个平台上,我遇到了可以说是智能家居折腾史里最难啃的一块硬骨头。

周末耗时两天,我把这套APP从底层协议到签名算法彻彻底底逆向了一遍。结论先行:控制协议100%破解,签名算法实测跑通,但最终卡在了未Root手机的本地令牌提取上。

今天这篇,如实记录这48小时里的全套技术细节、踩过的连环大坑,以及我提取出的全部中间产物。如果你有闲置的Root手机或模拟器,拿着这篇记录,你可以直接通关。

第一阶段:暴力拆解,从茫茫代码里找线索

京东小家接入Home Assistant智能家居记录

我的测试机是一台未Root的一加手机(Android 16),空调已经在云端在线。

第一步,先想办法把APP的安装包扒下来。通过无线ADB连上手机,一句 adb pull,把高达 219MB 的 base.apk 拽到了电脑上。

简单看了一下架构,这APP是个典型的缝合怪:UI层用的是 Flutter,设备控制走的是自家的 JoyLink 物联网协议,同时包里还塞满了涂鸦、云米、美的等第三方SDK。

丢进 Jadx 进行全量反编译,由于代码量极大(43000多个类),干等不仅浪费时间还容易死机。我直接写了个 Python 脚本,对着解包出来的 dex 文件做了一次暴力字符串扫描,用 smart.jd.comjoylinkfunctionId 等关键字过滤。

这个小技巧帮我省了至少一个小时,瞬间锁定了三个核心文件:

classes18.dex:负责设备控制的服务层

classes20.dex:登录逻辑封装

classes17.dex:底层统一登录组件

第二阶段:核心突破,挖出完整协议与签名算法

京东小家接入Home Assistant智能家居记录

顺藤摸瓜,我在 URLConstant.java 里找到了整个智能云的 API 清单。

网关的 Base URL 是 [https://api.smart.jd.com](https://api.smart.jd.com)。所有的核心动作都明明白白摆在那:

获取设备列表:/c/service/integration/v1/getDeviceList

下发控制指令:/c/service/integration/v1/controlDevice_v1

状态快照:/c/service/integration/v1/getDeviceSnapshot_v1

产品模板:/c/service/getProductTemplate

稍微抓一下包就能看出,它的控制请求体长这样:{json: {feed_id: 123456, command: [{stream_id: ..., current_value: ...}], version: 2.0}}。其中 feed_id 是设备ID,stream_id 代表开关、温度、模式等具体属性。

重点来了:怎么伪造请求?

大厂的API不可能让你随便调,肯定有签名校验。在 RestClient#getAuthorization 里,我完整还原了它的 HMAC 签名算法。非常有意思,它的签名不仅绑定了请求体,还绑定了手机机型、系统版本甚至是年积日(一年中的第几天)。

我把这段逻辑用 Python 复刻了出来:

Python

```python
APP_ID = a188caaf009839ba200bb55bb8fa38407a595c2a
HMAC_KEY = e685c8d1daa7e4dec8821a3df41c0b34a56db779

def make_authorization(method, body, when):

构造时间戳

timestamp = when.strftime(%Y-%m-%dT%H:%M:%S.) + f{when.microsecond//1000:03d} + Z
day = when.timetuple().tm_yday

将App版本、机型、系统版本、年积日进行MD5

strc = md5hex(Android + 2.3.1 + PKR110 + 16 + : + str(day))

拼装最终签名字符串并做 HMAC-SHA1

signstr = strc + method.lower() + jsonbody + body + timestamp + APPID + str_c
sig = base64(hmacsha1(HMACKEY, sign_str))

return fsmart {APP_ID}:::{sig}:::{timestamp}

```
代码写完,我迫不及待地构造了一个假令牌(tgt)发给服务器测试。

服务器秒回:{status:-4, errorInfo:登录已过期,请重新登录}

看到这个报错,我长舒了一口气,它提示未登录,而不是签名错误! 这说明我们复刻的签名算法是完美的,成功骗过了网关的校验机制。

现在,距离成功只差最后一块拼图:拿到真正的登录令牌(tgt)

第三阶段:登录深渊,连环踩坑记

京东小家接入Home Assistant智能家居记录

这套APP用的是内部统一的 wjlogin SDK,网关需要的 tgt 就是 SDK 里的 A2 令牌。但这个 A2 存在 APP 的私有目录下,我的手机没有 Root,根本读不到。

既然本地拿不到,我能不能通过网页版扫码登录,抓取网页端的凭证来代替?

事实证明,我一脚踩进了一个深不见底的连环坑里。

坑1:相册扫码被拒

我用脚本把官方登录二维码保存到手机,试图用APP的扫一扫-相册识别来授权。结果APP直接弹窗请使用相应客户端进行扫码。起初我以为是相册反钓鱼,后来查证发现是请求接口里的 appid 不对。网页版现在用的 appid 是133,而我一开始抓的是别处的1338。改对之后,手机立马弹出了正常的确认页。

坑2:隐秘的 Cookie 校验

网页扫码的 check 接口一直报错参数异常。查了半天才发现,新版接口要求必须在 Header 里带上 Cookie: ptqrtoken=md5(token)。这个 Cookie 是网页前端 JS 动态算出来写进去的,纯 Python 脚本如果不模拟这步,服务器就会直接拒收。

坑3:风控与 TLS 指纹

扫码成功后,拿着票据去换真正的 Token 时,接口返回了 riskCode:1100,直接触发了认证魔方的滑块验证。普通的 Python Requests 库直接被秒杀了。为了绕过这个风控,我换上了 curl_cffi 库,伪装成 Chrome 浏览器的 TLS 指纹,这才顺利放行。

坑4:时代的眼泪,pt_key 没了

很多搞过这个平台签到脚本的人都知道 pt_key。但在这次抓包中我发现,pt_key 已经彻底成为历史,取而代之的是新的 SSO 票据 thor

费了九牛二虎之力,我终于写出了第三代全自动扫码登录脚本,成功拿到了包含 thor 在内的全套最新网页凭证。

我满怀期望地把 thor 塞进空调的控制接口里。

结果网关冷酷地返回了:401 token invalid

终局宣告:智能云的 WL 网关,只认 APP 内部生成的 A2 令牌,所有的网页系凭证(包括最新的 thor)全部无效。 这个平台的鉴权体系,内外已经彻底分叉了。

复盘与接力

京东小家接入Home Assistant智能家居记录

到这里,我的本地折腾之旅只能暂时画上句号。因为我不打算把日常使用的主力机拿去 Root。

但我已经把路彻底铺平了。如果你想继续,接下来的操作极其简单:

搞个带 Root 的模拟器(比如雷电或 MuMu),装上这APP。

在模拟器里真实扫码登录(避免相册限制)。

用 Frida 直接 Hook WJLoginHelper.getA2() 接口,或者去私有目录读出 A2 令牌。

把令牌填进我已经写好的 ac_control.py 脚本里。

只要拿到凭证,调用 getDeviceList 拿到空调的 feed_id,再看看产品模板里的 stream_id,就能实现完美的本地控制了。

这次最大的教训是:搞这种大平台的接口,一开始就应该去翻官方前端的 JS 代码(用浏览器的 performance API 抓真实请求),能少走很多弯路。

虽然最后空调没能在这个周末吹进 HA 的生态里,但把这套铜墙铁壁般的加密协议一点点拆解开的过程,本身已经足够过瘾了。思路和脚本都留在这里,有想法的硬核玩家,欢迎接力。

京东小家接入Home Assistant智能家居记录
展开 收起
1评论

  • 精彩
  • 最新
  • 果然看不懂

    校验提示文案

    提交
提示信息

取消
确认
评论举报

相关文章推荐

更多精彩文章
更多精彩文章
最新文章 热门文章
0
扫一下,分享更方便,购买更轻松