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

 找回密码
 立即注册
楼主: idreamshen

[硬件DIY] 初步跑通了vrf刷写esphome固件

[复制链接]

10

主题

99

帖子

1370

积分

金牌会员

Rank: 6Rank: 6

积分
1370
金钱
1271
HASS币
0
发表于 2023-7-18 11:10:13 | 显示全部楼层
本帖最后由 ssspp 于 2023-7-18 11:14 编辑

它这个有带TCP,你要问问厂家有没有带TCP 透传功能,没有的话就买个485串口服务器,用NODERED的TCP 联接

我家用的设备不一样,但原理是一样的,要根据设备协议修改
先在配置文件里添加自定义空调,当然你也可以直接用nodered发送MQTT让HA自动发现

mqtt:
  climate:
    - name: 空调书房
      unique_id: ac04
      modes:
        - "off"
        - "heat"
        - "dry"
        - "cool"
        - "fan_only"
      fan_modes:
        - "高"
        - "中"
        - "低"
        - "自动"
      mode_command_topic: "command/AC/04/ms"
      fan_mode_command_topic: "command/AC/04/fs"
      temperature_command_topic: "command/AC/04/wd"
      current_temperature_topic: "state/AC/04/hj"
      mode_state_topic: "state/AC/04/ms"
      temperature_state_topic: "state/AC/04/wd"
      fan_mode_state_topic: "state/AC/04/fs"
      precision: 1
      qos: 0
    - name: 空调大厅
      unique_id: ac01
      modes:
        - "off"
        - "heat"
        - "dry"
        - "cool"
        - "fan_only"
      fan_modes:
        - "高"
        - "中"
        - "低"
        - "自动"
      mode_command_topic: "command/AC/01/ms"
      fan_mode_command_topic: "command/AC/01/fs"
      temperature_command_topic: "command/AC/01/wd"
      current_temperature_topic: "state/AC/01/hj"
      mode_state_topic: "state/AC/01/ms"
      temperature_state_topic: "state/AC/01/wd"
      fan_mode_state_topic: "state/AC/01/fs"
      precision: 1
      qos: 0

多少个就以此类推



