Skip to content

Repository files navigation

Please ⭐ this repo if you find it useful


Donate with PayPal

BroadlinkManager Docker Pulls

BroadlinkManager is a self-hosted web application for managing Broadlink IR/RF devices on your local network. It discovers Broadlink devices, learns and sends IR and RF codes, keeps a searchable library of saved codes, and includes generators and converters for common RF code formats. The backend is built with FastAPI and the bundled python-broadlink library; the UI is a React single-page app with dark and light themes. It runs as a single Docker container or as a Home Assistant add-on.

Table of Contents

Features

  • Device Discovery — scan your network for Broadlink devices; save the device list to a file and reload it later
  • Online Status — each discovered device is pinged every 30 seconds and shown as online or offline
  • IR Code Learning & Sending — put a device into IR learning mode, capture a code (30-second window), and send it with one click
  • RF Code Learning & Sending — guided 3-step RF sweep (hold → press → save) with real-time status polling
  • Temperature Reading — read the temperature from supported devices through the API (/temperature). The thermometer button on the Devices page currently opens the Send panel instead of reading the temperature.
  • Saved Codes Library — store codes (IR/RF) in a SQLite database; add codes manually, search, filter by type, edit, delete, send a code to a chosen device, and export them as CSV
  • RF Code Generator — generate random 433 MHz or 315 MHz RF codes (regular and long-repeat variants)
  • Livolo Code Generator — generate RF codes for Livolo smart switches by remote ID and button code
  • Energenie Code Generator — generate codes for Energenie Type-D 433 MHz RF sockets
  • Change Repeats — change the repeat count of an existing Base64-encoded IR or RF code
  • Hex ↔ Base64 Converter — live bidirectional conversion between hex and Base64 code formats
  • Dark / Light Mode — follows your system preference by default; your choice is saved in the browser
  • Mobile Friendly — responsive layout with collapsible sidebar navigation
  • REST API + Swagger UI — interactive OpenAPI documentation at /docs
  • Prometheus Metrics — HTTP request metrics at /metrics

Screenshots

Devices — Dark Mode

Devices Dark

Devices — Light Mode

Devices Light

Saved Codes

Saved Codes

RF Code Generator

RF Code Generator

Livolo Code Generator

Livolo

Energenie Code Generator

Energenie

Change Repeats

Change Repeats

Hex ↔ Base64 Converter

Convert

About

About

How It Works

flowchart LR
    Browser["Browser<br/>(React UI)"] -- "HTTP :7020" --> API["FastAPI app<br/>(uvicorn)"]
    API -- "UDP broadcast discovery,<br/>learn / send" --> Devices["Broadlink devices<br/>(RM, SP, ...)"]
    API --> DB[("SQLite<br/>data/codes.db")]
    API --> JSON["data/devices.json<br/>(saved device list)"]
Loading
  • A single Python process (broadlinkmanager.py) starts uvicorn on port 7020. It serves the REST API and the built React app from the same origin.
  • Discovery sends UDP broadcast packets from each local interface IP (see Configuration), then authenticates every device that answers.
  • Learned codes are returned as hex strings. The code generators and the Change Repeats tool work with Base64 (the format Home Assistant uses). The Convert page translates between the two.
  • Saved codes are stored in a SQLite database (codes.db); the device list can be saved to devices.json. Both live in the data/ directory next to the application.
  • The code generators (RF, Livolo, Energenie), Change Repeats, and the converter run entirely in the browser.

Requirements

  • A Broadlink device (see Supported Devices) on the same local network and subnet as the host running BroadlinkManager
  • Docker (with host networking), or Home Assistant OS / Supervised for the add-on, or Python 3.12 and Node.js 20.19+ (or 22.12+) to build and run from source
  • The host must be able to send and receive UDP broadcasts on the LAN for discovery

Installation

Published image status: the newest image on Docker Hub is techblog/broadlinkmanager:6.0.0 (also tagged latest), published in July 2024. It predates the React UI described in this README: it ships the older server-rendered UI and stores its data in /opt/broadlinkmanager/data instead of /app/data. The Docker snippets below target that published image. Paths under /app/data apply only to images built from the current source.

Docker Compose (recommended)

