A lightweight, zero-dependency codec for Samsung AC IR payloads
Project description
Samsung AC IR Protocol 🕵️♂️❄️
A Python package for encoding and decoding Samsung Air Conditioner IR remote payloads, featuring reverse-engineered checksum handling and timer decoding for Samsung's compact On/Off timer representation.
Disclaimer / Limitations
⚠️ Note: This protocol was entirely reverse-engineered through observation. While it has been tested on the models listed below, there is no guarantee that it works perfectly or reliably even for those specific devices, let alone other Samsung AC models or edge cases. There may be additional hidden flags or behaviors in other bytes that we have yet to discover. Use this library strictly at your own risk and feel free to contribute if you find discrepancies!
The Mystery
While standard Samsung AC IR protocols (Power, Temp, Mode, Fan) are well documented in open-source projects like HeatpumpIR, the timer scheduling functionality has remained a black box.
When observing the raw IR hex bytes sent by a Samsung remote while setting both "On Timers" and "Off Timers", the data did not simply represent 15-minute intervals. Furthermore, setting an Off Timer unexpectedly changed bytes associated with the On Timer.
Through raw byte analysis, we discovered that Samsung employs a compact bit-shifting and packing algorithm to fit timer durations into just 2.5 bytes of data.
The Protocol (21 Bytes Total)
Samsung AC IR payloads consist of 21 bytes (3 sections of 7 bytes). The timer data is heavily compressed into Section 2, specifically across Byte 9, Byte 10, and Byte 11.
🧩 The Tetris Packing
Because a timer can range from 0.5 hours to 24.0 hours, it requires more than 4 bits to store. Samsung chose to split these bits across byte boundaries:
- Off-Timer: Stored in the Upper Nibble of Byte 9 and the Lower Nibble of Byte 10.
- On-Timer: Stored in the Upper Nibble of Byte 10 and the Lower Nibble of Byte 11.
Note:
Byte 12often acts as a deceptive cache holding old timer data. When fully decoding dual-timers,Byte 12must be ignored in favor of the tightly packed B9~B11 region.
🔢 The Cryptic Formula (val = H * 8 + 3)
Even after successfully unpacking the nibbles into an integer val, the resulting integer is not a simple representation of hours or minutes. Samsung uses the following mathematical formula to encode the time:
- If the time is a whole hour (e.g., 1.0, 2.0, 3.0):
val = Hour * 8 - If the time is a half hour (e.g., 0.5, 1.5, 2.5):
val = Hour * 8 + 3
Examples:
| Actual Time | Formula Applied | Binary val (Packed) |
|---|---|---|
| 0.5 hours | 0 * 8 + 3 = 3 |
0000 0011 |
| 1.0 hours | 1 * 8 = 8 |
0000 1000 |
| 1.5 hours | 1 * 8 + 3 = 11 |
0000 1011 |
| 2.0 hours | 2 * 8 = 16 |
0001 0000 |
🚀 Installation
You can install the package directly from PyPI:
pip install samsung-ac-protocol
Or if you're using uv:
uv pip install samsung-ac-protocol
🛠 Usage (Python Codec)
Using the samsung-ac-protocol package is extremely simple.
Decoding (IR Sniffing)
Pass the 21-byte raw IR payload to the decode() function, and it will parse all the state information.
from samsung_ac_protocol import decode
# Example: 21-byte raw IR payload captured from an AC remote
raw_payload = [
0x02, 0x92, 0x0F, 0x00, 0x00, 0x00, 0xF0, 0x01,
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0,
0x00, 0x00, 0x00, 0x00, 0x00
]
state = decode(raw_payload)
print(state)
If you want the decoder to reject corrupted captures, enable checksum validation:
state = decode(raw_payload, validate_checksum=True)
You can also decode the timer fields directly:
from samsung_ac_protocol import decode_timers
timers = decode_timers(raw_payload)
Encoding & Timings (IR Blasting)
You can encode a desired state back into a 21-byte payload, and optionally convert it to raw microsecond timings to send directly to an IR LED. The encoder validates mode, temperature, fan, and timer ranges before generating bytes.
from samsung_ac_protocol import encode, to_timings, SamsungACRequest
req = SamsungACRequest(
power=True,
mode=1, # 1 = Cool
temp=24, # 24C
fan=4, # 4 = Medium
timer_mode=2, # 2 = Off Timer
timer_15m=8 # 2 hours
)
# 1. Generate 21-byte hex payload
payload_bytes = encode(req)
# 2. Generate 347 timing pulses for IR transmission
timings = to_timings(payload_bytes)
Supported encoder ranges:
mode:0Auto,1Cool,2Dry,3Fan,4Heattemp:16through30fan:0Auto,2Low,4Medium,5Hightimer_mode:0None,1On Timer,2Off Timer,3fixed special timer modetimer_15m:0through96, representing 15-minute units up to 24 hours. On/Off timers require a value greater than0;timer_mode=3accepts only0or4.
Verified Devices
This reverse engineering was tested and verified to work on the following hardware:
- Samsung WindFree™ 1-Way Cassette
- Model Numbers:
AC009BN1DCH(9K Btu),AC012BN1DCH(12K Btu),AC018BN1DCH(18K Btu)
- Model Numbers:
Contribution
Discovered while building a custom local IR bridge for Hermes Agent. Feel free to use this algorithm to implement full dual-timer support in your own open-source IR libraries!
License
This project is licensed under the MIT License. You are free to use, modify, and distribute this software, but it is provided "AS IS" with absolutely no liability or warranty.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file samsung_ac_protocol-0.1.1.tar.gz.
File metadata
- Download URL: samsung_ac_protocol-0.1.1.tar.gz
- Upload date:
- Size: 15.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d954b3160862dc6bcdc9b125e6158e2c6b8f5f70368116084c88988eef890d8d
|
|
| MD5 |
7673f6a92de3ee8114131c230209573e
|
|
| BLAKE2b-256 |
051116e7ab5b17af0879480f50c9143824dfa6306674cb1017b59749e0d72f11
|
File details
Details for the file samsung_ac_protocol-0.1.1-py3-none-any.whl.
File metadata
- Download URL: samsung_ac_protocol-0.1.1-py3-none-any.whl
- Upload date:
- Size: 8.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f025116f3a65af9bfac74a50744ca448204d0bcf6f8e637698cf3115fefbd71c
|
|
| MD5 |
f7d97ef26dcfb1ec1d449670aa460ad8
|
|
| BLAKE2b-256 |
53dc09e79ae697d24ceb3144644bc6bef5fef200a7e7e540576b120e34e6ab8c
|