『瀚思彼岸』» 智能家居技术论坛

标题: 万和热水器API方式探索(23-12-15更新) [打印本页]

作者: linmohc    时间: 2023-12-13 16:48
标题: 万和热水器API方式探索(23-12-15更新)
本帖最后由 linmohc 于 2023-12-15 16:08 编辑

以下API逆向得到,一边还要编写程序接入到ha,基本上是用到哪写到哪,还需要继续完善,精力有限可能有不准确的地方,但是大致可用,欢迎大家一起讨论。

1. HTTP请求登录

POST https://rubyuserapi.vanward.com/api/user/login application/x-www-form-urlencoded

code=&mobile=手机号&password=万和智能app密码明文

响应:
  1. {"User":{"Uuid":"用户id需要保存后续用到","Token":"token需要保存后续用到","Mobile":"手机号","UnReadMsgCount":0},"Domain":["rubyusercomet.vanward.com"]}
复制代码


2. 刷新TOKEN

第一步获得的token在连接ws后失效,下次再连接除了用第一步重新登录,还可以用这个接口获得新token

POST https://rubyuserapi.vanward.com/api/user/autoLogin application/x-www-form-urlencoded

uuid=用户id&token=旧token

响应与第一步相同

3. 连接websocket

用第一步中返回的Domain字段中随便一个域名,固定端口2301构成,如:wss://rubyusercomet.vanward.com:2301/ws

使用的是binaryframe

连接后需要马上发送认证消息

数据包由heaer+payload构成,其中header固定5字节,第一位为操作码,后4字段为大端int32,标识payload长度,如发送Hello,操作码为1,构数据包如下:

0x01, 0x05, 0x00, 0x00, 0x00, 0x48, 0x65, 0x6C, 0x6C, 0x6F

payload是一个json对象

已知操作码:

0x00: 登录,响应与请求相同,payload:  {"Id": "用户UUid", "Token": "xxxx"}
0x0A: 心跳,响应与请求相同
WebSocket协议

登录请求操作码: 0x00
{"Id": "用户UUid", "Token": "xxx"}

登录响应操作码: 0x00
{
    "Code": 0,
    "Devices": [
        {
            "ActiveDate": "设备激活日期?",
            "Alias": "设备别名(在app中设置)",
            "DeviceId": "设备id,需要记录保存",
            "Mac": "设备mac地址",
            "Master": "暂时不知道什么东西",
            "Product": {
                "CtrlPageUrl": "http://local/u2",
                "FirmwareId": "固件id,估计没什么用",
                "Icon": "https://smart-vanward.oss-cn-shenzhen.aliyuncs.com/vanwardsmart/1/JSLQ27-LS5W16/%E8%AE%BE%E5%A4%87%E5%9B%BE%E6%A0%871585561034123.png",
                "Model": "JSLQ27-LS5W16",     // 设备型号
                "Name": "JSLQ27-LS5W16",
                "Pid": "不清楚有什么用处",
                "Script": {
                    "Content": "s[1] === 1 ? '已打开':'已关闭';",
                    "Showonoff": true
                },
                "Series": "LS5  系列号,这个要保存,后面需要用来判断功能",
                "Type": "燃气热水器",     // 设备类型,如果有多种类型设备需要用这个值进行判断
                "catagoryId": 0,
                "catagoryName": "燃气热水器"
            },
            "Status": [0,1,4,0,15,0,45,24,0,0,0,0,24,9,7,9,0,0,0,38,0,0,0,0,23,0,7,16,12,24,0,0,0,0,0,0],    // 设备状态包括水温模式等,详见下面
            "Version": "1.4.3",   // 固件版本
            "deviceType": 0,     // 看起来像设备类型,但是官方并没有用这个值进行判断,反而用的是Product.Type
            "firmwareId": "frt92421-1e3f-479e-a98b-aa5692da1599",
            "isOnline": true,     // 设备离线(如断开WiFi)这里为false
            "serverId": "comet-CNS-01"
        }
    ],
    "Msg": "登录成功"
}

--------------------------------------------------------------------------------
心跳请求操作码:0x0A
心跳只需要发header的5字节包出去即可,即固定
0x0A 0x00, 0x00, 0x00, 0x00, 0x00
连接空闲时每60秒要发送一次心跳,否则服务端会断开连接

心跳响应
无,服务器不发送响应
--------------------------------------------------------------------------------

设备心跳请求
  1. 无,不需要客户端发送,服务端会主动推送过来
复制代码

设备心跳响应操作码:0x23
{"Id":"设备id"}

--------------------------------------------------------------------------------

设备状态报告请求
  1. 无,不需要客户端发送,服务端会主动推送过来