services:
  broadlinkmanager:
    image: techblog/broadlinkmanager:6.0.0   # same as latest
    container_name: broadlinkmanager
    network_mode: host
    restart: unless-stopped
    volumes:
      - ./data:/opt/broadlinkmanager/data   # use ./data:/app/data for an image built from current source

Why network_mode: host? Broadlink device discovery uses UDP broadcast packets on the local network. Host networking allows the container to send and receive those broadcasts. Without it, auto-discovery will not find any devices.

Once the container is running, open your browser at:

http://<docker-host-ip>:7020

Docker CLI

docker run -d \
  --name broadlinkmanager \
  --network host \
  --restart unless-stopped \
  -v "$(pwd)/data:/opt/broadlinkmanager/data" \
  techblog/broadlinkmanager:6.0.0

For an image built from the current source, mount /app/data instead.

Images are built for linux/amd64, linux/arm64, and linux/arm/v7.

Home Assistant Add-on

This repository is also a Home Assistant add-on repository (see repository.yaml and config.yaml).

  1. In Home Assistant, go to Settings → Add-ons → Add-on Store.
  2. Open the ⋮ menu → Repositories and add:
    https://github.com/t0mer/broadlinkmanager-docker
    
  3. Install Broadlink Manager, then start it.
  4. Open the web UI from the add-on page, or browse to http://<home-assistant-ip>:7020.

The add-on runs with host networking (so discovery works), exposes port 7020/tcp, supports aarch64, amd64, armhf , and armv7, and adds a Broadlink Manager entry to the sidebar (ingress).

Add-on caveats: config.yaml has no image: key, so the Supervisor builds the add-on locally from this repository's Dockerfile (which currently may not produce a working image — see Development). There is also no map: entry and the app stores its data in /app/data inside the container, not in the add-on's persistent /data, so saved codes and the saved device list are lost when the add-on is rebuilt or updated.

Build from Source

git clone https://github.com/t0mer/broadlinkmanager-docker.git
cd broadlinkmanager-docker

# Build the React UI (output goes to broadlinkmanager/dist)
cd broadlinkmanager/web
npm ci
npm run build
cd ..

# Install Python dependencies and run
pip install -r requirements.txt cryptography
mkdir -p data
python broadlinkmanager.py

The vendored broadlink library needs the cryptography package, which is not listed in broadlinkmanager/requirements.txt, so it is installed explicitly above. The data/ directory must exist before start-up, because the SQLite database is created there.

Configuration

Environment Variables

Variable Default Description
DISCOVERY_IP_LIST (auto-detected with hostname -I) Comma-separated list of local IP addresses to discover from. Useful when the host has multiple network interfaces. Example: 192.168.1.10,192.168.2.10. Ignored when --ip is given.
DB_PATH <app dir>/data/codes.db (/app/data/codes.db in the container) Path to the SQLite database file for saved codes. Current source only; the published 6.0.0 image always uses data/codes.db (/opt/broadlinkmanager/data/codes.db).

CLI Flags

You can pass arguments to broadlinkmanager.py to override discovery behaviour:

Flag Default Description
--ip <IP> (auto) Local interface IP to discover from. Repeatable. Takes precedence over DISCOVERY_IP_LIST.
--dst-ip <IP> 255.255.255.255 Destination address for discovery broadcasts
--timeout <s> 5 Accepted, but currently not used: discovery always waits 5 seconds

Arguments can also be read from a file with the @ prefix (for example python broadlinkmanager.py @args.txt).

Discovery interfaces are resolved in this order: --ip flags → DISCOVERY_IP_LIST → all addresses from hostname -I.

Example (Docker Compose, published 6.0.0 image — its entrypoint is already python3 broadlinkmanager.py, so pass only the flags):

command: ["--ip", "192.168.1.50"]

For an image built from the current source (which has no entrypoint), use the full form:

command: ["python", "broadlinkmanager.py", "--ip", "192.168.1.50"]

Fixed Settings

Setting Value
Listen address / port 0.0.0.0:7020 (not configurable)
Devices file <app dir>/data/devices.json
IR / RF learning timeout 30 seconds

Home Assistant Add-on Options

config.yaml declares the options ssl (default false), certfile (default fullchain.pem), keyfile (default privkey.pem), and log_level. The application does not read any of them, so changing them has no effect.

Persistent Data

Path (current source) Path (published 6.0.0 image) Contents
/app/data/codes.db /opt/broadlinkmanager/data/codes.db SQLite database of saved codes
/app/data/devices.json /opt/broadlinkmanager/data/devices.json Device list saved from the Devices page

