I have been waiting for Milight (also sold as Limitless LED and Easybulb) to release a bridge with support for >4 groups for a while, so I was very happy when recently I came across the ability to make your own Milight bridge with an ESP8266 and nrf radio. It’s working so well for me I thought I would share how to get it running to save others any issues I came across. You do not need to solder and it costs around $10!
UPDATE: I have now created a binding for this hub so you do not need to create rules anymore unless you prefer to do things the hard way The binding is found in this following thread:
Advantages of using this hub over using the OEM milight hubs are:
- Supports more than 4 groups from a single hub so all your globes have individual control.
- Updates openhab when the milight remotes are pressed.
- Uses MQTT which is lower latency, less delay for things to happen.
- If you prefer to use the milight binding via UDP instead of MQTT this bridge supports that by using emulation.
- If openhab is re-started the MQTT broker updates the controls in openhab when it re-connects, so the globes match the controls.
- Active opensource project that if new globes are released you only need a new firmware.
In depth details on how to build and what the bridge is can be found here:
http://blog.christophermullins.com/2017/02/11/milight-wifi-gateway-emulator-on-an-esp8266/
A quick overview of the steps to get the hardware going are:
- Connect a nodemcu/esp8266 to your computer via USB
- Download the latest BIN file from here Releases · sidoh/esp8266_milight_hub · GitHub
- Download esp8266flasher if you are on windows GitHub - nodemcu/nodemcu-flasher: A firmware Flash tool for nodemcu
Check the blog above on more info on how to do it from mac or linux. - Open the flasher tool and make sure the flash size is 4mb or whatever your esp8266 board has.
- Flash the bin and then press the reset button on the nodemcu board when complete.
- Connect to the wifi access point of the esp directly and setup to connect to your network. Blog has more info.
- Login by using the IP address of the esp8266 in a web browser and the control panel will show up.
- Connect 7 wires between the two ready made PCBs as shown in the above blog.
You then need to get MQTT running as this method uses the faster and lightweight MQTT protcol and not UDP. If you wish to use the milight binding with this ESP hub you can use the UDP method and details on how to do this are found here.
To get MQTT running google mosquitto and how to install a broker. If using openhabian you can use the linux command ‘sudo openhabian-config’ and select the menu option to install and setup mosquitto for you. Once setup you can use this linux command to watch all milight topics which is handy for fault finding…
mosquitto_sub -u usernamehere -P passwordhere -p 1883 -v -t 'milight/#'
change the -p to your port if not using the default 1883 port.
Next step is to use paperUI to install the MQTT Binding, if this is successful it will auto create a file you need to edit, if the file is missing then the binding is not installed by paperUI.
\OPENHABIANPI\openHAB-conf\services\mqtt.cfg
Put these lines in the file:
mqtt:mosquitto.url=tcp://192.168.1.100:1883
mosquitto.clientId=openHab
mosquitto.user=UserNameForMqttHere
mosquitto.pwd=PasswordHere
mosquitto.qos=0
mosquitto.retain=false
mosquitto.async=true
If you called your broker something other than mosquitto you will need to change the above to match the brokers name. Also change the IP address and port to match the brokers location. You can use localhost instead of an IP.
Reboot your openhab server after saving and it should be setup.
Enter the control panel for the ESP8266 by using any browser and entering the IP address.
Setup the following:
mqtt_topic_pattern
milight/commands/:device_id/:device_type/:group_id
mqtt_state_topic_pattern
milight/states/:device_id/:device_type/:group_id
In the box called “group_state_fields” you need to untick brightness and Color, then you need to tick level, hue and saturation instead. Leave the rest on defaults.
Fill in the other fields for your MQTT broker.
Click save down the bottom and now when you use a milight remote control you will see MQTT topics being created.
Once again you can use this linux command to watch all topics from milight:
mosquitto_sub -u usernamehere -P passwordhere -p 1883 -v -t 'milight/#'
You can also use the mosquitto_pub command to send your own commands and watch the bulbs respond to test before getting into setting up openhabs items.
Now for the changes to OpenHab2 files…
Sitemap:
Text label="Milight hallway globe" icon="light"
{
Switch item=Milight_ID1_G1_State
Slider item=Milight_ID1_G1_Brightness
Slider item=Milight_ID1_G1_CTemp
Colorpicker item=Milight_ID1_G1_Hue
}
Items:
String Milight_ID1_G1_Light {mqtt=">[mosquitto:milight/commands/0x1/rgb_cct/1:command:*:default]"}
String Milight_ID1_G1_EspMilightHub {mqtt="<[mosquitto:milight/states/0x1/rgb_cct/1:state:default]"}
Switch Milight_ID1_G1_State "Light On/Off"
Dimmer Milight_ID1_G1_Brightness "Brightness"
Dimmer Milight_ID1_G1_CTemp "White Color Temp"
Color Milight_ID1_G1_Hue "Color Hue"
These rules MUST be used with firmware 1.6.0 RC3 or higher loaded into the esp8266 otherwise the remote will not control Openhab.
Create a file called ‘milight.rules’ and place it into the “openhab2-conf\rules” folder.
Rules:
rule "Milight_ID1_G1_ONOFF"
when
Item Milight_ID1_G1_State received command
then
Milight_ID1_G1_Light.sendCommand('{"state":"'+receivedCommand+'"}')
end
rule "Milight_ID1_G1_BRIGHT"
when
Item Milight_ID1_G1_Brightness received command
then
var iLEVEL = (receivedCommand as PercentType).intValue
if(Milight_ID1_G1_State.state==OFF) // Needed to keep openhab up to date if incoming MQTT is disabled.
Milight_ID1_G1_State.postUpdate(ON)
Milight_ID1_G1_Light.sendCommand('{"state":"ON","level":'+iLEVEL+'}') // Using level means values from 0 to 100 and not 0-255
end
rule "Milight_ID1_G1_CT"
when
Item Milight_ID1_G1_CTemp received command
then
var iVAL = (receivedCommand as DecimalType).intValue
var iCTEMP = (370-(2.17*iVAL)).intValue // Scale values to range from 370 to 153
if(Milight_ID1_G1_State.state==OFF) // Needed to keep openhab up to date if incoming MQTT is disabled.
Milight_ID1_G1_State.postUpdate(ON)
Milight_ID1_G1_Light.sendCommand('{"state":"ON","color_temp":'+iCTEMP+'}')
end
rule "Milight_ID1_G1_HUE"
when
Item Milight_ID1_G1_Hue received command
then
var iHUE = Math::round((receivedCommand as HSBType).getHue.intValue)
var iSAT = Math::round((receivedCommand as HSBType).getSaturation.intValue)
var iLEVEL = Math::round((receivedCommand as HSBType).getBrightness.intValue)
Milight_ID1_G1_Light.sendCommand('{"state":"ON","level":'+iLEVEL+',"hue":'+iHUE+',"saturation":'+iSAT+'}')
end
// Rule for updating controls in Openhab when a milight remote is used //
// Only use postUpdate in here to prevent Openhab sending a command in response and causing pot. feedback//
rule "Milight_ID1_G1_HubStates"
when
Item Milight_ID1_G1_EspMilightHub changed
then
var sJSONBLOB = Milight_ID1_G1_EspMilightHub.state.toString
var sMODE = transform("JSONPATH","$.bulb_mode", sJSONBLOB)
var sSTATE= transform("JSONPATH","$.state", sJSONBLOB)
var sLEVEL= transform("JSONPATH","$.level", sJSONBLOB)
var Number iLEVEL= Integer::parseInt(sLEVEL).intValue //convert the string to an int.
if(Milight_ID1_G1_State.state!=sSTATE)
Milight_ID1_G1_State.postUpdate(sSTATE)
if(sMODE=="white") // Code to handle a white JSON blob
{
var sCTEMP=transform("JSONPATH","$.color_temp", sJSONBLOB)
var iTempScaled=(((Integer::parseInt(sCTEMP)/2.17)-171)*-1).intValue //Dirty but seems to work. Converts string to int and scale range.
Milight_ID1_G1_CTemp.postUpdate(iTempScaled) //send CT to globe
Milight_ID1_G1_Brightness.postUpdate(iLEVEL) //send new brightness to globe
}
else if(sMODE=="color") // Code to handle a colour JSON blob
{
var String sHUE = transform("JSONPATH","$.hue", sJSONBLOB)
var String sSATURATION = transform("JSONPATH","$.saturation", sJSONBLOB)
Milight_ID1_G1_Brightness.postUpdate(iLEVEL) //update main dimmer item
Milight_ID1_G1_Hue.postUpdate(sHUE+","+sSATURATION+","+sLEVEL) //update color item
}
end
Note: The above is for one of the RGB+WW+CW also called rgb+cct globes which is setup/paired to a remotes device ID of 1 and a group of 1. Each milight remote has a hard coded device ID and for each of these you can have four groups. Bulbs do not have an ID and you pair/sync them to a device ID for a remote. You can have multiple remotes paired to a single globe at the same time. For example I have 1 remote that is paired to every globe in the house for testing, plus I have openhab paired and controlling every globe individually.
These are the better Milight globes to use that have saturation controls that older and cheaper globes do not:
http://www.limitlessled.com/shop/rgbw-ww-cw-light-bulb/