deiger/AirCon

AEH-W4A1

Opened this issue · 44 comments

Hi,
I've found your repository the first day of creation. I've tried the script with AEH-W4A1 but this module does not seem to have an open LAN port.
It has 8888 TCP open but it just replays everything you send to it.
With Wireshark I found it communicates to the servers with port 1024 TCP, but it is closed/filtered on LAN.

It communicates with a couple of servers, but the main one is:
hi-smartlife.topfuturesz.com (TCP Port 7820, App Hi-Smart Life)

I've been able to replay some TCP packets to turn on/off, change the fan speed, get and set the temperature, turn off the dimmer and other things.

I will try the new script, but upon sniffing traffic, I couldn't find any lan_key in the communication between the servers, so I think this module is out of luck with LAN control.
This module does not work with Hi-Smart AC.

Hi,
I haven't tried https://play.google.com/store/apps/details?id=com.qd.android.livehome (Hi-Smart Life), but it should work for https://play.google.com/store/apps/details?id=com.accontrol.europe.hisense (Hi-Smart AC).
I'll try finding out if the former is using the same protocol.

I pried into the Hi-Smart Life app, and it seems entirely different. It is not based on aylanetworks code, but has something by xinlianfeng.
I'm afraid if none of the aylanetworks-based apps works, then a different solution would be needed.

https://github.com/cgdgithub/ControlJavaEdition

Searching for xinlianfeng I found this repository, it seems that this is the same way they communicate with Hi-Smart Life app, it also states that the module port is 8888 which is correct, and also seems that this port is used to receive authenticated mqtt commands.

EDIT: The same package com.xinlianfeng.livehome is mentioned inside Hi-Smart Life app, so yeah this is the source code for controling the AC.

Cool!
I couldn't find any mention for MQTT within the current app, but it is definitely worth a shot.
If you could configure it to work against an MQTT broker your life would be much easier.

Hi guys,
I'm working on reverse engineering AEH-W4A1. Luckily it is much simpler than newer revision: if on lan, after contacting the china server to obtain the list of ac, it communicates with them directly on port 8888 via a plain serial protocol.

I used Packet Capture, an android app to MITM sniff packets.

For example, if you raw send AT+XMV to port 8888 of ac you obtain a response like +XMV:4.4.6 (it can be useful to identify the AEH-W4A1 module and also to search in the LAN of all the conditioners)

And if you send
F4F500400C00000101FE0100006600000001B3F4FB
the response is the current state, for example
F4F50140490100FE01010101006600010000201A211D80808001A10000000000000000000000050000000000215E2300000000000000000000000000080000000000000000000000000000000000053DF4FB

I searched a lot online information about the protol used, but I found only an old pamplet about a similar serial protol developed together by Hisense and Hitachi. Probably an archaic version of the current one, but of no use.

Unfortunately I do not have the skills to develop an add-on for Home Assistant, but if someone wanted to do it I could put myself to decode all the bytes of the protocol and reconstruct its functioning. I have already done some work ;)

Hi!
I'd be terribly interested in the decoding of the protocol! Once it is done (i.e. we need just to send bytes to device_ip:8888 to get status and send commands I think it should be relatively trivial to implement control via home assistant!

(or just a mqtt translator)

@bannhead Unfortunately with +XMV:4.4.7, I only get a response directly from the AC if i send AT+XMV.
All the other commands it just echoes what you wrote.

The protocol seems to be a somehow encoded JSON string, you can learn more here: https://github.com/cgdgithub/ControlJavaEdition/blob/master/src/com/xinlianfeng/android/livehome/devices/base/DevicesLogic.java#L461

Anyway, you can do guessing with many replies, for example, in the status response F4F50140490100FE01010101006600010000201A211D80808001A10000000000000000000000050000000000215E2300000000000000000000000000080000000000000000000000000000000000053DF4FB

in the series of bytes 201A21 the byte 20 means that the AC is Off, while 28 means that the AC is On; while the byte 21 represents the current temperature (in my testing, 1C was 28°C, 1B 27°C, 1A 26°C, 19 25°C and 17 23°C)

Unfortunately the actual parsing logic here is hidden in the JNI-wrapped libhisense.so file, in functions like Java_com_xinlianfeng_android_livehome_hisense_ProtocolNative_parsePara and Java_com_xinlianfeng_android_livehome_hisense_ProtocolNative_buildPara.
Likely the best option to analyse the entire protocol would be to link to the .so file in AndroidStudio and feed it with different inputs.