With Docker, mount the data directory as a volume so your codes survive container updates. This does not apply to the Home Assistant add-on (see the add-on caveats above).

Usage

  1. Discover devices. The Devices page scans the network when it opens. Use Rescan to scan again, Save to write the current list to devices.json, and Load to restore it without scanning.
  2. Open the command panel. Click a device's IR, RF, or Send button to open the side panel with the IR Code, RF Code, and Send tabs. The buttons are disabled while the device is offline.
  3. Learn an IR code. Click Learn IR, point the remote at the Broadlink device, and press the button within 30 seconds. Name the captured code and save it, or copy it.
  4. Learn an RF code. Start the sweep, then press and hold the remote button until the frequency is found. Release the button, click Continue Sweep, then press the button once to capture the code. Name it and save it.
  5. Send a code. Paste a hex code, or pick one from your saved codes, and click Send.
  6. Manage saved codes. The Saved Codes page lists all codes (10 per page), with search by name, an IR/RF filter, edit, delete, and Export CSV. Add Code stores a code entered by hand (the form accepts Base64 or hex, but sending only works with hex). The per-code send button sends a saved code to a device you pick.
  7. Generate and convert codes. Use RF Generator, Livolo, Energenie, Repeats, and Convert from the sidebar. These tools produce Base64 codes.

Supported Devices

Family Models
SP1 SP1
SP2 SP2, SP mini, SP2-compatible (Honeywell, URANT), NEO (Ankuoo), SP mini 3, MP2, SP2-CL, SC1
SP2S SP2, NEO PRO (Ankuoo), Ego (Efergy), SP mini+
SP3 SP3, SP3-EU
SP3S SP3S-US, SP3S-EU
SP4 SP4L-CN/EU/AU/UK/US, SP4M, SP4M-US, MCB1, SCB1E, SCB2, SP mini 3
RM mini RM mini, RM mini 3 (all variants)
RM pro RM pro/pro+, RM home, RM plus
RM mini B RM mini 3 (0x5F36, 0x6507, 0x6508)
RM4 mini RM4 mini, RM4C mini, RM4S, RM4 TV mate, RM4C mate
RM4 pro RM4 pro, RM4C pro
Sensors e-Sensor (A1)
Lights LB1, LB26 R1, LB27 R1, SB500TD, SB800TD
Power strips MP1 (MP1-1K4S, MP1-1K3S2U) — supported by the bundled library, but shown as "Not Supported" in the UI because they are missing from the app's device name list
Alarm S2KIT
Hub S3
Climate HY02/HY03 (Hysen)
Cover DT360E-45/20 (Dooya)
BG Electrical BG800/BG900, AHC/U-01

IR/RF learning and sending need a remote-capable device (RM family). RF learning requires an RF-capable model (for example RM pro or RM4 pro).

REST API

Interactive API documentation is available at http://<host>:7020/docs (Swagger UI). Some endpoints used by the UI are hidden from Swagger; they are included below.

Device endpoints take the device parameters returned by /autodiscover as query parameters: host (IP), mac (hex, no separators), and type (device type, e.g. 0x5f36).

Method Path Parameters Description
GET /autodiscover freshscan (1 = scan, default; 0 = return saved list if present) Discover Broadlink devices
GET /device/ping host Check whether a device is online
POST /devices/save JSON array of {name, type, ip, mac} Save the device list to devices.json
GET /devices/load — Load the saved device list
GET /ir/learn host, mac, type Learn an IR code (waits up to 30 s); returns the code as hex
GET /rf/learn host, mac, type Start the RF sweep; returns the code as hex when finished
GET /rf/status — Poll RF learning status
GET /rf/continue — Continue the RF sweep after the frequency is found
GET /command/send host, mac, type, command (hex) Send an IR/RF code
GET /temperature host, mac, type Read the temperature from a supported device
GET /api/codes — List all saved codes
GET /api/code/{id} — Get one saved code (returned as a one-element array)
POST /api/code JSON {CodeType, CodeName, Code} Save a new code
PUT /api/code/{id} JSON {CodeType, CodeName, Code} Update a saved code
DELETE /api/code/{id} — Delete a saved code
GET /api/version — Get the application version
GET /metrics — Prometheus metrics