复制代码

设备状态报告响应操作码:0x22

{"Id":"设备id", "Status": [0,1,4,0,15,0,45,24,0,0,0,0,24,9,7,9,0,0,0,38,0,0,0,0,23,0,7,16,12,24,0,0,0,0,0,0]}

--------------------------------------------------------------------------------
更新设备状态请求,操作码:0x04
{
        "Status": [1, 4, 44, 0, 15, 0, 40, 0, 0, 0, 0, 0],    // 写设备状态,与读状态序列不同注意甄别
        "Id": "设备id",
        "MsgId": 1,                                                     // 消息id,实际官方并没有实现此值增长,保持为1即可
        "Timestamp": 1702620580,                           // 当前Unix时间戳
        "Model": "JSLQ27-LS5W16",                         // 设备型号,从登录请求中获得
        "Series": "LS5"                                               // 设备系列,从登录请求中获得
}

更新设备状态请求



--------------------------------------------------------------------------------

读设备状态(这个是服务器端返回的Status字段
(因为家里只有万和热水器,没有其他万和设备,所以下面的状态可能在其他类型设备上不通用,但是所有万和热水器都适用下面的状态
索引 说明
1
热水器通电状态:0待机/1正常通电
2
热水器模式,1普通/2厨房/4节能/5自适温/6自定义1/7自定义2/8自定义3/21温水浴
4
未知
5
未知
6
水温
8
加热状态,需要按位与运算判断,1加热中/2通水中/4散热风扇/8防冻功能
11
实时产水量,需要/10为L/min
18
零冷水巡航模式设置,高地址第3位为水增压,高地址第5-8位为巡航模式
19
零冷水温度
20
未知
21
未知
23
手动零冷水巡航,0未运行/1运行中
25
未知
33
零冷水预约模式,0非预约模式/1预约模式

其中索引8加热状态要按位运算得出,如第8位非0时说明防冻功能正在运行,其他的直接取值即可

零冷水巡航模式设置(读18)
二进制数位
说明
B7
固定为0
B6
固定为0
B5
1为水增压
B4
固定为0
B3巡航模式,0关闭/1全天候/2点动
    其中预约模式为0
B2
B1
B0

--------------------------------------------------------------------------------

写设备状态(发送到服务器端的Status字段)

索引 说明
0
热水器通电状态,用读设备状态(1)初始化
1
模式,用读设备状态(2)初始化
2
水温,用读设备状态(6)初始化
3
未知,用读设备状态(25)初始化
4
未知,用读设备状态(4)初始化
5
零冷水巡航设置,用读设备状态(18)初始化
6
零冷水温度,用读设备状态(19)初始化
7
未知,用读设备状态(20)初始化
8
未知,用读设备状态(21)初始化
9
触发一次零冷水巡航,用读设备状态(23)初始化,此项设1时会触发一次巡航且热水器完成时自动停止。除非实现自动化需要,否则填0
10
固定为0
11
零冷水预约模式,用读设备状态(33)初始化

补充:
Series为LS5时,最低温度为30,否则为35


基于以上信息基本上可以对热水器的完全控制,这两天看情况会用Go实现一个简单的接口以供大家调用或参考。

有遗漏或错误的地方也欢迎大家一起继续探讨







作者: yxy2888    时间: 2023-12-14 09:21
厉害,可否指导研究一下万家乐的呢
作者: yxy2888    时间: 2023-12-14 09:22
https://bbs.hassbian.com/thread-21262-1-1.html
作者: yaojogd    时间: 2023-12-14 09:50
yxy2888 发表于 2023-12-14 09:22
https://bbs.hassbian.com/thread-21262-1-1.html

不是所有设备都支持快捷指令的,不支持快捷指令你的怎么用那个教程?你给个解决方案看下
作者: yxy2888    时间: 2023-12-14 13:05
yaojogd 发表于 2023-12-14 09:50
不是所有设备都支持快捷指令的,不支持快捷指令你的怎么用那个教程?你给个解决方案看下 ...

我的万家乐热水器,可以抓包,但不太懂
作者: linmohc    时间: 2023-12-14 17:08
yxy2888 发表于 2023-12-14 09:21
厉害,可否指导研究一下万家乐的呢

不好意思我这边没有万家乐的设备估计难帮上忙,总体思路差不多都是抓包再逆向得到的
作者: linmohc    时间: 2023-12-14 17:10
刚才编辑的内容保存后就不见了,稍后重新编辑一下
作者: aourwz    时间: 2023-12-14 17:21
[0,0,1,0,15,0,60,33,0,0,0,0,15,71,25,71,0,0,33,43,0,0,0,0,30,0,25,16,12,24,0,0,0,0,0,0]
这种结构的状态你能对应上吗?我看每次发送控制指令都会把所有的状态发到服务器
作者: aourwz    时间: 2023-12-14 17:26
本帖最后由 aourwz 于 2023-12-14 17:29 编辑
aourwz 发表于 2023-12-14 17:21
[0,0,1,0,15,0,60,33,0,0,0,0,15,71,25,71,0,0,33,43,0,0,0,0,30,0,25,16,12,24,0,0,0,0,0,0]
这种结构的状 ...

看错了,这是服务器发回来的,帖子已经更新了,刚刚没看到,感谢大佬
作者: linmohc    时间: 2023-12-14 17:27
aourwz 发表于 2023-12-14 17:21
[0,0,1,0,15,0,60,33,0,0,0,0,15,71,25,71,0,0,33,43,0,0,0,0,30,0,25,16,12,24,0,0,0,0,0,0]
这种结构的状 ...

并不是发送所有回去的,而且索引位置也有不同,后面再补充上来
作者: aourwz    时间: 2023-12-14 17:33
linmohc 发表于 2023-12-14 17:27
并不是发送所有回去的,而且索引位置也有不同,后面再补充上来

谢谢大佬,我家的万和热水器会隔几个月断开wifi,就连不上了,你的有这种情况吗?
作者: linmohc    时间: 2023-12-14 17:46
aourwz 发表于 2023-12-14 17:33
谢谢大佬,我家的万和热水器会隔几个月断开wifi,就连不上了,你的有这种情况吗? ...

我的是JSLQ27-LS5W16暂时没出现你这个情况,但是有一个IAM净水器有类似,没找到原因,猜测是固件本身的问题
作者: aourwz    时间: 2023-12-15 09:21
linmohc 发表于 2023-12-14 17:46
我的是JSLQ27-LS5W16暂时没出现你这个情况,但是有一个IAM净水器有类似,没找到原因,猜测是固件本身的问 ...

我也是这个型号的,过几个月就断一次,然后要重连,很麻烦
作者: 就要注册    时间: 2023-12-15 09:45
我以前自己学习抓包获取了状态,但弄没明白发送指令怎么搞的,只能用小爱同学发送指令。期待大佬的更新。
作者: Gen007    时间: 2023-12-22 23:59
大佬,这个包怎么分析?
请求头
GET http://newapi.machtalk.net/v2.0/8/user HTTP/1.1
ts: 1703260126947
uid: 4e87763b214c4edaa51d3154d7f058dd
key: c99c968e381455cae6006234b917efe3
Host: newapi.machtalk.net
Connection: Keep-Alive
Accept-Encoding: gzip
User-Agent: okhttp/3.8.1


响应的数据


211
{"server":"106.75.114.124:6778","code":0,"cityId":1607,"hasPassword":true,"cityIdLogin":1601,"uid":"4e87763b214c4edaa51d3154d7f058dd","modifyTime":"2023-12-22T23:48:46","nickname":"Gen","platformDesc":"万家乐用户系统","platformName":"macro","apikey":"c87213d8b00f49b5bd672b948de9a275","sex":0,"telephone":"13580572676","platformId":8,"provinceId":19,"extend":"","lastLoginTime":"2023-12-22T23:48:46","provinceIdLogin":19,"districtId":-1,"createTime":"2022-06-24T11:15:01","online":1,"status":1,"username":"u1656040501155"}
0
作者: wen4007    时间: 2024-10-26 09:41
初学者,看懂了第一步,也调通了,想用ESP32来控制零冷水,达到提前预热的目的,但后面没懂,楼主能在详细说一下整个流程
作者: wen4007    时间: 2024-12-23 14:35
看了这么多,都很麻烦,我想拆开热水器,用开关模块直接控制水泵,用米家
作者: hmhboy    时间: 2025-1-14 09:41
不知道还有下文吗?这个太复杂了搞不来啊。
作者: hayonghu    时间: 2025-3-3 00:41
Gen007 发表于 2023-12-22 23:59
大佬,这个包怎么分析?
请求头
GET http://newapi.machtalk.net/v2.0/8/user HTTP/1.1

key是动态的,需要看第一个TCP包,我来出个教程吧
作者: hayonghu    时间: 2025-5-1 21:20
我已经解开了,万家乐APP协议,做成单片机了
[attach]69443[/attach][attach]69444[/attach][attach]69445[/attach][attach]69446[/attach]






欢迎光临 『瀚思彼岸』» 智能家居技术论坛 (https://bbs.hassbian.com/) Powered by Discuz! X3.5