[{"id":"3d2e78c0.0e4bd8","type":"tcp request","z":"48ab0e4.b1ce5f","name":"大金空调 2.163:1106","server":"192.168.2.163","port":"1106","out":"sit","ret":"buffer","splitc":" ","newline":"","trim":false,"tls":"","x":720,"y":160,"wires":[["9c997b58.1409a8","cca43bac.1614b8"]]},{"id":"acc1d7b2.9adca8","type":"inject","z":"48ab0e4.b1ce5f","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"240","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":260,"y":160,"wires":[["2f8c2ba3.42b044"]]},{"id":"2f8c2ba3.42b044","type":"function","z":"48ab0e4.b1ce5f","name":"发送查询9台机","func":"//01 04 07 D0 00 06 70 85\n/*\n其中查询: 01 04 07 D0 00 06 70 85\n 01 从机地址 01~15\n 04 功能代码 04 查询\n 07 D0 寄存器 32001 的地址是 0x07d0\n 00 06 查询 6 个寄存器\n 70 85 校验 CRC16\n1、1楼客厅 2、二楼主卧 3、二楼东房 4、书房 5、三楼西房 6、三楼东房 7、三楼南房 8、餐厅 9、厨房\n*/\n//010607D910FF14C5\n\nvar dd = new Buffer([1,3,0,0,0,54,197,220]);\nmsg.payload = dd;\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":500,"y":160,"wires":[["3d2e78c0.0e4bd8"]]},{"id":"9c997b58.1409a8","type":"function","z":"48ab0e4.b1ce5f","name":"分析全部","func":"if(msg.payload.length != 113 || msg.payload[2] != 108){\n    return;\n}\n\nvar nmsg=[];\nvar ktz = flow.get(\"kt\").空调列表;\nvar top = \"state/AC/0\"\nfor (var bh =1;bh<10;bh++){\n    let wz = bh*12 -9;\n    gxyt(bh,wz);\n}\n\nif(nmsg.length > 0){\n    return [nmsg];\n}\n\nfunction gxyt(kthb,wz){\n    var kt = ktz[kthb];\n    let tic = top + String(kthb)+\"/\";\n    if (kt.同步 == false){\n        var ha = global.get(\"homeassistant\").homeAssistant.states;\n        var cskt = ha[kt.haid];\n        if (cskt == null){\n            node.error(kt.haid);\n            return;\n        }\n        qms(kt,wz,tic);\n        qwd(kt,wz,tic);\n        qfs(kt,wz,tic);\n        qhj(kt,wz,tic);\n        kt.同步 = true;\n        return [nmsg];\n    }\n    if(kt.开关 != msg.payload[wz + 1] || kt.模式 != msg.payload[wz +3]){//改变开关\n        qms(kt,wz,tic);\n    }\n    if(kt.温度 != msg.payload[wz + 5]){//改变温度\n        qwd(kt,wz,tic);\n    }\n    if(kt.风速 != msg.payload[wz + 7]){//改变风速\n        qfs(kt,wz,tic);    \n    }\n    if(kt.环境 != msg.payload[wz + 9]){//改变环境\n        qhj(kt,wz,tic);\n    }\n    kt.故障= msg.payload[wz + 11];//7\n}\n\nfunction qms(kt,wz,topic){\n    let data1 ={};\n    data1.qos = 0;\n    data1.retain= true;\n    data1.topic = topic + \"ms\";\n    kt.开关 = msg.payload[wz + 1];//2\n    kt.模式 = msg.payload[wz + 3];\n    if (kt.开关 == 0){\n        data1.payload =\"off\";\n    }else if(kt.模式 == 2){\n        data1.payload =\"cool\"; \n    }else if(kt.模式 == 4){\n        data1.payload =\"fan_only\"; \n    }else if(kt.模式 == 1){\n        data1.payload =\"heat\"; \n    }else{\n        data1.payload =\"dry\"; \n    }\n    nmsg.push(data1);\n}\nfunction qwd(kt,wz,topic){\n    kt.温度 = msg.payload[wz + 5];//3\n    let data3 ={};\n    data3.qos = 0;\n    data3.retain= true;\n    data3.topic = topic + \"wd\";\n    data3.payload = kt.温度;\n    nmsg.push(data3); \n}\nfunction qfs(kt,wz,topic){\n    kt.风速 = msg.payload[wz + 7];//4\n    let data2 ={};\n    data2.qos = 0;\n    data2.retain= true;\n    data2.topic = topic + \"fs\";\n    if(kt.风速 == 0){\n        data2.payload= \"自动\";\n    }else if(kt.风速 == 1){\n        data2.payload= \"低\";\n    }else if(kt.风速 == 2){\n        data2.payload= \"中\";\n    }else{\n        data2.payload= \"高\";\n    }\n    nmsg.push(data2);\n}\nfunction qhj(kt,wz,topic){\n    kt.环境= msg.payload[wz + 9];//6\n    let data4 ={};\n    data4.qos = 0;\n    data4.retain= true;\n    data4.topic = topic + \"hj\";\n    data4.payload = kt.环境;\n    nmsg.push(data4);\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":940,"y":140,"wires":[["44bdbda5.428624"]]},{"id":"1655c428.a5619c","type":"function","z":"48ab0e4.b1ce5f","name":"初始数据","func":"var kt = {};\n//1、1楼客厅 2、二楼主卧 3、二楼东房 4、书房 5、三楼西房 6、三楼东房 7、三楼南房 8、餐厅 9、厨房\nkt.空调列表={};\nvar ktid =[\"climate.kong_diao_da_ting\",\n            \"climate.kong_diao_zhu_wo\",\n            \"climate.kong_diao_dong_fang\",\n            \"climate.kong_diao_shu_fang\",\n            \"climate.kong_diao_san_lou_xi_fang\",\n            \"climate.kong_diao_san_lou_dong_fang\",\n            \"climate.kong_diao_san_lou_nan_fang\",\n            \"climate.kong_diao_can_ting\",\n            \"climate.kong_diao_chu_fang\"];\nfor (var i = 0;i<9;i++){\n    let yg ={};\n    yg.haid = ktid;\n    yg.开关 = 100;\n    yg.模式 = 100;\n    yg.风速 = 100;\n    yg.温度 = 100;\n    yg.环境 = 100;\n    yg.同步 = false;\n    kt.空调列表[i+1] =yg;\n}\nlet csyg ={};\n    csyg.haid = \"climate.kong_diao_cha_shi\";\n    csyg.开关 = 100;\n    csyg.模式 = 100;\n    csyg.风速 = 100;\n    csyg.温度 = 100;\n    csyg.环境 = 100;\n    csyg.同步 = false;\n    kt.空调列表[\"cskt\"] =csyg;\nlet slkt ={};\n    slkt.haid = \"climate.kong_diao_san_lou_ke_ting\";\n    slkt.开关 = 100;\n    slkt.模式 = 100;\n    slkt.风速 = 100;\n    slkt.温度 = 100;\n    slkt.环境 = 100;\n    slkt.同步 = false;\n    kt.空调列表[\"slkt\"] =slkt;\nflow.set(\"kt\",kt);\nif(msg.payload == 20){\n    return;\n}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":260,"y":100,"wires":[["2f8c2ba3.42b044","2a89dcb7.c102c4"]]},{"id":"134c780b.883f88","type":"inject","z":"48ab0e4.b1ce5f","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":true,"onceDelay":"1","topic":"","payload":"20","payloadType":"num","x":110,"y":100,"wires":[["1655c428.a5619c"]]},{"id":"44bdbda5.428624","type":"delay","z":"48ab0e4.b1ce5f","name":"","pauseType":"delay","timeout":"5","timeoutUnits":"milliseconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"outputs":1,"x":1100,"y":100,"wires":[["22596125.80dd9e"]]},{"id":"e111617b.9f9d8","type":"mqtt in","z":"48ab0e4.b1ce5f","name":"","topic":"command/AC/#","qos":"0","datatype":"utf8","broker":"108404e3d6f63908","nl":false,"rap":false,"inputs":0,"x":480,"y":100,"wires":[["e7a74817.03d208"]]},{"id":"e7a74817.03d208","type":"function","z":"48ab0e4.b1ce5f","name":"MQTT操作分析","func":"var bh =parseInt(msg.topic.substr(11,2));\nvar xm = msg.topic.substr(14,2);\nif (bh < 1 || bh > 9){\n    return;\n}\nvar ktz= flow.get(\"kt\");\nmsg.bh = bh;\nvar kt = ktz.空调列表[bh];\nif (typeof(kt) == \"undefined\"){\n    return;\n}\nvar dd = [0x01,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff];\ndd[1] = bh-1;\nvar nmsg = {};\nif (xm == \"ms\"){\n    if (msg.payload == \"off\"){ //关制冷\n        dd[2]= 0;\n    }else if (msg.payload == \"cool\"){ //制冷\n        dd[2] = 1;\n        dd[3] = 2;\n    }else if (msg.payload == \"dry\"){ //除湿\n        dd[2] = 1;\n        dd[3] = 8;\n    }else if (msg.payload == \"fan_only\"){ //风\n        dd[2] = 1;\n        dd[3] = 4;\n    }else if (msg.payload == \"heat\"){ //制热\n        let yf = new Date().getMonth(); \n         dd[2] = 1;\n         dd[3] = 1;\n        if (yf>1 && yf<10){ // 2 月到10月 不能制热\n           dd[3] = 2; \n        }\n    }else{\n        return;\n    }\n    nmsg.payload = sczj(dd);\n    return nmsg;\n}else if(xm == \"wd\"){\n    if (msg.payload > 32){\n       msg.payload = 32; \n    }else if(msg.payload < 16){\n        msg.payload = 16; \n    }\n    dd[4] = msg.payload;\n    nmsg.payload = sczj(dd);\n    return nmsg;\n}else if(xm == \"fs\"){\n    if (msg.payload == \"自动\"){\n        dd[5] = 0;\n    }else if (msg.payload == \"高\"){\n        dd[5] = 3;\n    }else if (msg.payload == \"中\"){\n        dd[5] = 2;\n    }else if (msg.payload == \"低\"){\n        dd[5] = 1;\n    }else{\n        return;\n    }\n    nmsg.payload = sczj(dd);\n    return nmsg;\n}\n\n\n\n\nfunction sczj(zjsz){\n    var zjj= new Buffer(zjsz);\n    var zs = 0;\n    for(var t=0;t<9;t++){\n       zs += zjj[t]; \n    }\n    zjj[9] =zs;\n    msg.zs = zjj[9];\n    return zjj;\n}\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":660,"y":100,"wires":[["3d2e78c0.0e4bd8"]]},{"id":"cca43bac.1614b8","type":"function","z":"48ab0e4.b1ce5f","name":"返回分析","func":"if (msg.payload[0] !== 1 || msg.payload.length !== 10){\n    return;\n}\nfor (var t=1;t<8;t++){\n    if (msg.payload == 0xff){\n        return;\n    }\n}\nvar bh = msg.payload[1] + 1;\nif (bh < 1 || bh >9){\n    return;\n}\nvar kt = flow.get(\"kt\").空调列表[bh];\nvar nmsg=[];\nvar topic = \"state/AC/0\"+String(bh)+\"/\";\nif (kt.同步 == false){\n    var ha = global.get(\"homeassistant\").homeAssistant.states;\n    var cskt = ha[kt.haid];\n    if (cskt == null){\n        return;\n    }\n    qms();\n    qwd();\n    qfs();\n    qhj();\n    kt.同步 = true;\n    return [nmsg];\n}\nif(kt.开关 != msg.payload[2] || kt.模式 != msg.payload[3]){//改变开关\n    qms();\n}\nif(kt.温度 != msg.payload[4]){//改变温度\n    qwd();\n}\nif(kt.风速 != msg.payload[5]){//改变风速\n    qfs();    \n}\nif(kt.环境 != msg.payload[6]){//改变环境\n    qhj();\n}\nkt.故障= msg.payload[7];//7\n//01 01 02 14 03 00 19 95 11 DA (开启 制冷 20度 高风 无风向 室温25 大金故障U5 有切换权运转限制中)\n    \nif(nmsg.length > 0){\n    return [nmsg];\n}\n\n\nfunction qms(){\n    let data1 ={};\n    data1.qos = 0;\n    data1.retain= true;\n    data1.topic = topic + \"ms\";\n    kt.开关 = msg.payload[2];//1\n    kt.模式 = msg.payload[3];\n    if (kt.开关 == 0){\n        data1.payload =\"off\";\n    }else if(kt.模式 == 2){\n        data1.payload =\"cool\"; \n    }else if(kt.模式 == 4){\n        data1.payload =\"fan_only\"; \n    }else if(kt.模式 == 1){\n        data1.payload =\"heat\"; \n    }else{\n        data1.payload =\"dry\"; \n    }\n    nmsg.push(data1);\n}\nfunction qwd(){\n    kt.温度 = msg.payload[4];//3\n    data3 ={};\n    data3.qos = 0;\n    data3.retain= true;\n    data3.topic = topic + \"wd\";\n    data3.payload = msg.payload[4];\n    nmsg.push(data3); \n}\nfunction qfs(){\n    kt.风速 = msg.payload[5];//4\n    let data2 ={};\n    data2.qos = 0;\n    data2.retain= true;\n    data2.topic = topic + \"fs\";\n    if(kt.风速 == 0){\n        data2.payload= \"自动\";\n    }else if(kt.风速 == 1){\n        data2.payload= \"低\";\n    }else if(kt.风速 == 2){\n        data2.payload= \"中\";\n    }else{\n        data2.payload= \"高\";\n    }\n    nmsg.push(data2);\n}\nfunction qhj(){\n    kt.环境= msg.payload[6];//6\n    let data4 ={};\n    data4.qos = 0;\n    data4.retain= true;\n    data4.topic = topic + \"hj\";\n    data4.payload = msg.payload[6];\n    nmsg.push(data4);\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":940,"y":180,"wires":[["22596125.80dd9e"]]},{"id":"22596125.80dd9e","type":"mqtt out","z":"48ab0e4.b1ce5f","name":"","topic":"","qos":"0","retain":"true","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"108404e3d6f63908","x":1310,"y":100,"wires":[]},{"id":"108404e3d6f63908","type":"mqtt-broker","name":"","broker":"127.0.0.1","port":"1883","clientid":"","autoConnect":true,"usetls":false,"protocolVersion":"4","keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","birthMsg":{},"closeTopic":"","closeQos":"0","closePayload":"","closeMsg":{},"willTopic":"","willQos":"0","willPayload":"","willMsg":{},"userProps":"","sessionExpiry":""}]
回复

使用道具 举报

6

主题

96

帖子

1653

积分

论坛技术达人

积分
1653
金钱
1542
HASS币
75
 楼主| 发表于 2023-7-18 12:35:07 | 显示全部楼层
ssspp 发表于 2023-7-18 11:10
它这个有带TCP,你要问问厂家有没有带TCP 透传功能,没有的话就买个485串口服务器,用NODERED的TCP 联接

...

问下这些 tcp padyload 是怎么逆向解析出来的?
公众号+海鲜市场: 万能浇筑哥
回复

使用道具 举报

10

主题

99

帖子

1370

积分

金牌会员

Rank: 6Rank: 6

积分
1370
金钱
1271
HASS币
0
发表于 2023-7-18 13:25:54 | 显示全部楼层
为什么要逆向,空调网关都有公开协议说明的,根据协议进行解析后转HA格式,你用ESPHOME也是得转,不建议用ESPHOME转,过程是一样的直接在NODERED里写方便,可以实时调试,不用改装原设备!当然你也可以直接用ESPHOME写个当透传直接到NODERED里转协议
回复

使用道具 举报

6

主题

96

帖子

1653

积分

论坛技术达人

积分
1653
金钱
1542
HASS币
75
 楼主| 发表于 2023-7-18 13:33:42 | 显示全部楼层
ssspp 发表于 2023-7-18 13:25
为什么要逆向,空调网关都有公开协议说明的,根据协议进行解析后转HA格式,你用ESPHOME也是得转,不建议用E ...

“空调网关都有公开协议说明”能给个链接指引吗?我一直搜不到,所以只能抓包串口自己逆向分析
公众号+海鲜市场: 万能浇筑哥
回复

使用道具 举报

10

主题

99

帖子

1370

积分

金牌会员

Rank: 6Rank: 6

积分
1370
金钱
1271
HASS币
0
发表于 2023-7-18 20:31:25 | 显示全部楼层
idreamshen 发表于 2023-7-18 13:33
“空调网关都有公开协议说明”能给个链接指引吗?我一直搜不到,所以只能抓包串口自己逆向分析 ...

找你买网关的人要,都有
回复

使用道具 举报

1

主题

28

帖子

209

积分

中级会员

Rank: 3Rank: 3

积分
209
金钱
181
HASS币
0
发表于 2023-7-21 14:43:42 | 显示全部楼层
咸鱼423那家?我是通过米家+HA接入homekit的。但是有个问题,米家能显示室温,HA不显示,homekit显示室温21°
回复

使用道具 举报

6

主题

96

帖子

1653

积分

论坛技术达人

积分
1653
金钱
1542
HASS币
75
 楼主| 发表于 2023-7-21 23:03:00 | 显示全部楼层
Always_67 发表于 2023-7-21 14:43
咸鱼423那家?我是通过米家+HA接入homekit的。但是有个问题,米家能显示室温,HA不显示,homekit显示室温21 ...

是的。homekit温度显示21是因为这个 vrf 的 climate 实体没有 current_temperature 属性,默认温度就显示21了。

https://github.com/jcwillox/hass-template-climate 你可以试试用这个 climate template 自己生成一个新的 climate 再接入 homekit
公众号+海鲜市场: 万能浇筑哥
回复

使用道具 举报

6

主题

96

帖子

1653

积分

论坛技术达人

积分
1653
金钱
1542
HASS币
75
 楼主| 发表于 2023-7-22 08:21:43 | 显示全部楼层
本帖最后由 idreamshen 于 2023-7-22 15:51 编辑

主体功能初步完成了,控制+读取数据。

微信图片_20230722154907.jpg 微信图片_20230722082002.png 微信图片_20230722082013.png
公众号+海鲜市场: 万能浇筑哥
回复

使用道具 举报

46

主题

332

帖子

3394

积分

论坛元老

Rank: 8Rank: 8

积分
3394
金钱
3062
HASS币
0
发表于 2023-7-22 15:57:53 | 显示全部楼层
期待,那不是控制成本大大降低了
回复

使用道具 举报

6

主题

96

帖子

1653

积分

论坛技术达人

积分
1653
金钱
1542
HASS币
75
 楼主| 发表于 2023-7-22 16:18:30 | 显示全部楼层
jck773656345 发表于 2023-7-22 15:57
期待,那不是控制成本大大降低了

不是,成本没降。这方案只是把 vrf 上的 wifi(esp32) 芯片替换成自己的 8266/32 再刷自定义的 esphome 固件。 vrf 网关还是得买,只不过能改成本地控制。
公众号+海鲜市场: 万能浇筑哥
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|Hassbian

GMT+8, 2024-11-24 19:16 , Processed in 0.383225 second(s), 32 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表