Skip to content

Add support for Broadlink RM Max (0xAF8B) - #838

Open
amasolov wants to merge 1 commit into
mjg59:new_product_idsfrom
amasolov:add-rm-max-support
Open

Add support for Broadlink RM Max (0xAF8B)#838
amasolov wants to merge 1 commit into
mjg59:new_product_idsfrom
amasolov:add-rm-max-support

Conversation

@amasolov

@amasolov amasolov commented May 24, 2026

Copy link
Copy Markdown

Context

The Broadlink RM Max is the successor to the RM4 Pro, featuring IR and RF 433MHz capabilities. It is currently not recognized by the library, reporting as "Unsupported device: 0xAF8B" in Home Assistant.

This is a highly requested addition — see #829 with 20+ community members requesting support.

Proposed change

Add device type 0xAF8B to the rm4pro class mapping. The RM Max uses the same protocol as the RM4 Pro (confirmed by testing IR learning and sending on a physical device).

Type of change

  • New product id (the device is already supported with a different id)

Additional information

Checklist

  • The code change is tested and works locally.
  • The code has been formatted using Black.
  • The code follows the Zen of Python.
  • I am creating the Pull Request against the correct branch.
  • Documentation added/updated.

@dwery

dwery commented Jun 20, 2026

Copy link
Copy Markdown

This really is a one liner, can someone please hit merge?

@phenigma

Copy link
Copy Markdown

I tested this change and it detects the device but wants me to unlock it from the manufacturer's app but there is no option to do that in the app.

@dwery

dwery commented Jun 26, 2026

Copy link
Copy Markdown

Same. I couldn't find a way to unlock it. Even blocking the device's access to internet didn't work, I guess it locks itself immediately.

@amasolov
amasolov force-pushed the add-rm-max-support branch from 7aeb3c7 to 02796c8 Compare July 15, 2026 22:25
@blundsteen

Copy link
Copy Markdown

Hi! I've been testing an RM Max extensively and noticed something that may help.

My device:

PID: 0x8baf0000
Devtype: 0xAF8B
Firmware: V62130
SDK: 2.18.x
Name returned by discovery: "FCBLE GW"

Discovery works correctly, but device.auth() immediately fails. The device responds with a short error packet and never returns a session ID or AES key.

I noticed your PR only changes the device mapping (rm4pro → rmpro) and doesn't modify auth().

Did device.auth() succeed on your RM Max without any local modifications?

If so, could you share:

firmware version,
SDK version,
whether the device also reported "FCBLE GW",
and whether there were any additional local changes not included in PR #838?

Place in the rmpro class which uses <I framing for IR learn/send
commands, matching the device's actual protocol. The rm4pro class
uses <HI framing which causes "device is locked" errors on this
hardware.

Co-authored-by: Cursor <cursoragent@cursor.com>
@amasolov
amasolov force-pushed the add-rm-max-support branch from 02796c8 to de95700 Compare July 26, 2026 23:37
DAB-LABS added a commit to DAB-LABS/python-broadlink that referenced this pull request Sep 6, 2026
A fifth review, of 1.0.4, found one more place where the connected socket
could surface an error the original library never raised, and made a fair
case that the capture window claim was more machinery than the job needed.
This fixes the first, simplifies the second, and takes two small items
along. No change to the wire format or the public API. Tested on 3.13 and
3.14, 272 tests under -X dev with ResourceWarning as an error, oracle
fixtures unchanged, and live against an RM4 Pro.

Technical details:
- EHOSTUNREACH and Windows's ConnectionResetError are treated as silence
  in _exchange, as ECONNREFUSED already was: logged, the timeout decides,
  the socket is dropped afterwards. Home Assistant tolerates a timeout for
  a few polls but marks a device unavailable on the first OSError, and the
  original's unconnected socket never saw any of these. Measured on the
  bench before changing anything: neither an on-link address with no host
  nor an off-subnet one produced the ICMP here, so this is insurance for
  networks that do.
- The window claim is a flag set on first iteration and cleared in the
  generator's finally (so asyncio's finalizer releases a dropped window),
  replacing the weakref and ag_frame inspection. Same behaviour, same
  tests; CaptureInProgressError now always comes from the first
  iteration.
- discover() closes the xdiscover() generator it drains.
- A comment explains why the RM Max sits in rmpro (upstream mjg59#838).
- README: a device belongs to the event loop it first talks on.
- Version 1.0.5.
DAB-LABS added a commit to DAB-LABS/python-broadlink that referenced this pull request Sep 6, 2026
A sixth review, of 1.0.5, found no defect in the code. This takes its small
items. No change to the wire format or the public API. Tested on 3.13 and
3.14, 274 tests under -X dev with ResourceWarning as an error, oracle
fixtures unchanged, and live against an RM4 Pro.

Technical details:
- A NetworkTimeoutError or EndpointClosedError during the library's own
  re-authentication propagates instead of being swallowed in favour of
  the device's original expired-key reply, so a network failure is
  reported as one.
- _open_endpoint binds to ("0.0.0.0", 0) when neither address is given
  (discovery, ping, setup), for the proactor loop on Windows.
- The RM Max comment and the 1.0.0 changelog entry say only what upstream
  mjg59#838 showed: mapping per its diff, testers reported "locked" on auth,
  listed as reported rather than confirmed.
- The undecodable-capture message is debug, not warning.
- _capture_rf_loop closes its inner generator with aclosing.
- Version 1.0.6.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants