It’s taken me some time to get this all working, so I hope this is useful for someone else!
The situation
The room has one of these fan/light combos on the ceiling. The whole fixture can be controlled via the included infra-red (IR) remote, which looks like this:
To enable automation of the fan/light I got a Broadlink RM4C Mini (branded as BestCon).
Click here for prerequisites
- MQTT broker - I use Mosquitto , setup as per its defaults
- On my setup, Mosquitto and OpenHab are running on the same device, at 192.168.1.92
- Javscript Transformation installed in OpenHab
- PaperUI -> Add-ons -> Transformations -> Javascript Transformation -> Install
Click for system details
Setup was on a Raspberry Pi 3B+ on Stretch, with OpenHAB2 2.5.3, as shown below. A mosquitto
mqtt broker is also running on the network, and python3
is installed.
pi@raspberrypi:~ $ cat /etc/os-release
PRETTY_NAME="Raspbian GNU/Linux 9 (stretch)"
NAME="Raspbian GNU/Linux"
VERSION_ID="9"
VERSION="9 (stretch)"
VERSION_CODENAME=stretch
pi@raspberrypi:~ $ apt list openhab2
Listing... Done
openhab2/stable,now 2.5.3-1 all [installed]
Configuration
Install python-broadlink
Install the python-broadlink
package directly from github. I used the following commands:
sudo apt-get install python3-dev python3-pip git
git clone https://github.com/mjg59/python-broadlink.git
cd python-broadlink
python3 -m pip install pycrypto
python3 -m pip install netaddr
python3 -m pip install --upgrade pyopenssl
sudo python3 setup.py install
Connect RM4C Mini to wifi
The following methods will connect the RM4C Mini to the local wifi network:
- The first method uses only the
python-broadlink
project - The second uses the Broadlink app
I recommend trying the first option first, if only so you don’t have to make a Broadlink account.
Important Only get the RM4C Mini connected to your wifi network - DO NOT allow it to connect to the cloud.
Method 1 - python-broadlink
Important Perform the following steps using your native/local machine, not through an SSH terminal. This method will connect your device to the RM4C Mini’s wifi, so you may lose your SSH connection!
- Connect the RM4C Mini to power, and press the reset button until the blue light starts to flash quickly (multiple times a second).
- Press the reset again for longer (>10 seconds) until the blue light starts to flash more slowly (about once per second).
- The RM4C Mini is now a wifi access point. Connect your computer to the access point (it will probably have
Broadlink
in the name). It may take a little bit of time for the access point to appear in your wifi list. - Once connected, in a terminal on your computer, start the python console by typing
python3
and hitting enter.
python3
- Import the broadlink library by typing the following and hitting enter.:
import broadlink
- Send your wifi credentials to the device by typing the following, swapping out
mysside
andmynetworkpass
for your wifi name and password respectively, and hitting enter.:
broadlink.setup('myssid', 'mynetworkpass', 3)
- You don’t seem to get any feedback to announce it has worked, other than your PC losing connection as the RM4C Mini stops being an access point and connects to your wifi.
- Once I’d confirmed that the RM4C Mini was connected to my network via the wifi routers management pages, I had to re-power the device for the next steps to work (pull the power cable out, count to 10, put the power cable back in).
- At this point, I also blocked the RM4C Mini from accessing the internet, again using the wifi routers management pages.
Note: to exit from the python3 console in your terminal, type exit()
and hit enter.
Method 2 - Broadlink app
- Install the
Broadlink
app from the Android Play store (I presume an iOS equivalent is available) - Make an account with Broadlink - this is unfortunately necessary because you can’t seem to use the app without one
- Exit out of the app completely (for me, that’s pressing the square icon on the Android menu bar at the bottom of the screen, then swiping that app window upwards)
- Connect the RM4C Mini to power, and press the reset until the blue light starts to flash quickly (multiple times a second)
- Press the reset again for longer (>10 seconds) until the blue light starts to flash more slowly (about once per second).
- The RM4C Mini is now a wifi access point. Connect your phone to the access point (it will probably have
Broadlink
in the name). It may take a little bit of time for the access point to appear in your wifi list. - Once connected, start up the Broadlink app. I was asked for a bunch of information again (country etc), and had to login again. There was then a complaint that it can’t connect to the internet, but ultimately it goes through a ‘home screen’, and it will inform you (potentially not immediately) that it has found a compatible device.
- Choose to setup the device, and enter your home wifi name and password. Watch as it sets up the device, then exit the app again.
- Find out the IP address of the RM4C Mini on your network using your wifi router’s management pages. Mine was 192.168.1.120 .
- At this point, I also blocked the RM4C Mini from accessing the internet, again using the wifi routers management pages.
Check connection
Whilst in the python-broadlink
folder in your terminal, move to the cli
folder.
cd cli/
Open the broadlink_discovery
file, and alter the top line so it references Python 3:
#!/usr/bin/env python3
Try to discover the RM4C Mini. Replace the IP address with the one for your RM4C Mini device:
./broadlink_discovery --timeout 10 --dst-ip 192.168.1.120
Hopefully that works, and you will get something similar to the output below:
Discovering...
###########################################
RM4
# broadlink_cli --type 0x62be --host 192.168.1.120 --mac a57c4fa7df24
Device file data (to be used with --device @filename in broadlink_cli) :
0x62be 192.168.1.120 a57c4fa7df24
temperature = 0.0
Install broadlink-mqtt
Note You can now switch to SSHing into your Raspberry Pi, and continue following the steps below.
Setup is as per the installation instructions at on github.
- Ensure the named prerequisites are installed.
- At the configuration step, the only lines I altered in
custom.conf
was entering the correct IP address for my mqtt broker and un-commenting themqtt_birth_topic
andmqtt_birth_payload
lines.
Startup broadlink-mqtt
using python3
from within the broadlink-mqtt
folder:
python3 mqtt.py
[2020-05-03 16:10:50,482] DEBUG Connected to 'RM4' Broadlink device at '192.168.1.120' (MAC 24:df:a7:4f:7c:a5) and started listening for commands at MQTT topic having prefix 'broadlink/'
[2020-05-03 16:10:50,493] DEBUG Connected to MQTT broker, subscribing to topic broadlink/#
Connected! Move this terminal or command window to one side - we’ll call it Terminal 1.
Teach remote codes
Two methods again. The first uses broadlink-mqtt
and should be the easiest. However, this sometimes results in errors (usually as a result of issues with python-broadlink
), so the second method uses the base commands from python-broadlink
. Both routes will ensure you end up at the same place!
Click to teach via broadlink-mqtt
Teach via broadlink-mqtt
To teach broadlink-mqtt
what each button press is for, you:
- Tell
broadlink-mqtt
(via MQTT) that you’re about to press a specific button - Press the button (and keep it pressed) whilst pointing it at the RM4C Mini.
The example below is for the button which turns the light on and off. In a second terminal (Terminal 2) type:
mosquitto_pub -t 'broadlink/masterbedroom/light/power' -m 'record'
Point the remote at the RM4C Mini and press the button until the messages in Terminal 1 says Done, as below:
[2020-05-02 08:25:57,997] DEBUG Received MQTT message broadlink/masterbedroom/light/power record
[2020-05-02 08:25:57,998] DEBUG Recording command to file ~/src/broadlink-mqtt/commands/masterbedroom/light/power
[2020-05-02 08:26:09,023] DEBUG Done
You can test if this has worked by entering the following into Terminal 2, which should force the RM4C Mini to blast out the correct IR command, and switch on the light:
mosquitto_pub -t 'broadlink/masterbedroom/light' -m 'power'
I repeated this process for the 4 fan buttons too: hi, med, low and off:
mosquitto_pub -t 'broadlink/masterbedroom/fan/hi' -m 'record'
mosquitto_pub -t 'broadlink/masterbedroom/fan/med' -m 'record'
mosquitto_pub -t 'broadlink/masterbedroom/fan/low' -m 'record'
mosquitto_pub -t 'broadlink/masterbedroom/fan/off' -m 'record'
Click to teach via python-broadlink
Teach via python-broadlink
In a terminal, enter the python3
console:
python3
Python 3.6.9 (default, Jul 17 2020, 12:50:27)
[GCC 8.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
import the python-broadlink
module by typing import broadlink
and hitting enter. You won’t get any feedback other than a new prompt >>>
:
>>> import broadlink
>>>
discover your device You won’t get any feedback other than a new prompt >>>
:
>>> devices = broadlink.discover(timeout=5)
>>>
check that the device was discovered:
>>> print(devices)
[<broadlink.rm4 object at 0x7fe1e484ce10>]
>>>
connect to your device. This should return True
when connected:
>>> devices[0].auth()
True
>>>
Put device into learning mode. The white LED on the device should then become visible (different devices [non-RM4C Mini] may have different coloured LEDs).
>>> devices[0].enter_learning()
>>>
Point your remote at the device, and keep the desired button pressed until the white LED turns off. Then, in the terminal grab the data:
>>> packet = devices[0].check_data()
>>>
and print the data to the screen:
>>> print(packet.hex())
2600b0040d2b0c2b0d2a0d2a0d2b280f0d2a0d2b0c000108280f290f0c2b0d2a0d2b0c2b0d2a0d2b280f0c2b0d2a0d000108290e290e0d2b0c2b0d2a0d2b0c2b0d2a290f0c2b0c2b0d000108280f290e0d2a0d2b0c2b0d2a0d2b0c2b280f0d2b0c2b0c000108290f280f0c2b0d2a0d2b0c2b0d2a0d2b280f0d2a0d2a0d000108280f290f0c2b0d2a0d2a0d2b0c2b0d2a290f0c2b0d2a0d000108280f280f0d2b0c2b0d2a0d2a0d2b0c2b280f0d2b0c2b0d000107290f280f0d2a0d2b0c2b0d2a0d2b0d2a280f0d2a0d2b0d000107280f290f0c2b0e290d2b0c2b0d2a0d2b280f0c2b0d2a0d000108280f290f0c2b0d2a0d2a0e2a0c2b0d2a290f0c2b0d2a0d000108280f280f0d2b0c2b0d2a0d2a0e2a0c2b280f0d2b0c2b0d000107290f280f0d2a0d2b0c2b0d2a0d2a0e2a280f0d2a0d2b0d000107280f290f0c2b0d2a0d2b0c2b0c2b0e29290f0c2b0d2a0d000108280f280f0d2b0c2b0d2a0d2b0c2b0c2b280f0d2b0c2b0d000108280f280f0d2a0d2b0c2b0d2a0d2b0c2b280f0d2a0d2b0c000108290f280f0c2b0d2a0d2b0c2b0d2a0d2b280f0c2b0d2a0d000108280f290f0c2b0c2b0d2a0d2b0c2b0d2a290f0c2b0d2a0d000108280f280f0d2b0c2b0d2a0e290e2a0d2a280f0d2b0d2a0d000107290f280f0d2a0e2a0d2a0d2a0e290e2a280f0d2a0e2a0c000108280f290f0c2b0d2a0d2b0c2b0c2b0d2a290f0c2b0d2a0d000108280f28100c2b0c2b0d2a0d2b0c2b0c2b28100c2b0c2b0d000108280f280f0d2a0d2b0c2b0d2a0d2b0c2b28100c2b0c2b0c000108281028100b2b0d2a0d2b0c2b0d2a0d2b28100c2a0d2b0c000108281027100c2b0c2b0d2a0d2b0c2b0d2a29100b2b0d2a0d000108281027100c2b0c2b0c2b0d2b0c2b0c2b28100c2b0c2b0c000108291027100c2a0d2b0c2b0c2b0d2b0c2b28100c2a0d2b0c000108281028100b2c0c2b0c2c0b2c0b2b0d2b28100b2c0c2b0c000108281027100c2c0b2c0c2b0c2b0c2c0b2c27100c2c0b2c0c000108281027100c2b0c2c0b2c0c2b0c2b0c2c27100c2b0c2c0b000109281027100b2c0c2b0c2c0b2c0c2b0c2c27100c2b0c2b0c000109271027100c2c0b2c0c2b0c2c0b2c0c2b28100b2c0b2c0c000109271027100c2b0c2c0b2c0c2b0c2c0b2c27100c2c0b2c0b000109281027100c2b0c2b0c2c0b2c0c2b0c2c27100c2b0c2c0b000109271028100b2c0c2b0c2c0b2c0b2c0c2b28100b2c0c2b0c000109271027100c2c0b2c0c2b0c2c0b2c0b2c27110b2c0b2c0c000108281126110b2b0c2c0b2c0c2b0c2c0b2c27110b2b0c2c0b000109271127110a2c0c2b0c2c0b2c0c2b0c2c27110a2c0c2c0b000109271126110b2c0b2c0c2b0c2c0b2c0c2b27110b2c0b2c0c00010a261126110b2c0b2d0a2d0b2c0b2d0a2d26110b2d0a2d0a00010a271126110a2d0b2c0b2d0a2d0b2c0b2d26110b2c0b2d0a00010a261127110a2d0b2c0b2c0b2d0a2d0b2c27110a2d0b2c0b00010a261225120a2d0a2e092d0b2d0a2e092e25120a2e092e0a00010a261225120a2d0a2e092e0a2d0a2d0a2e25120a2d0a2e0900010b25122612092f092e092e092f082f092e2513082f092e0900010c24132413092f082f092f082f0830082f2314082f08300800010d23142315073007300731073007300731221606310631060001102117200001691a000d05000000000000
This huge string is the code which needs to be saved. To double check that it works, you can send this code through python-broadlink
back to your RM4C Mini device, and see whether it has the desired effect (switch things on/off etc):
>>> devices[0].send_data(packet)
>>>
We now need to save this huge string so that broadlink-mqtt
can use it. First, you need to decide what the structure of your MQTT topic will be. For me, the above example captured the power button on the remote, so I’m going to use the topic
broadlink/masterbedroom/light/power
As a result, go into the broadlink-mqtt
folder, then into commands
, and create a folder called masterbedroom
. Inside masterbedroom
, create a folder called light
.
Inside the light
folder, create an empty text file called power
(strictly no extensions such as .txt
), and inside that file copy and paste the huge string you’ve just captured.
And that’s it. I repeated the same thing for the fan commands (hi, med, low, off), saving those into the following topics/files:
broadlink/masterbedroom/fan/hi
broadlink/masterbedroom/fan/med
broadlink/masterbedroom/fan/low
broadlink/masterbedroom/fan/off
Configure OpenHAB
bridge.things
I have a separate file which just contains the bridge Thing to my Mosquitto MQTT broker:
Bridge mqtt:broker:MosquittoMqttBroker "Mosquitto MQTT Broker" [
host="192.168.1.92",
secure=false,
port=1883,
clientID="OpenHAB2"
]
broadlink.things
Thing mqtt:topic:swBedroomLight "Switch Bedroom Light" (mqtt:broker:MosquittoMqttBroker) {
Channels:
Type switch : swPower "Power switch" [
commandTopic="broadlink/masterbedroom/light",
on="power",
off="power"
]
Type switch : swReachable "Reachable" [
stateTopic = "clients/broadlink",
on="Hello!",
off="Adios!"
]
Type number : swFanControl "Fan control" [
commandTopic="broadlink/masterbedroom/fan",
transformationPatternOut="JS:bedroomfan.js"
]
}
bedroomfan.js
Saved into the transform folder:
(function(x) {
var result = "";
switch(x) {
case '0':
result="off";
break;
case '1':
result="low";
break;
case '2':
result="med";
break;
case '3':
result="hi";
break;
default:
result="off";
}
return result;
})(input)
broadlink.items
Switch sBedroomMainLight "Bedroom Main Light" { channel="mqtt:topic:swBedroomLight:swPower", autoupdate="false"}
Switch sBedroomMainLightReachable "Bedroom Main Light Reachable" { channel="mqtt:topic:swBedroomLight:swReachable" }
Number nFanControl "Bedroom fan control" { channel="mqtt:topic:swBedroomLight:swFanControl" }
Sitemap
(See the next post for alternative Sitemap configurations)
Switch item=sBedroomMainLight label="sBedroomMainLight" mappings=[ON="PUSH"]
Setpoint item=nFanControl label="Fan speed [%d]" icon="fan" minValue=0 maxValue=3 step=1
I hope this helps someone, and would be happy to hear about more efficient or elegant methods! I’m especially interested in any solutions for the dimmer button. When pressed, this reduces the brightness to a minimum level, then increases it again to maximum. Each press is a decrease or increase, depending on which part of the curve the light is currently on…
Edits
Edit 27/12/2020: Added command to upgrade existing pyopenssl
package.
Edit 23/08/2020: Added section in teaching codes to use base python-broadlink
commands, as some are having issues with teaching via broadlink-mqtt
.
Edit 17/08/2020: Improved formatting slightly, and added instructions to ensure the discovery script is run using Python 3.
Edit 04/08/2020: Added notes regarding what device you should be performing particular actions with.
Edit 31/05/2020: Managed to setup the device on the Wifi without needing the app! Instructions updated.
Edit 30/05/2020: broadlink-mqtt has now implemented Last Will and Testament (LWT) messages. Added the default configuration into the thing and item descriptions.