It's a serial protocol, JSON is used only in app for code semplicity; communication to and from AC are raw bits sent in tcp over port 8888.
I extracted deviceprotocol.java and obtained the bit code to create and read data packets.

Standard response packet
F4F50140490100FE010101010066000108002A1D1F1B80808001D10000000000000000C000800500000000001E481B00000000000000000000000000080000000000000000000000000000000000069DF4FB
F4F5 header
01 packet from AC (00 for packet sent)
40 need further analysis - does not change
49 length in byte: hex to dex -> 73 + 9 (constant) = correct length
0100FE0101010100 need further analysis - does not change
6600 packet type (66 ->102) and sub type
01 need further analysis - does not change - maybe data delimiter
08002A1D1F1B80808001D10000000000000000C000800500000000001E481B00000000000000000000000000080000000000000000000000000000000000 data
06 it seems the number of iterations of crc
9D 1 byte checksum calculated from header (excluded) to previous byte (06 - excluded) +1
F4FB footer

And here the data part converted in binary and divided using the table obtained from java analysis:
0 00010000 00000000 01 (5->) 0 1010 00011101 00011111 00011011 (10->) 10000000 10000000 100000000 00 000011 (15->) 101 00010 000000 0 000 (20->) 00000 00 000000 0 000 (25->) 0000 00 000000 0 000 (30->) 0000 00 0000000 0000 000 (35->) 1 1 0 0 0 (40->) 0 0 0 0 0 (45->) 0 0 0 0 0 (50->) 0 1 0 0 0 (55->) 0 0 0 0 0 (60->) 0 0 00101 00000000 00000000 (65->) 00000000 00000000 00000000 00011110 01001000 (70->) 00011011 00000000 00000000 0000000000000000 0000000000000000 (75->) 0000000000000000 000000000 00000000 00000000 0000000000000000 (80->) 00010000 0000 0 0000 0 (85->) 0 0 0 0 0 (90->) 0 00 0 0 0 (95->) 0 0 0 0 00000000 (100->) 00000000 00000000 00000000 00000000 00000000 (105->) 00000000 00000000 00000000 00000000 00000000 (110->) 0000000 0 00000000 0000000

1 WindSpeedMode 2 AirVolume 3 SleepMode 4 WindDirectionSwitch 5 LaunchSwitch 6 WorkMode 7 IndoorSetTemp 8 IndoorCurrentTemp 9 IndoorPipeTemp 10 IndoorSetHumi 11 IndoorCurrentHumi 12 RecvFeelIndoorTemp 13 FeelControl 14 FeelIndoorTempOffset 15 TempDisplayMode 16 AutoAndDehumiModeTempOffset 17 NormalTimingValue 18 NormalTimingValidity 19 RTCHourExplain 20 RTCHourValue 21 RTCMinuteExplain 22 RTCMinuteValue 23 RTCPowerOnHourExplain 24 RTCPowerOnControl 25 RTCPowerOnHourValue 26 RTCPowerOnMinuteExplain 27 RTCPowerOnMinuteValue 28 RTCPowerOffHourExplain 29 RTCPowerOffControl 30 RTCPowerOffHourValue 31 RTCPowerOffMinuteExplain 32 RTCPowerOffMinuteValue 33 WindValvePosition 34 DehumiMode 35 DualModeSwitch 36 StrongSwitch 37 CombinConserveEnergySwitch 38 ConserveEnergySwitch 39 ElectricHeatSwitch 40 NaturalWindSwitch 41 LeftRightWindSwitch 42 UpDownWindSwitch 43 SmokeSwitch 44 VoiceControl 45 MuteSwitch 46 SmartEyeSwitch 47 OutdoorCleanSwitch 48 IndoorCleanSwitch 49 FanSwitch 50 CleanerSwitch 51 IndoorElectricityBoard 52 RightWindSwingSwitch 53 LeftWindSwingSwitch 54 IndoorStrainerCleanStatus 55 TempDisplaySwitch 56 LedSwitch 57 DisplayScreenShineSwitch 58 BackgroundLightSwitch 59 IndoorEEPROMUpgrade 60 Model 61 BeforeWifiControl 62 BeforeIrAndButtonControl 63 IndoorAlarm1 64 IndoorAlarm2 65 CompressorRunHz 66 CompressorTargetHz 67 ToDriverHz 68 OutdoorEnvironmentTemp 69 OutdoorCondenserTemp 70 CompressorExhaustTemp 71 TargetExhaustTemp 72 OutdoorEXVOpening 73 Uab 74 Ubc 75 Uca 76 Iab 77 Ibc 78 Ica 79 UDCBus 80 Iuv 81 FanRunStatus 82 OutdoorUnitCurrentWorkStatus 83 FourWayValveStatus 84 OutdoorDefrostingCream 85 OutdoorFrost 86 DehumiValve 87 MultiSplit 88 TempControlPowerOff 89 ForceInnerStop 90 ForceInnerSpeed 91 ForceInnerWindValvePosition 92 FillGasIncreaseHan 93 CompressorPreheat 94 CompressorRibbonHeater 95 OutdoorElectricityBoard 96 OutdoorEEPROMUpgrade 97 OutdoorFaultDisplay 98 OilReturn 99 OutdoorAlarm1 100 OutdoorAlarm2 101 OutdoorAlarm3 102 OutdoorAlarm4 103 OutdoorAlarm5 104 OutdoorAlarm6 105 OutdoorAlarm7 106 OutdoorAlarm8 107 OutdoorAlarm9 108 IndoorFanRPM 109 OutdoorFanRPM 110 PM2.5Level 111 WhetherPM2.5 112 PM2.5% 113 DisplayScreenBrightness

