Midea A/C via local XYE

Hi All,
I have a C&H CH-36AHU (https://cooperandhunter.us/product/ch-36ahu) which like many others, is a Midea-manufacturered heat pump.

Like others, it definitely acted weird with the KJR-120X “wired controller” and so as a last-ditch effort (I almost got the company to rip it out…), we switched it to 24V control. This mostly worked, but was not good when really cold as the Honeywell had terrible settings, and does not support dual fuel to run the heat pump and electric backup at the same time.

I’d basically like to use this thread to find out the current status of RS-485 support, detail what hardware is needed. I’ve got the UART stick, and it works for everything except Follow Me support, I just can’t get the IR stuff to work.

Edit: Even tried to connect together the GND plane of the UART dongle with the wired controller’s IR TSOP. That didn’t work either.

But ideally if I could take an ESP32 and just hook it to RS-485 and be done with it, aside from times the wired controller might be needed for some maintenance settings…then that would be the cleanest, as I have the “Wifi smart module” there right now to hold the UART thing ( SMARTLIGHT SLWF-01pro (v.2.1))

References to posts in the other thread:

Thanks,
-Matt

Edit: Can only put two links in this post for now. Yay.

I received my RS-485 module along with more ESP32s.

“ALMOCN 2 Pack TTL to RS485 Adapter Module 3.3V 5V 485 to TTL Signal Single Chip Serial Port Level Converter Borad with RXD, TXD Indicator” off Amazon.

I used the github repo named esphome-mideaXYE-rs485 and tried that…

I used some probes to connect to the TX/RX on the wifi smart port where the Wired Controller pluigged in via RS-485.

All I get in the logs are:

[23:47:10][I][custom:130]: there are 240 bytes of data waiting
[23:47:10][I][custom:155]: dumped some data: 240
[23:47:10][I][custom:201]: First 6 bytes of incoming data were bad, not using values
[23:47:10][D][sensor:094]: 'updater': Sending state 0.00000  with 1 decimals of accuracy
[23:47:10][D][sensor:094]: 'Inlet Air Temperature': Sending state 0.00000 °F with 1 decimals of accuracy
[23:47:10][D][sensor:094]: 'Outside Air Temperature': Sending state 0.00000 °F with 1 decimals of accuracy
[23:47:11][D][number:012]: 'Set Point': Sending state 70.000000
[23:47:11][D][select:015]: 'Fan Mode': Sending state auto (index 3)
[23:47:11][D][sensor:094]: 'Coil A Temperature': Sending state 0.00000 °F with 1 decimals of accuracy
[23:47:11][D][sensor:094]: 'Coil B Temperature': Sending state 0.00000 °F with 1 decimals of accuracy
[23:47:11][D][text_sensor:064]: 'Error Codes': Sending state 'E1: 0 E2: 0'
[23:47:11][D][select:015]: 'Operating Mode': Sending state off (index 0)
[23:47:11][I][custom:130]: there are 240 bytes of data waiting
[23:47:11][I][custom:162]: got small response, wait for more. size was 240

Over and over.

Ideally, I’d like to just dump what it’s seeing, to see if I’ve even got the physical layer right.

Any help / thoughts would be appreciated!

-Matt

PS I also have a scope and a logic analyzer, and am OK with C…so I’ll hopefully have something that will make the old wired controller useless after this is done…

Changed the error line to actually just dump data - I’m getting values of some sort.

I also note that the LED on the board is always RX. I guess that means the board does not have automatic flow control. Re-reading the description on Amazon, it does…Interesting…

Here’s more reference posts in the meantime:

-Matt

Ok I got somewhere:

[04:41:43][E][midea_xye:164]: Received incorrect message length from AC
[04:41:43][W][component:237]: Component midea_xye.climate took a long time for an operation (2094 ms).
[04:41:43][W][component:238]: Components should block for at most 30 ms.
[04:41:43][D][uart_debug:114]: <<< 55:AA:C4:00:00:00:00:00:00:00:00:00:00:00:3B:01:55:AA:C4:00:00:00:00:00:00:00:30:98:00:00:00:01:20:84:80:CE:BC:D6:2C:00:00:FF:00:80:80:80:80:C4:55:AA:C0:00:00:00:00:00:00:00:00:00:00:00:3F:01:55:AA:C0:00:00:00:00:30:14:84:80:15:52:54:00:2E:FF:00:00:00:00:00:00:00:00:00:00:00:14:E0:01:1B:55:AA:C4:00:00:00:00:00:00:00:00:00:00:00:3B:01:55:AA:C4:00:00:00:00:00:00:00:30:98:00:00:00:01:20:84:80:CE:BC:D6:2C:00:00:FF:00:80:80:80:80:C4:55
[04:41:45][D][uart_debug:114]: >>> AA:C0:00:00:80:00:00:00:00:00:00:00:00:3F:81:55
[04:41:45][D][uart_debug:114]: <<< AA:C0:00:00:00:00:00:00:00:00:00:00:00:3F:01:55:AA:C0:00:00:00:00:30:14:84:80:15:52:54:00:2E:FF:00:00:00:00:00:00:00:00:00:00:00:14:E0:01:1B:55:AA:C4:00:00:00:00:00:00:00:00:00:00:00:3B:01:55:AA:C4:00:00:C0:E5:FC:FF:FF:FF:FF:FF:FF:FF:FF:F3:F7:2C:00:00:FF:00:80:80:80:80:C4:55:AA:C0:00:00:00:00:00:00:00:00:00:00:00:3F:01:55:AA:C0:00:00:00:00:30:14:84:80:15:52:54:00:2E:FF:00:00:00:00:00:00:00:00:00:00:00:14:E0:01:1B:55:AA:C4:00:00:00:00:00:00:00:00

Using this config:

substitutions:
  name: esp32-bluetooth-proxy-48bbf4
  friendly_name: RS485 Sniffer 48bbf4
esphome:
  name: ${name}
  name_add_mac_suffix: false
  friendly_name: ${friendly_name}

api:
  encryption:
    key: ...

esp32:
  board: esp32dev
  framework:
    type: arduino



wifi:
  use_address: ...
  ssid: !secret wifi_ssid
  password: !secret wifi_password


ota:
  - platform: esphome

# Enable logging (but not via UART)
logger:
  baud_rate: 0

external_components:
  - source: 
      type: git
      url: https://github.com/exciton/esphome
      ref: dev
    components: [midea_xye]
  
# UART settings for RS485 converter dongle (required)
uart:
  tx_pin: GPIO17
  rx_pin: GPIO16
  baud_rate: 4800
  debug: #If you want to help reverse engineer
    direction: BOTH


# Main settings
climate:
  - platform: midea_xye
    name: Heatpump
    period: 1s                  # Optional. Defaults to 1s
    timeout: 2s              # Optional. Defaults to 100ms
    beeper: true               # Optional. Beep on commands.
    visual:                     # Optional. Example of visual settings override.
      min_temperature: 17 °C    # min: 17
      max_temperature: 30 °C    # max: 30
      temperature_step: 1.0 °C  # min: 0.5
    supported_modes:            # Optional. 
      - FAN_ONLY
      - HEAT_COOL              
      - COOL
      - HEAT
      - DRY
    supported_swing_modes:      # Optional
      - VERTICAL
    outdoor_temperature:        # Optional. Outdoor temperature sensor
      name: Outside Temp
    temperature_2a:             # Optional. Inside coil temperature
      name: Inside Coil Temp
    temperature_2b:             # Optional. Outside coil temperature
      name: Outside Coil Temp
    current:                    # Optional. Current measurement
      name: Current
    timer_start:                # Optional. On timer duration
      name: Timer Start
    timer_stop:                 # Optional. Off timer duration
      name: Timer Stop
    error_flags:                # Optional.
      name: Error Flags
    protect_flags:              # Optional. 
      name: Protect Flags

Please note I had a wired controller connected dfuring this exchange…
I guess I should fork the code and then add in debugging to just dump the contents witrhout it trying to send something out…

Edit: Forked code.

Commented out the send commands…

Had the UART debugging on, did some text manipulation and…

user@personal:~/Downloads$ sort com2 |uniq -c
     32 :AA:C0:00:00:00:00:00:00:00:00:00:00:00:3F:01:55
     32 :AA:C0:00:00:00:00:30:14:00:80:18:58:5E:00:26:FF:00:00:00:00:00:00:00:00:00:00:00:14:E0:01:94:55
     33 :AA:C4:00:00:00:00:00:00:00:00:00:00:00:3B:01:55
     33 :AA:C4:00:00:00:00:00:00:00:30:98:00:00:00:01:20:04:80:D2:BC:D6:28:00:00:FF:00:80:80:80:80:44:55

Looking at the dumps there, I notice one thing right away - the “reply” does not have 0x80 set for Byte 2.

Sooo…

commit b18b957dd21d41da406a53c128dd689d2cff3acf (HEAD -> client_id, origin/client_id)
Author: Matthew Drobnak <[email protected]>
Date:   Fri Mar 7 18:43:16 2025 +0000

    Change TO_CLIENT byte.

diff --git a/esphome/components/midea_xye/air_conditioner.h b/esphome/components/midea_xye/air_conditioner.h
index 44d1648b..1ab876ee 100644
--- a/esphome/components/midea_xye/air_conditioner.h
+++ b/esphome/components/midea_xye/air_conditioner.h
@@ -64,7 +64,7 @@
 #define SERVER_COMMAND_LOCK   0xCC
 #define SERVER_COMMAND_UNLOCK 0xCD
 
-#define TO_CLIENT            0x80
+#define TO_CLIENT            0x00
 
 #define RESPONSE_UNKNOWN     0x30  

Disconnected the wired controlller…and some success.
Some values still seem very wrong, but I was able to turn the unit to heat mode and back off using the XYE interface in Home Assistant.

Now to figure out what the Wired Controller is sending for the foillow-me temperature so I can finaly make that part work.

Got it!

AA:C6:00:00:00:00:00:00:00:00:02:15:00:39:EA:55
AA:C6:00:00:00:00:00:00:00:00:02:15:00:39:EA:55
AA:C6:00:00:00:00:00:00:00:00:02:15:00:39:EA:55
AA:C6:00:00:00:00:00:00:00:00:02:15:00:39:EA:55
AA:C6:00:00:00:00:00:00:00:00:02:15:00:39:EA:55
AA:C6:00:00:00:00:00:00:00:30:98:00:00:00:00:20:84:80:55:BC:D6:2C:00:00:FF:00:80:80:80:80:3C:55
AA:C6:00:00:00:00:00:00:00:30:98:00:00:00:00:20:84:80:55:BC:D6:2C:00:00:FF:00:80:80:80:80:3C:55
AA:C6:00:00:00:00:00:00:00:00:02:15:00:39:EA:55
AA:C6:00:00:00:00:00:00:00:00:02:15:00:39:EA:55
AA:C6:00:00:00:00:00:00:00:30:98:00:00:00:00:20:84:80:55:BC:D6:2C:00:00:FF:00:80:80:80:80:3C:55
AA:C6:00:00:00:00:00:00:00:30:98:00:00:00:01:20:84:80:55:BC:D6:2C:00:00:FF:00:80:80:80:80:3B:55

0x02 = Update?
0x15 = Temperature in C. 0x15 = 21 C, which is what the wired remote says.

And there we go “Follow Me” via not-IR.

This may have been brought up in the other thread - but I don’t see it implemented anywhere…

-Matt

Edit: I also see in Midea branded AC’s with ESPhome (no cloud) - #1240 by th4h4x that post that indeed, it is just XYE on a different pysical port.

Edit 2: Updated teh follow_me code to send the command…and it seems to have worked. :slight_smile:

At least on my unit, it looks like the temperatures were off a bit.

I validated using the wired controller (using the t1,t2,t2b,t3,t4 items), and it looks like the offset is 0x28, not 0x30. The values via XYE now match that of the UART interface.

Interestingly, when you send a 0xC6 command for follow me - it looks like the AC responds with a 0xC4 in addition to the 0xC6 response.

Still don’t know what’s in there.

You want to share your code so we can test?

Sure!
GitHub - mdrobnak/esphome at client_id - forked from your repo.

That branch has client_id change, follow_me change, and temperature offset change.

Trying to find T3 (T3 = Outdoor = already found and correct) and T4 temperature values (as reported on my wired controller) now.

Response byte 0x15 (21) on 0xC4 query seems to be T4 temperature.

Edit: According to the service manual, T3 is outdoor coil temp, T4 is outdoor “room” temperature.

From the Midea circuit diagram:
T2 COIL TEMP> SENSOR
T2A INDOOR COIL INLET TEMP.SENSOR
T2B INDOOR COIL OUTLET TEMP.SENSOR

Error EC52 “Condenser coil temperature sensor T3 is in open circuit or has short circuited”
Error EC53 “Outdoor room temperature sensor T4 is in open circuit or has short circuited”

This gaph seems to suggest that indeed, XYE reports the coil temp.

-Matt

I updated the client_id branch.

The ESPHome Style Guide mentions following Google standards for the most part, so I ran the code through clang-format --style=Google. So the diff vs the main branch looks bigger, but git log -p -w is probably the easiest way to see what happens on each commit.

Past that, the changes are now:

  • Client ID is set to 0 to match the wired controller
  • Temperature offset has ben corrected
  • Follow-me code is available and seems to mostly work
  • Corrected naming of Temperature Sensors (Add in T3 for Outside Coil Temp, Outdoor Temp is actually T4 and comes from 0xC4 query)
  • Restructure ParseResponse to handle 0xC0 and 0xC4 queries

Please note that as of right now I’m listening-only to what the wired controller does, so I may have broke sending stuff, but I don’t think I did. I did reduce the sned delay in my config from 1s to 100ms.

-Matt

During Fan-Only → Heat → Stop at Target Temp:

Outgoing from Wire Controller:

AA:C0:00:00:00:00:00:00:00:00:00:00:00:3F:01:55
AA:C4:00:00:00:00:00:00:00:00:00:00:00:3B:01:55
AA:C6:00:00:00:00:00:00:00:00:02:15:00:39:EA:55

Probably a pretty stable 20 Degrees C in the basement. Hence the C6 Query.

Note for all counts below - unique counts…there were 86000+ values send / received during the timeframe in question.

Looks like there is common structure between the C6 and C4 Query responses:

$ ../../an c6-response 
15 (Array 14)
--
      6 00
      7 01
--
17 (Array 16) [ Edit: Theory is this is the current running mode ]
--
      2 81
     11 84
--
19 (Array 18)
--
      7 CD
      5 CF
      1 D0
--
22 (Array 21)
--
      1 38
      3 3A
      2 3C
      3 3E
      2 40
      1 50
      1 52

C4 Responses:

15 (Array 14)
--
      6 00
     22 01
--
17 (Array 16) [ Edit: Theory is this is the current running mode ]
--
     12 81
     16 84
--
19 (Array 18)
--
     10 CD
      7 CF
     11 D0
--
22 (Array 21)
--
      2 38
      3 3A
      4 3C
      5 3E
      3 40
      1 42
      1 44
      1 46
      1 48
      1 4A
      1 4C
      1 4E
      2 50
      2 52

22 (Array 21) is now known to be the outside temperature. So that one makes total sense.
15/17/19 though…
Edited up there - 17 I think is the current running mode.

In other news, I was able to get my remote control into “Inquiry Mode” - which interestingly put my controlle rback into F Temperature units (that’s how the remote was set). Unfortunately I got no response out of the wired controller after messing with a few queries…

Should probably watch some of those commands…

I re-did the “Turn on follow-me” test:

root@cnc:/ssdpool/home/esphome# grep AA:C6 turn-on-follow-me.txt 
[02:04:40][D][uart_debug:114]: <<< AA:C0:00:00:00:00:00:00:00:00:00:00:00:3F:01:55:AA:C0:00:00:00:00:30:14:84:80:15:52:62:00:3C:FF:00:00:00:00:00:00:00:00:00:00:00:14:E0:01:FF:55:AA:C6:00:00:00:00:00:00:00:00:06:15:00:39:E6:55:AA:C4:00:00:00:00:00:00:00:30:98:00:00:00:00:20:84:80:CD:BC:D6:44:00:00:FF:00:80:80:80:80:AE:55:AA:C6:00:00:00:00:00:00:00:00:06:15:00:39:E6:55:AA:C4:00:00:00:00:00:00:00:30:98:00:00:00:00:20:84:80:CD:BC:D6:44:00:00:FF:00:80:80:80:80:AE:55:AA:C6:00:00:00:00
[02:04:40][D][uart_debug:114]: <<< 00:00:00:00:06:15:00:39:E6:55:AA:C6:00:00:00:00:00:00:00:30:98:00:00:00:00:20:84:80:CD:BC:D6:44:00:00:FF:00:80:80:80:80:AC:55:AA:C4:00:00:00:00:00:00:00:00:00:00:00:3B:01:55:AA:C6:00:00:00:00:00:00:00:30:98:00:00:00:00:20:84:80:CD:BC:D6:44:00:00:FF:00:80:80:80:80:AC:55
[02:07:39][D][uart_debug:114]: <<< AA:C4:00:00:00:00:00:00:00:00:00:00:00:3B:01:55:AA:C4:00:00:00:00:00:00:00:30:98:00:00:00:01:20:84:80:CD:BC:D6:44:00:00:FF:00:80:80:80:80:AD:55:AA:C6:00:00:00:00:00:00:00:00:02:15:00:39:EA:55:AA:C4:00:00:00:00:00:00:00:30:98:00:00:00:00:20:84:80:CD:BC:D6:44:00:00:FF:00:80:80:80:80:AE:55:AA:C6:00:00:00:00:00:00:00:00:02:15:00:39:EA:55:AA:C4:00:00:00:00:00:00:00:30:98:00:00:00:00:20:84:80:CD:BC:D6:44:00:00:FF:00:80:80:80:80:AE:55:AA:C6:00:00:00:00
[02:07:39][D][uart_debug:114]: <<< 00:00:00:00:02:15:00:39:EA:55:AA:C6:00:00:00:00:00:00:00:30:98:00:00:00:00:20:84:80:CD:BC:D6:44:00:00:FF:00:80:80:80:80:AC:55:AA:C4:00:00:00:00:00:00:00:00:00:00:00:3B:01:55:AA:C6:00:00:00:00:00:00:00:30:98:00:00:00:00:20:84:80:CD:BC:D6:44:00:00:FF:00:80:80:80:80:AC:55
[02:10:39][D][uart_debug:114]: <<< AA:C0:00:00:00:00:00:00:00:00:00:00:00:3F:01:55:AA:C0:00:00:00:00:30:14:84:80:15:52:54:00:4E:FF:00:00:00:00:00:00:00:00:00:00:00:14:E0:01:FB:55:AA:C4:00:00:00:00:00:00:00:00:00:00:00:3B:01:55:AA:C4:00:00:00:00:00:00:00:30:98:00:00:00:01:20:84:80:CD:BC:D6:44:00:00:FF:00:80:80:80:80:AD:55:AA:C6:00:00:00:00:00:00:00:00:02:15:00:39:EA:55:AA:C4:00:00:00:00:00:00:00:30:98:00:00:00:00:20:84:80:CD:BC:D6:44:00:00:FF:00:80:80:80:80:AE:55:AA:C6:00:00:00:00
[02:10:39][D][uart_debug:114]: <<< 00:00:00:00:02:15:00:39:EA:55:AA:C4:00:00:00:00:00:00:00:30:98:00:00:00:00:20:84:80:CD:BC:D6:44:00:00:FF:00:80:80:80:80:AE:55:AA:C6:00:00:00:00:00:00:00:00:02:15:00:39:EA:55:AA:C6:00:00:00:00:00:00:00:30:98:00:00:00:00:20:84:80:CD:BC:D6:44:00:00:FF:00:80:80:80:80:AC:55

Three transmissions outbound of the “Turn on” command (06 byte), then every 3 minutes after…


02:04

AA:C0:00:00:00:00:00:00:00:00:00:00:00:3F:01:55
AA:C0:00:00:00:00:30:14:84:80:15:52:62:00:3C:FF:00:00:00:00:00:00:00:00:00:00:00:14:E0:01:FF:55
AA:C6:00:00:00:00:00:00:00:00:06:15:00:39:E6:55
AA:C4:00:00:00:00:00:00:00:30:98:00:00:00:00:20:84:80:CD:BC:D6:44:00:00:FF:00:80:80:80:80:AE:55
AA:C6:00:00:00:00:00:00:00:00:06:15:00:39:E6:55
AA:C4:00:00:00:00:00:00:00:30:98:00:00:00:00:20:84:80:CD:BC:D6:44:00:00:FF:00:80:80:80:80:AE:55
AA:C6:00:00:00:00:00:00:00:00:06:15:00:39:E6:55
AA:C6:00:00:00:00:00:00:00:30:98:00:00:00:00:20:84:80:CD:BC:D6:44:00:00:FF:00:80:80:80:80:AC:55
AA:C4:00:00:00:00:00:00:00:00:00:00:00:3B:01:55
AA:C6:00:00:00:00:00:00:00:30:98:00:00:00:00:20:84:80:CD:BC:D6:44:00:00:FF:00:80:80:80:80:AC:55

02:07

AA:C4:00:00:00:00:00:00:00:00:00:00:00:3B:01:55
AA:C4:00:00:00:00:00:00:00:30:98:00:00:00:01:20:84:80:CD:BC:D6:44:00:00:FF:00:80:80:80:80:AD:55
AA:C6:00:00:00:00:00:00:00:00:02:15:00:39:EA:55
AA:C4:00:00:00:00:00:00:00:30:98:00:00:00:00:20:84:80:CD:BC:D6:44:00:00:FF:00:80:80:80:80:AE:55
AA:C6:00:00:00:00:00:00:00:00:02:15:00:39:EA:55
AA:C4:00:00:00:00:00:00:00:30:98:00:00:00:00:20:84:80:CD:BC:D6:44:00:00:FF:00:80:80:80:80:AE:55
AA:C6:00:00:00:00:00:00:00:00:02:15:00:39:EA:55
AA:C6:00:00:00:00:00:00:00:30:98:00:00:00:00:20:84:80:CD:BC:D6:44:00:00:FF:00:80:80:80:80:AC:55
AA:C4:00:00:00:00:00:00:00:00:00:00:00:3B:01:55
AA:C6:00:00:00:00:00:00:00:30:98:00:00:00:00:20:84:80:CD:BC:D6:44:00:00:FF:00:80:80:80:80:AC:55

02:10

AA:C0:00:00:00:00:00:00:00:00:00:00:00:3F:01:55
AA:C0:00:00:00:00:30:14:84:80:15:52:54:00:4E:FF:00:00:00:00:00:00:00:00:00:00:00:14:E0:01:FB:55
AA:C4:00:00:00:00:00:00:00:00:00:00:00:3B:01:55
AA:C4:00:00:00:00:00:00:00:30:98:00:00:00:01:20:84:80:CD:BC:D6:44:00:00:FF:00:80:80:80:80:AD:55
AA:C6:00:00:00:00:00:00:00:00:02:15:00:39:EA:55
AA:C4:00:00:00:00:00:00:00:30:98:00:00:00:00:20:84:80:CD:BC:D6:44:00:00:FF:00:80:80:80:80:AE:55
AA:C6:00:00:00:00:00:00:00:00:02:15:00:39:EA:55
AA:C4:00:00:00:00:00:00:00:30:98:00:00:00:00:20:84:80:CD:BC:D6:44:00:00:FF:00:80:80:80:80:AE:55
AA:C6:00:00:00:00:00:00:00:00:02:15:00:39:EA:55
AA:C6:00:00:00:00:00:00:00:30:98:00:00:00:00:20:84:80:CD:BC:D6:44:00:00:FF:00:80:80:80:80:AC:55

Doing some data analysis:
C0 and C3 response structure is exactly the same.
C4 and C6 response structure is exactly the same.

C0/C3: (Field Number, Not Byte Number)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
AA C0 00 00 00 00 30 14 00 00 15 50 36 00 0C FF 00 00 00 00 00 00 00 00 00 00 00 14 E0 01
C3 80 01 16 52 54 TO 02
81 80 17 54 5E 50
84 81 56 5E
82 58 74
84 5A 80
92

Note for below data - 0x1D was missing, and 0x1E and 0x1F are listed incorrectly on the source site. Corrected here, in italics.
Original data from xye/xye: Reverse engineered information of protocol spoken on the XYE bus found on many AC indoor components of split VRF systems. Primary vendor seems to be Midea, but others vendors seem to sell rebanded versions (e.g. FrigoLine, Mundo Clima, Daikin, ...) - Forgejo: Beyond coding. We Forge..

Byte Field Description
0x00 preambel 0xAA
0x01 response code 0xc0 - Query, 0xc3 - Set, 0xcc - Lock, 0xcd - Unlock
0x02 to master 0x80
0x03 destination 0 … 0x3f - master device id
0x04 Source / Own Id 0 … 0x3f - device id
0x05 destination 0 … 0x3f - master device id
0x06 ??? 0x30 - maybe capabilities
0x07 capabilities 0x80 - extended temp (16 … 32 °C), 0x10 has SWING
0x08 Oper Mode 0x00 - off, 0x80 - auto, 0x88 - Cool, 0x82 - Dry, 0x84 - Heat, 0x81 - Fan
0x09 Fan 0x80 - Auto, 0x01 - High, 0x02 - Medium -0x03 Low
0x0A Set Temp in °C
0x0B T1 Temp in 0.5 °C - 0x30
0x0C T2A Temp in 0.5 °C - 0x30
0x0D T2B Temp in 0.5 °C - 0x30
0x0E T3 Temp in 0.5 °C - 0x30
0x0F Current 0 … 99 Amps
0x10 ??? 0xff - could be frequency
0x11 Timer Start Sum of: 0x01 - 15min, 0x02 - 30min, 0x04 - 1h, 0x08 - 2h, 0x10 - 4h, 0x20 - 8h, 0x40 - 16h 0x80 - invalid
0x12 Timer Stop Sum of: 0x01 - 15min, 0x02 - 30min, 0x04 - 1h, 0x08 - 2h, 0x10 - 4h, 0x20 - 8h, 0x40 - 16h 0x80 - invalid
0x13 ??? 0x01 - run?
0x14 Mode Flags 0x02 - Aux Heat (Turbo), 0x00 - norm, 0x01 - ECO Mode (sleep), 0x04 - SWING, 0x88 VENT
0x15 Oper Flags 0x04 - water pump running, 0x80 - locked
0x16 error E + bit pos, (0…7)
0x17 error E + bit pos, (7…f)
0x18 protect P + bit pos, (0…7)
0x19 protect P + bit pos, (7…f)
0x1A CCM Comm Error 00 … 02
0x1B ??? (0x00)
0x1C ??? (0x00)
0x1D XXX XXX
0x1E CRC 255 - sum(data) % 256 + 1
0x1F prologue 0x55

My Interpretation of the data (Changes in italics):

Field Number Description Notes
1 Preamble 0xAA
2 response code 0xc0 - Query, 0xc3 - Set, 0xC4 - Extended Query?, OxC6 - Follow Me, 0xcc - Lock, 0xcd - Unlock
3 to master 0x00, 0x80
4 destination 0 … 0x3f - master device id
5 Source / Own Id 0 … 0x3f - device id
6 destination 0 … 0x3f - master device id
7 ??? 0x30 - maybe capabilities
8 capabilities 0x14 - Aux Heat?, Air Handler?, 0x80 - extended temp (16 … 32 °C), 0x10 has SWING
9 Oper Mode 0x00/0x04 - off, 0x80 - auto, 0x88 - Cool, 0x82 - Dry, 0x84 - Heat, 0x81 - Fan
10 Fan 0x8? = Auto Fan flag. 0x0 = Stopped, 0x1 = High, 0x2 = Medium, 0x4 = Low. OR the values (e.g 0x84 = Auto Fan, Current SPeed Low)
11 Set Temp in °C
12 T1 Temp in 0.5 °C - 0x28
13 T2A Temp in 0.5 °C - 0x28
14 T2B Temp in 0.5 °C - 0x28
15 T3 Temp in 0.5 °C - 0x28
16 Current 0 … 99 Amps
17 ??? 0x00 - ???, 0xff - could be frequency
18 Timer Start Sum of: 0x01 - 15min, 0x02 - 30min, 0x04 - 1h, 0x08 - 2h, 0x10 - 4h, 0x20 - 8h, 0x40 - 16h 0x80 - invalid
19 Timer Stop Sum of: 0x01 - 15min, 0x02 - 30min, 0x04 - 1h, 0x08 - 2h, 0x10 - 4h, 0x20 - 8h, 0x40 - 16h 0x80 - invalid
20 ??? 0x01 - run?
21 Mode Flags 0x02 - Aux Heat (Turbo), 0x00 - norm, 0x01 - ECO Mode (sleep), 0x04 - SWING, 0x88 VENT
22 Oper Flags 0x04 - water pump running, 0x80 - locked
23 error E + bit pos, (0…7)
24 error E + bit pos, (7…f)
25 protect P + bit pos, (0…7)
26 protect P + bit pos, (7…f)
27 CCM Comm Error 00 … 02
28 ??? (0x00), 0x14 - ??
29 ??? Startup Status Flag 1 - Counts up and then 0xE0 is Normal Operation
30 ? Startup Status Flag 2 - 0x01 is Normal Operation
31 CRC 255 - sum(data) % 256 + 1
32 prologue 0x55

For C4/C6:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
AA C4 00 00 00 00 00 00 00 30 98 00 00 00 00 20 04 01 CD BC D6 Ou 00 00 FF 00 80 80 80 80
C6 01 81 80 CF ts
84 D0 id
D1 e
T

My Interpretation of the data (Field 1-6 Same As Above, all else mine):

Field Number Description Notes
1 Preamble 0xAA
2 response code 0xc0 - Query, 0xc3 - Set, 0xC4 - Extended Query?, OxC6 - Follow Me, 0xcc - Lock, 0xcd - Unlock
3 to master 0x00, 0x80
4 destination 0 … 0x3f - master device id
5 Source / Own Id 0 … 0x3f - device id
6 destination 0 … 0x3f - master device id
7 ? 0x00
8 ? 0x00
9 ? 0x00
10 ? Same as 0xC0 Field 7
11 ? Similar to 0xC0 Field 8?
12 ? 0x00
13 ? 0x00
14 ? 0x00
15 ? 0x00, 0x01
16 ? 0x20, 0x60 - Emergency Heat (Aux Only)
17 Mode 0x04 - Off , 0x81 - Fan, 0x84 Heat, 0x90 auto, 0x88 Cool, 0x82 Dry
18 ? 0x01, 0x80
19 Temperature Setpoint (C = 0.5C scaling, F =1 F scaling, Val - 0x87 = Temp in F)
20 ? 0xBC
21 ? 0xD6
22 Outside Temp in 0.5 °C - 0x28
23 ? 0x00
24 ? 0x00
25 ? 0xFF - Normal, 0x07 - Error?
26 ? 0x00
27 ? 0x80
28 ? 0x80
29 ? 0x80
30 ? 0x80
31 CRC 255 - sum(data) % 256 + 1
32 prologue 0x55

C6 Command set:
My Interpretation of the data (Field 1-6 Same As Above, all else mine):

Field Number Description Notes
1 Preamble 0xAA
2 Command 0xC6 - Extended Set? - Follow-Me, Static Pressure, Emergency Heat Modes
3 to master 0x00, 0x80
4 destination 0 … 0x3f - master device id
5 Source / Own Id 0 … 0x3f - device id
6 destination 0 … 0x3f - master device id
7 ? 0x00
8 ? 0x00
9 Settings 0x95-9F (5-15 for Static Pressure), 0x80 - Emergency Heat
10 ? 0x00
11 Follow-Me Command 0x6 Start, 0x2 Update, 0x4 Stop
12 Follow-Me Temp in C
13 ? 0x00
14 Command Check 0xFF - Field 2
15 CRC 255 - sum(data) % 256 + 1
16 prologue 0x55

That’s where I am so far in terms of analysis. Mind you I’m onlyu using the heating mode right now…Haven’t even tried turning on the Heat + Aux Heat mode.

Also, when I tried to put the unit in Inquiry / Service mode with the remote, it switched it back into Farenheight.on the wired controller display. The only data this affects is the setpoint. Everything else stilli is in C.

-Matt

Field 10 in C0 will tell you current fan speed, not necessarily desired fan speed.

At least in Heating mode this might be useful to tell the difference between “Heat” and “Heating”.

We might also be able to figure this out via difference in outdoor temp vs outdoor coil temp… But I have to imagine this data is here somewhere.

Edit: This has been doing OK so far:

diff --git a/esphome/components/midea_xye/air_conditioner.cpp b/esphome/components/midea_xye/air_conditioner.cpp
index 0f811031..db875b9f 100644
--- a/esphome/components/midea_xye/air_conditioner.cpp
+++ b/esphome/components/midea_xye/air_conditioner.cpp
@@ -284,6 +284,14 @@ void AirConditioner::ParseResponse(uint8_t cmdSent) {
             need_publish = true;
             this->fan_mode = fan_mode;
           }
+          if ((this->mode == climate::CLIMATE_MODE_HEAT) && (RXData[9] & 0x0F) != 0x00) {
+            this->action = climate::CLIMATE_ACTION_HEATING;
+            need_publish = true;
+          } else if ((this->action != climate::CLIMATE_ACTION_IDLE) && (RXData[9] & 0x0F) == 0x00) {
+            this->action = climate::CLIMATE_ACTION_IDLE;
+            need_publish = true;
+          }
+
           if ((this->swing_mode != ClimateSwingMode::CLIMATE_SWING_OFF) !=
               (bool)(RXData[RX_BYTE_MODE_FLAGS] & MODE_FLAG_SWING))
             need_publish = true;
@@ -438,6 +446,9 @@ ClimateTraits AirConditioner::traits() {
     traits.add_supported_swing_mode(ClimateSwingMode::CLIMATE_SWING_OFF);
   if (!traits.get_supported_presets().empty())
     traits.add_supported_preset(ClimatePreset::CLIMATE_PRESET_NONE);
+
+  traits.set_supports_action(true);
+
   return traits;
 }
 

This is awesome work! Did you figure out how to set/read auto mode? I had a similar observation where the actual mode is returned, so it’s not possible to know if you’re in auto. Any luck?

This is awesome work! Did you figure out how to set/read auto mode? I had a similar observation where the actual mode is returned, so it’s not possible to know if you’re in auto. Any luck?

Nothing on that yet.

I did, however, figure out a little aobut the F vs C on the wired display.

It literally just sends it in F instead of C, on the AA:C3 command:

$ cat change-from-f-to-c.txt |egrep '^.{47}$' |sort |uniq -c
    203 AA:C0:00:00:00:00:00:00:00:00:00:00:00:3F:01:55
      1 AA:C3:00:00:00:00:84:01:56:00:00:00:00:3C:26:55
      3 AA:C3:00:00:00:00:84:01:57:00:00:00:00:3C:25:55
      3 AA:C3:00:00:00:00:84:01:58:00:00:00:00:3C:24:55
    204 AA:C4:00:00:00:00:00:00:00:00:00:00:00:3B:01:55
      1 AA:C6:00:00:00:00:00:00:00:00:06:14:00:39:E7:55
      9 AA:C6:00:00:00:00:00:00:00:00:06:15:00:39:E6:55
$ ./parse-log wired-change-c-to-f.txt |grep AA:C3
AA:C3:00:00:00:00:84:01:CB:00:00:00:00:3C:B1:55
AA:C3:00:00:00:00:84:01:CB:00:00:00:00:3C:B1:55

So if in range A → Celsius, if in range B, Farenheit. Also C moves in 0.5C increments, F moves in 1F increments.

Yep. So, interestingly, AA:C3 → Setpoint in C or F… But Follow Me value on 0xC6 is always in C. Also, looks like all of the other temp sensors are always in C.

That said, it may change the overall behavior leaving it in F as to the way “Auto” mode will work with regards to deadbands, etc.

Ah hah!

So…it turns out when I put it into “High” mode the other day - it did not go back into auto when I thought it did.

I looked at the wired controller and was confused when I didn’t see the word “Auto” and just saw Full speed…

So, Yes I can say, with certainty…

if (RXData[9] & 0xF0) == 0x80 —> Auto fan speed enabled.
In other words…
0x84 = Auto + Low Speed
0x82 = Auto + Medium Speed
0x81 = Auto + High Speed

0x04 = Low Speed
0x02 = Medium Speed
0x01 = High Speed

NOW - Here’s the fun part - Just because it was set into Hi -The system will ramp it lower as it gets closer to the target temperature, at least in heating mode.

I got a few captures of things I tested on the wired controller. Will compare the captures vs what the code does tomorrow. Bed time now. :slight_smile:

-Matt

So, looks like the before the checksum are some kind of status bits.
I powered off the AHU and logged the startup.

$ ./parse-log circuit-breaker-off-to-poweer-on-idle.txt  |sort |uniq
AA:C0:00:00:00:00:00:00:00:00:00:00:00:3F:01:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:00:FF:00:00:00:00:00:00:00:00:00:00:00:14:00:00:2F:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:00:00:FB:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:03:00:F8:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:03:01:F7:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:05:02:F4:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:12:00:E9:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:14:01:E6:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:16:01:E4:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:1A:00:E1:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:1B:01:DF:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:29:00:D2:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:2B:01:CF:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:2D:00:CE:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:2E:01:CC:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:31:00:CA:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:32:01:C8:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:41:00:BA:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:42:01:B8:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:45:00:B6:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:45:01:B5:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:49:00:B2:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:49:01:B1:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:58:00:A3:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:5A:01:A0:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:5C:00:9F:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:5D:01:9D:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:60:00:9B:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:61:01:99:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:70:00:8B:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:71:01:89:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:73:00:88:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:74:01:86:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:77:00:84:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:78:01:82:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:87:00:74:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:88:01:72:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:8A:00:71:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:8B:01:6F:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:8E:00:6D:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:90:01:6A:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:9E:00:5D:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:A0:01:5A:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:A2:00:59:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:A3:01:57:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:A6:00:55:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:A7:01:53:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:B6:00:45:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:B7:01:43:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:B9:00:42:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:BA:01:40:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:BD:00:3E:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:BE:01:3C:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:CD:00:2E:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:CE:01:2C:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:D1:00:2A:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:D2:01:28:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:D5:00:26:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:D6:01:24:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:E0:01:1A:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:E5:00:16:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:E8:00:13:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:EC:00:0F:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:ED:01:0D:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:FC:00:FF:55
AA:C0:00:00:00:00:30:14:00:00:16:52:52:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:FF:00:FC:55

Looking through the log they don’t count up in order, they move around a bit. But for sure it’s something related to readiness of the hardware. In no other logs do I see values other than E0:01in Fields 29 and 30.

-Matt

Interestingly, for my unit, 0x04 is “Off” - I am starting to wonder if that just means to “beep”.

I did figure out Emergency Heat (Aux Only mode):

C3 is sent like normal…

AA:C3:00:00:00:00:84:80:CF:00:00:00:00:3C:2E:55
AA:C3:00:00:00:00:30:14:84:80:16:52:54:00:34:FF:00:00:00:00:00:00:00:00:00:00:00:14:E0:01:11:55

But then a C6 command is sent:

AA:C6:00:00:00:00:00:00:80:00:06:15:00:39:66:55

Normal Follow-Me…Except…0x80 Flag. So C6 seems to be the “Extended Set” command, in the way that C4 seems to be the “Extended Query” command…

After that C6 command:

AA:C4:00:00:00:00:00:00:00:00:00:00:00:3B:01:55
AA:C4:00:00:00:00:00:00:00:30:98:00:00:00:01:60:84:80:CF:BC:D6:32:00:00:FF:00:80:80:80:80:7D:55

Note the 01:60:84 - instead of what should be 01:20:84…

@exciton Please test clien_id branch.

Changelog:

f718aed05b8d1941dc3fb9e79d59a5cd548cce70 Run clang-format --style=Google -i air_conditioner.*
aa5b6d51589b8f906c7ede6e4f8b011f953a1798 Fix representation of beginning and ending bytes.
7bc3ab714554c24a1235dae0d152c97acaf6effc Change FROM_CLIENT byte to match Wired Control KJR-120X.
0a782d56f177bd42bfdf063d6e096b55789e3c0c Change TO_CLIENT byte to match Wired Control KJR-120X.
d96fe8584200a89353856cba9a057eeb57559e62 Remove setup code for Celsius, as it doesn't do what it is thought to do.
b21f1c9f7d52b08f742c5e4288541ce77ac7c428 Correct temperature calculation. 0x28, not 0x30 offset.
835bcee7a118158a4e3cc45fa6f5c0ea4944fb8e Correct naming of T2/3 sensors.
5e0967ef357764b6163a04d20dcfa3f91f9b97fb Send out query types of both 0xC0 and 0xC4. Restructure ParseResponse to handle multiple message types.
4727a429d9b374c649ef003c4fb13b247f7dd7c5 Rename setClientCommand function to prepareTXData.
3476287549be1f8be0969ac408aa0fb6750282ee Handle Automatic Fan Speed Correctly.
337d13cb037f2c8553507469c068ed1e48bc2c5b Fix location of Mode Flag - Array location 11, not 12.
30b74c18bd14a967395ff6b9fc10fc0940a1a774 Add action trait to show heating/cooling vs heat/cool.
cc07a95444f3a50474fcf5d6a91d6c3353825134 Add in follow_me code.
08c34738da4a744c1e51cfd71af1e812fd52649f Add Debug for 0xC4 packet type.

Follow-Me is working as expected, it defintiely reports back teh same value as what I’m seinding it (within a 1 Degree C accuracy). I do wish there was a way to accurately identify when the compressor was running.

-Matt

I’m just starting to analyse my system to see if I can set static pressure from Home Assistant via XYE.

Wall controller commands when setting static pressure to SP0-SP4:
aac6000000000000100004170039d655
aac6000000000000110004170039d555
aac6000000000000120004170039d455
aac6000000000000130004170039d355
aac6000000000000140004170039d255

Responses from indoor unit:
aac600000000000000301c0000000000108054bed65200002000000000000455
aac600000000000000301c0000000000108054bed65200002100000000000355
aac600000000000000301c0000000000108054bed65200002200000000000255
aac600000000000000301c0000000000108054bed65200002300000000000155
aac600000000000000301c0000000000108054bed65200002400000000000055

C6 command
Field 9: lower nibble is static pressure?

C6 response
Field 24: lower nibble is static pressure?

This seems to line up with your more rigorous analysis. I’m watching with interest for now, waiting for some parts to arrive before I hook up an ESP32.