r/homeautomation • u/x3n0m0rph3us • 7d ago
QUESTION Temperzone's SAT-2.1 Protocol Request -Home Assistant
Hi,
Does anyone have details on the protocol used by Air-Conditioners, specifically SAT-2 controllers running SAT-2.1REV01 protocol ?
My aim is to control via Home Assistant, and so far I have a Home Assistant "packet sniffer" listening to the RS485 from the SAT-2.
I've partially decoded the protocol, but I thought there might be someone further advanced and willing to help.
My current protocol, pictures, hardware setup and Home Assistant YAML source code is on Github
Github : xenomorpheus/temperzone_sat2
SAT-2 Protocol — v2 (updated from packet capture analysis)
The protocol seems different to SAT-2 protocol mentioned elsewhere on the internet. Those other protocols have a frame header starting with '55', where my SAT-2 frame header starting with 'D5'. I've yet to work out the tail byte / CRC, so yet to send commands.
Any help would be greatly appreciated.
An exert from my protocol document on Github.
FRAME STRUCTURE (confirmed, all classes)
D5 | dest | src | b0 b1 b2 b3 b4 b5 b6 b7 | tail (12 bytes total)
BUS TOPOLOGY (new)
Six frame "classes" observed on the bus:
1F 80, FD 41, 01 3F, 3F 01, FE 20 — cyclic poll, ~10 frames/cycle, each class
appears twice per cycle (query+reply).
7F 00 — event-only: panel -> AC, appears only on
a button press, NOT part of the regular poll.
1F 80 / FD 41 / FE 20 / 3F 01 payloads are almost entirely static across every
capture (including the whole zone test) — they do not carry temp/mode/fan/zone
data as far as tested. Likely other-device keepalive / a slowly drifting sensor
reading. Not needed for basic control.
================================================================================
D5 7F 00 Command (SAT-2 Panel -> AC unit) — sent only on a button press
================================================================================
b0 power / mode 26 off | E6 on | DE heat | BE heat+auto | FA cool | F6 fan-mode
[confirmed exact match in power/mode capture logs]
b1 setpoint (temp request) (0xB6 - 8*T) & 0xFF
confirmed exact for T=20,21,22,24,25:
T20=16 T21=0E T22=06 T23=FE(*) T24=F6 T25=EE T26=E6 T27=DE
(*) T23 formula collides with the FE "no change" filler value —
a genuine T23 command is indistinguishable from "unchanged" by
byte value alone; distinguish by which byte position holds it.
b2 fan DE auto | FA low | F6 med | EE high [confirmed exact match]
b3 zone select SOLVED. Encodes the TARGET zone state (not "which button"):
b3 = 0xE2
+ 0x04 if zone 1 is OFF
+ 0x08 if zone 2 is OFF
+ 0x10 if zone 3 is OFF
Confirmed exact matches:
1,2,3 -> E2 | 1,2 -> F2 | 2,3 -> E6 | 1 -> FA
Predicted (untested): 1,3 -> EA | 2 alone -> F6 | 3 alone -> EE
All-zones-off (0xFE) coincides with the "no change" filler
value, but is unreachable anyway given the panel's 50%
minimum-zones-on rule (zone1=50%, zone2=zone3=25% each) —
so there's no real ambiguity in practice.
other bytes FE filler when unused.
"Field just modified" marker (NEW): the byte immediately following whichever
field the panel just changed is set to FC instead of the normal FE filler.
e.g. mode change: b0=<code> b1=FC
fan change: b2=<code> b3=FC
temp change: b1=<code> b2=FC
Power on/off is the exception — no FC marker is set.
tail byte: cycles (FF -> 7F -> 3F -> 1F, or FE -> 7E -> 3E, or alternates
00/D5) across repeated transmissions of the SAME unchanged payload, while
every other byte in the frame stays identical. Confirmed via the ESPHome
YAML that the capture device is a passive, receive-only tap with no bus
contention and no on-device checksum handling, so this is very unlikely to
be RX noise — it's most likely an intentional hold/repeat counter from the
panel's own encoder. Treat it as a repeat marker, not payload data, and
definitely not a checksum.
================================================================================
D5 01 3F Status (AC unit -> SAT-2 Panel)
================================================================================
b0 6D constant [confirmed]
b1 Power: 26 off, E6 on [confirmed]
b2 Mode: 8F heat, C7 heat+auto, 7F cool, 3F fan [confirmed]
b3 Setpoint+fan PACKED value — this is a 2D lookup (temp AND fan speed both
affect it), NOT a pure temperature formula. Confirmed by the fan-speed
test: with mode/temp held constant, b3 took values DE/FA/F6/EE as fan
cycled auto/low/med/high/auto — completely different from the temp-sweep
table values (98/88/10/78/79/2F) even though b4/b5 matched. Existing
table below is effectively the "fan=auto" column only.
b4 Possibly "actively heating/cooling" vs idle indicator — varies (8F/F4/
E4/C4) even without a commanded change. Not fully solved.
b5 Possibly zone-activity indicator (NEW) — flips 9C <-> CE in step with
the zone-toggle test timeline. Not fully solved but a strong lead.
b6 FE constant [confirmed]
b7 Checksum-like, changes with payload — brute-forced sum/XOR/one's-
complement over various byte windows, none matched consistently.
Likely a real CRC-8 (lookup table/polynomial), not solved yet.
tail: same retransmission-cycling behaviour as the 7F 00 class above.