P.S. I use netcat on Windows to resquest AC state, sending this hex string F4F500400C00000101FE0100006600000001B3F4FB

image

This is the output of my netcat on Windows with XMV 4.4.7, it replies to XMV request but not to the hex string.

You must send not plain text, but a real bit string. You can create it using a hex editor like HxD and pass it to nc using < and > to redirect output to a file

Oh, it works. I don't get why sending plain HEX to the Hisense server works but not directly to the AC :P

Well this is a nice finding, LAN is Open \😃/

It's surprising that in this protocol they use Celsius, in the AEH-W4B1 protocol they rely on Fahrenheit.
If you get the entire protocol working I may be able to integrate it as another option to my code. I'd need volunteers for repeated testing though, as I don't have the relevant module.

I have almost finished analysis of responses for packet type 102. This is the most important type because it reports the full state of the AC. Other packet types (3, 3 sub 1, 7 sub 1, 10 sub 4, 30, 101, 101 sub 32 and 202) are related to other things like setting modes (101), wifi (30) and so on.

These are the links to download the case study and related tables to interpret fields and values.
https://drive.google.com/file/d/1K6qdijNnSLKMMEIREe5DxBzMbA-cMeMT/view?usp=sharing
https://drive.google.com/file/d/1X0dlAzwSA3_JsJJbhk3O-2g2pSHQ5d1F/view?usp=sharing
https://drive.google.com/file/d/1mTMuDkfRTzD2l_iuy52PMcK0IvrfzF46/view?usp=sharing

It's surprising that in this protocol they use Celsius, in the AEH-W4B1 protocol they rely on Fahrenheit.
If you get the entire protocol working I may be able to integrate it as another option to my code. I'd need volunteers for repeated testing though, as I don't have the relevant module.

It is possible to switch easily to °F and the other way around: all the logic start to use and report temperature consequently.

This is the source of my knowledge of the protocol.

The DeviceProtocol and OffsetAttribute declarations explain the parameters for the creation and interpretation of the data field of the packets, with a few small variations that I indicated in my analysis, perhaps due to a revision of the protocol.

But the best thing is that most command packets can be written statically, except for those where a timer is set and little else!

If you tell me what else you may need I am at your disposal! I can create a list of commands to be sent to set the various parameters and obviously I am available for any clarification on the interpretation of the reply packets with the conditioner status.

In AEH-W4B1 everything is Fahrenheit, there is a parameter for changing the mode to Celsius, but it only affects the display on the AC.

Here is what I need:

  • A list of parameters (preferably mapped to the parameter names here). For each one the list of possible values, and whether the parameter is read-only.
  • How to fetch the current status of a single/all parameters.
  • How to update each parameter. A static string would be great.
  • Is there a way to get an update once the AC's status is changed?

I have done my dirty job!

  • A list of parameters (preferably mapped to the parameter names here). For each one the list of possible values, and whether the parameter is read-only.

List of parameters UPDATED

The read-only flag is only for JSON, because for AEH-W4A1 you obtain a response packet, as follow

  • How to fetch the current status of a single/all parameters.

Response packet analysys UPDATED and UPDATED SOURCE to latest protocol specification!