Examples:

# Discover devices
curl "http://localhost:7020/autodiscover"
# [{"name": "RMmini3 (Broadlink)", "type": "0x5f36", "ip": "192.168.1.20", "mac": "a1b2c3d4e5f6"}]

# Send a hex code
curl "http://localhost:7020/command/send?host=192.168.1.20&mac=a1b2c3d4e5f6&type=0x5f36&command=2600..."
# {"data": "", "success": 1, "message": "Command sent successfully"}

# Save a code
curl -X POST "http://localhost:7020/api/code" \
  -H "Content-Type: application/json" \
  -d '{"CodeType": "IR", "CodeName": "TV Power", "Code": "2600..."}'
# {"message": "Code inserted successfully.", "success": 1}

Using Codes in Home Assistant

The Home Assistant Broadlink integration sends Base64 codes. To use a code learned in BroadlinkManager (hex), convert it on the Convert page and send it with the b64: prefix:

action: remote.send_command
target:
  entity_id: remote.living_room_rm
data:
  command: b64:JgBIAAABK5QQ...

Codes from the RF, Livolo, and Energenie generators and from Change Repeats are already in Base64.

Security Notes

  • There is no authentication. Anyone who can reach port 7020 can discover devices, send IR/RF commands, and read, change, or delete saved codes.
  • CORS allows all origins (*), so any web page opened in a browser on your network can call the API.
  • The app listens on all interfaces (0.0.0.0) and, with host networking, is reachable on every host IP. Keep it on a trusted LAN and do not expose it to the internet; put it behind a reverse proxy with authentication if you need remote access.

Troubleshooting

  • No devices found — make sure the container uses host networking and the device is on the same subnet. If the host has several interfaces, set DISCOVERY_IP_LIST or --ip to the LAN address. If broadcasts to 255.255.255.255 are blocked, try the subnet broadcast address with --dst-ip (for example 192.168.1.255).
  • Device shows as "Not Supported" — its device type ID is not in the name list. It may still work if python-broadlink supports it.
  • "Send failed" when sending a Base64 code — the send endpoint only accepts hex. Convert Base64 codes to hex on the Convert page first.
  • "No Data Received" / "RF Frequency not found!" — learning times out after 30 seconds. Start again and press the button sooner, closer to the device.
  • Saved codes disappear after an update — with Docker, mount the data directory as a volume (see Persistent Data). The Home Assistant add-on currently cannot keep data across rebuilds.
  • "Frontend not built yet" — the React UI has not been built into broadlinkmanager/dist. Run npm run build in broadlinkmanager/web.

Development

Project layout:

broadlinkmanager/
├── broadlinkmanager.py   # entry point — starts uvicorn on :7020
├── app/
│   ├── main.py           # FastAPI app, routers, SPA fallback, /metrics
│   ├── config.py         # CLI args, discovery interfaces, paths
│   ├── db.py             # SQLite access (DB_PATH)
│   ├── state.py          # RF sweep state
│   └── routers/          # devices, commands, codes
├── broadlink/            # vendored python-broadlink library
├── web/                  # React + TypeScript + Vite + Tailwind UI
├── dist/                 # built UI (generated)
└── VERSION
config.yaml, repository.yaml   # Home Assistant add-on metadata
Dockerfile                     # multi-stage build (Node → Python)

Run the backend and the UI dev server with hot reload:

# Terminal 1 — backend on :7020
cd broadlinkmanager
pip install -r requirements.txt cryptography
mkdir -p data
python broadlinkmanager.py

# Terminal 2 — UI on :5173 (proxies API calls to :7020)
cd broadlinkmanager/web
npm ci
npm run dev

Lint the UI with npm run lint. The application version is read from broadlinkmanager/VERSION.

Build the Docker image locally:

docker build -t broadlinkmanager .

Contributing

Issues and pull requests are welcome at github.com/t0mer/broadlinkmanager-docker. Please keep changes focused and describe how you tested them.

Credits

License

This project is licensed under the Apache License 2.0.

Donation

If you find this project useful, consider buying me a coffee ☕

Donate with PayPal

About

Self-hosted web app and Home Assistant add-on to discover Broadlink devices and learn, send, save and convert IR/RF codes

Topics

Resources

Stars

324 stars

Watchers

13 watching

Forks

Releases

Packages

Used by

Contributors

Languages