Every packet contains all the values

  • How to update each parameter. A static string would be great.

static command packets

Only the packets to set the on and off timers, which need to be created dynamically, are missing. If it can be useful to implement it, I already have the instructions to create the packets ;)

  • Is there a way to get an update once the AC's status is changed?

No, the Android app requires status every time it sends a command and when it is inactive about every 40 seconds.

I hope everything is clear and that you can add support to this device too

For completeness, I point out that the protocol extrapolated here was the basis of everything, but that it is a non-exact correspondence with the current one.
For reference, referring to response packets (type 102 sub 0), this is the file with the original version and this one with the revision I made.
I did the same job on the command packages, where the changes to the logic of the fields are more pronounced, but easier to identify because I knew the command I had sent.

After all this work, I found also this page with updated protocol data!

Thanks, I'll start merging it into the script.

Hi-Smart Life app updated today to version 5.2.9 with changelog "Updated the application protocol".
Did someone test the new version? What has changed and does it breaks our control method?

There are significant code changes, it's hard to exactly as the code when through some sort of obfuscation processing.
OTOH, I'd be surprised if the protocol itself has significantly changed, since that would require an update to the server code running on the AC as well (and they would also still need to handle the previous version for ACs that have not been updated).

Ok, in my spare time I managed to do a working HA integration for the AEH-W4A1 module; post on HA forum here

I ask those who have a different module like AEH-W4B1 and AEH-W4E1 if they can test the library on the local network to find out if they are compatible.

Those who own an AEH-W4A1 can copy the integration into custom components to try it while waiting for the pull request

@bannhead, Nice! The protocol for AEH-W4B1 is entirely different, no chance for it to work.

yeah,it seem that app or module version differs,the protocol differs,so it's a hard way.I have tried the serial comm to control it,using esp8266 and ttl-to-rs485 module,and it's a little difficult to analysis the code,any help would be grateful!

this is the code i have captured and i analysisd some of them:

AA 2A AC 00 00 00 10 00 00 02 01 04 00 48 35 00 00 00 04 04 00 00 04 01 04 01 0E 00 00 00 00 80 00 00 00 00 00 00 00 00 00 DE 18 //set_temp 26 cool
Temp, //15 byte (x*2-1)
mode(cool:28;auto:48;dry:38;fan:08;heat:18), //14byte
swing(00,02,04,06,08,0A,0C,0E), //31byte
fan_speed(03:speed_1,04:speed_2,05:auto,06:speed_3,08:speed_4) //12byte
the rest i haven't figured out.

@happylichuanxi could you grab various packets (switching modes, hor and vert swing on and off, set temp from min to max step by step, and everything else you can change and grab via serial bus) and send them to me?

Can you indicate wifi module and ac brand&model?

@happylichuanxi could you grab various packets (switching modes, hor and vert swing on and off, set temp from min to max step by step, and everything else you can change and grab via serial bus) and send them to me?

Can you indicate wifi module and ac brand&model?

@happylichuanxi could you grab various packets (switching modes, hor and vert swing on and off, set temp from min to max step by step, and everything else you can change and grab via serial bus) and send them to me?

Can you indicate wifi module and ac brand&model?

sure,but it takes time, I will grab as soon as I can.

@happylichuanxi were you able to get the ESP8266 to control the AC directly without using the hisense module?

I am trying to connect directly to AC over RS485. esp32+uartRS485, I have Hisense AC with AEH-W4E1. = Works.
bannhead/pyaehw4a1#1 - my test.

# Command: cmd message len: 240 bit

61: always 1

# Power
ON:
11 - Command: last always 1
10 - Status = 10

OFF:
01 - Command: last always 1
00 - Status = 00

ON / OFF
      ON: offset:    [20, 21, 61]
00000000000000000000 11 00000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
      OFF: offset:       [21, 61]
00000000000000000000 01 00000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

# Wind
Super Low Wind:
00001011 - Command: last always 1.
00001010 - Status = 10

Super High Wind
00010011 - Command:
00010010 - Status = 18

         Auto in AC mode only: offset:             [7, 61]
00000001 0000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
         Super Low Wind - offset:            [4, 6, 7, 61]
00001011 0000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
         Low Wind - offset:                  [4, 5, 7, 61]
00001101 0000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
         Middle Wind - offset:            [4, 5, 6, 7, 61]
00001111 0000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 
         High Wind - offset:                    [3, 7, 61]
00010001 0000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
         Super High Wind - offset:           [3, 6, 7, 61]
00010011 0000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
_Setting_101_0 = {
        "wind_status":                          {"offset": 0,   "sz": 8, "prop": {"auto": "00000001", "lowest": "00001011", "low": "00001101", "middle": "00001111", "high": "00010001", "highest": "00010011"}},
        "sleep":                                {"offset": 8,   "sz": 8, "prop": {"0": "00000001", "1": "00000011", "2": "00000101", "3": "00001001", "4": "00010001"}},
        "mode":                                 {"offset": 16,  "sz": 4, "prop": {"cold": "0101", "fan": "0001", "heat": "0011", "dry": "0111", "auto": "1001"}},
        "run":                                  {"offset": 20,  "sz": 2, "prop": {"on": "11", "off": "01"}},
        "temp_fahrenheit":                      {"offset": 61,  "sz": 2, "prop": {"on": "11", "off": "01"}},
        "up_down":                              {"offset": 128, "sz": 2, "prop": {"on": "11", "off": "01"}},
        "left_right":                           {"offset": 130, "sz": 2, "prop": {"on": "11", "off": "01"}},
        "low_electricity":                      {"offset": 138, "sz": 2, "prop": {"on": "11", "off": "01"}},
        "turbo":                                {"offset": 140, "sz": 2, "prop": {"on": "11", "off": "01"}},
        "mute":                                 {"offset": 154, "sz": 2, "prop": {"on": "11", "off": "01"}, "info": "#quiet"},
        "back_led":                             {"offset": 160, "sz": 2, "prop": {"on": "11", "off": "01"}},
        "temp_indoor_set":                      {"offset": 24,  "sz": 8, "prop": {"25": "00110011", "26": "00110101"}, "info": "you can send int or key, but need configure key"}
}

I will try to use RS485+esp8266(esp-link) can you give me baudrate of rs485 ?

baudrate=9600

IMG_20221012_174935

I will use this adapter, only understand better , i send 30bytes @9600 baud with commands and i receive 30bytes ? Or i receive only one byte with status?

For now I only want read status.

all byte.

9600 commented

@miky2k Hello, yes, you called?

I'm testing hardware with simple c code:

  1. ESP8266 (esp-link firmware )
  2. from linux i use socat to create virtual serial port: /usr/bin/socat -T 40 pty,link=/tmp/ttyS10,raw,echo=0,iexten=0 tcp:192.168.170.237:23
  3. I use this simple code to send packet and AC respond,
    https://pastebin.com/YYz2JiQY

My goal is to write a simple esp8266 firmware that abstract AC protocol and present command as rest API or JSON state,
does someone write c funciotn to generate packet (header footer sum ,and all proprieties)?

@miky2k @straga
Hi,
Can you explain in more detail the procedure of how you established a direct connection with AC?
Your link is broken (https://pastebin.com/YYz2JiQY).
I'm not a programmer.
I bought two modules AEH-W4G1, through which, as is known, it has not yet been possible to connect to AC :(
Maybe you already have a ready-made firmware for ESP8266 or ESP32 ?

miky2k commented

Link is working i try to fix , copy and paste if not work with click.
I'use https://github.com/jeelabs/esp-link on esp8266 firmware to simulate com port through wifi .

Hi, some solution for hisense ac in hass?

I use the AEH-W4A1 module. Control and status is functional but unstable. Often the module disconnects from wifi regularly every 2 minutes. Regularly every 5 minutes I am unavailable in HA. I have already replaced the module with the new problem is the same. I assume that the problem is with the program in the module

I use https://github.com/pslawinski/esphome_airconintl and make some changes and it works with 1 model of my hisense AC, using ESP-8266 NodeMCU directly connecting to the AC can control it via esphome but still can't getting any current status from the AC. But same ESP-8266 not working for another model hisense AC, I guess another model using different uart protocol.
Here's my repository https://github.com/zoffypal/esphome_hisence_ac

@zoffypal HI
Try good micropython or ESPHome implementations.
It's tested on AMS-09UR4SVEDB65 and works
image
image
photo_2024-06-05_17-12-04

@zoffypal HI Try good micropython or ESPHome implementations. It's tested on AMS-09UR4SVEDB65 and works image image photo_2024-06-05_17-12-04

I was found this repository before. However, it's looks not esphome or adruino project, I didn't know how to use it neither to compile it and flash to esp8266 and connect to Home Assistant.

@zoffypal
repo is micropython project, yes.
If you want do this in ESPHome look at second link more closely