Milight WiFi Gateway Emulator on an ESP8266

Milight bulbs* are cheap smart bulbs that are controllable with an undocumented 2.4 GHz protocol. In order to control them, you either need a remote* (~$13), which allows you to control them directly, or a WiFi gateway* (~$30), which allows you to control them with a mobile app or a UDP protocol.

A few days ago, I posted my Arduino code to emulate a Milight WiFi gateway on an ESP8266 (link). This allows you to use an NRF24L01+ 2.4 GHz tranceiver module* and an ESP8266* to emulate a WiFi gateway, which provides the following benefits:

  1. Virtually unlimited groups. The OTS gateways are limited to four groups.
  2. Exposes a nice REST API as opposed to the clunky UDP protocol.
  3. Secure the gateway with a username/password (note that the 2.4 GHz protocol used by the bulbs is inherently insecure, so this only does so much good).

I wanted to follow up with a blog post that details how to use this. I’m going to cover:

  1. How to setup the hardware.
  2. How to install and configure the firmware.
  3. How to use the web UI and REST API to pair/unpair and control bulbs.

Shopping List

This should run you approximately ~$10, depending on where you shop, and how long you’re willing to wait for shipping. Items from Chinese sellers on ebay usually come at significant discounts, but it often takes 3-4 weeks to receive items you order.

  1. An ESP8266 module that supports SPI. I highly recommend a NodeMCU v2*.
  2. An NRF24L01+ module. You can get a pack of 10* on Amazon for $11. You can also get one that supports an external antenna if range is a concern (link*).
  3. Dupont female-to-female jumper cables (at least 7). You’ll need these to connect the ESP8266 and the NRF24L01+.
  4. Micro USB cable.

If you get a bare ESP8266 module, you’ll need to figure out how to power it (you’ll likely need a voltage regulator), and you’ll probably have to be mildly handy with soldering.

Setting up the Hardware

The only thing to do here is to connect the ESP8266 to the NRF24L01+ using the jumper cables. I found this guide pretty handy, but I’ve included some primitive instructions and photos below.

NodeMCU Pinout

NRF24L01+ Pinout

NodeMCU Pin NRF24L01+ Pin
3V (NOT Vin) VCC

Update – Jan 4, 2019: The default CE pin has been changed from D0/GPIO16 to D2/GPIO4 as of version 1.8.6.

Installing drivers

There are a couple of different versions of NodeMCUs (I’m not convinced they’re all actually from the same manufacturer). Depending on which one you got, you’ll need to install the corresponding USB driver in order to flash its firmware.

The two versions I’m aware of are the v2 and the v3. The v2 is smaller and has a CP2102 USB to UART module. You can identify it as the small square chip near the micro USB port:

NodeMCU v2 with CP2102 circled

Install drivers for the v2 here.

The v3 is larger and has a CH34* UART module, which thin and rectangular:

NodeMCU v3 with CH34* circled

The CH34* drivers seem more community-supported. This blog post goes over different options.

I’ve been able to use both the v2 and v3 with OS X Yosemite.

Installing Firmware

If you’re comfortable with PlatformIO, you can check out the source from Github. You should be able to build and upload the project from the PlatformIO editor.

Update – Mar 26, 2017: I highly recommend using PlatformIO to install the firmware. The below instructions are finicky and unless you get the arguments exactly right, the filesystem on your ESP will not work correctly. Using PlatformIO is a more robust way to get a fresh ESP set up. Further instructions are in the README.

Update – Feb 26, 2017: if you’ve used your ESP for other things before, it’s probably a good idea to clear the flash with --port /dev/ttyUSB0 erase_flash . Thanks to Richard for pointing this out in the comments.

If not, you can download a pre-compiled firmware binary here. If you’re on Windows, the NodeMCU flasher tool is probably the easiest way to get it installed.

On OS X (maybe Linux?), following the NodeMCU guide, you should:

  1. Connect the NodeMCU to your computer using a micro USB cable.
  2. Install esptool
  3. Flash the firmware:

    Note that  /dev/cu.SLAB_USBtoUART should be substituted for  /dev/cu.wchusbserial1410 if you’re using a v3 NodeMCU. Be sure to specify the real path to the firmware file.
  4. Restart the device. To be safe, just unplug it from USB and plug it back in.

Setup firmware

Note that you’ll have to do all of these things before you can use the UI, even if you used the pre-compiled firmware:

  1. Connect the device to your WiFi. Once it’s booted, you should be able to see a WiFi network named “ESPXXXXXX”, where XXXXXX is a random identifier. Connect to this network and follow the configuration wizard that should come up.  The password will be milightHub.
  2. Find the IP address of the device. There are a bunch of ways to do this. I usually just look in my router’s client list. It should be listening on port 80, so you could use nmap  or something.

You should now be able to navigate to http://<ip_of_isp>.

Using the Web UI

The UI is useful for a couple of things.

If you have Milight bulbs already, you probably have them paired with an existing device. Rather than unpairing them and re-pairing with the ESP8266 gateway, you can just have the ESP8266 gateway spoof the ID of your existing gateway or remote. Just click on the “Start Sniffing” button near the bottom and push buttons in the app or on the remote. You should see packets start to appear:

The “Device ID” field shows the unique identifier assigned to that device. To have the ESP8266 gateway spoof it, scroll up to the top and enter it:

The controls should not work as expected. You can click on the “Save” button below if you want to save the identifier in the dropdown for next time.

The UI is also useful for pairing/unpairing bulbs. Just enter the gateway ID, click on the group corresponding to the bulb you wish to pair/unpair, screw in the bulb, and quickly (within ~3-5s) press the appropriate button. The bulb should flash on and off if it was successful.

Using the REST API

The UI is great for poking around and setting things up, but if you want to tie this into a home automation setup, you’ll probably want a programmatic interface. The API is fully documented in the Github readme, but here’s a quick example:

This will turn bulbs paired with device 0xCD86, group 2 on and set the color to red (hue = 0).

UPDATE – Feb 12, 2016

I realized this project would be a lot more immediately useful to people if it just supported the existing Milight UDP protocol. This would allow people to use the existing integrations others have built for OpenHab, Home Assistant, SmartThings, etc.

The Web UI has a section to manage gateway servers. Each server will need a device ID and a port.

* Amazon affiliate link.

558 thoughts on “Milight WiFi Gateway Emulator on an ESP8266

  1. Hi Chris,

    Thank you for this great Blog!
    I own 4 RGBWW (FUT017) bulbs and can’t get it to work with the OpenHab2 Milight binding.
    I just ordered the suggested modules etc. and I’ll definitely try to get this to work when these arrive.

    There’s just a question I have, before connecting them.
    Can I power the ESP8266 module via USB from my Raspberry Pi 3?
    Or is the USB port on my RPi 3 not good enough for that? I read it’s not always powerful enough for powering devices via the RPi USB port.

    • Hi Jorg,

      Hope it works out for you!

      There’s a troubleshooting guide here in case you run into trouble (hopefully you don’t 🙂 —

      Judging from This FAQ, it looks like RPi 3 B can supply up to 1.2A to USB peripherals. That should be more than enough for an ESP8266 with an nRF24L01, assuming the power supply to the RPi itself is good enough to handle that.

      If you do run into trouble, it’s probably good to have a backup plan, though. At least to rule it out. 🙂

  2. Hello Christop,

    Nice project! Is it also possible to make a Arduino software version?
    That will be a bit easyer for my domotica set.

    Greetings Mark

    • Hi Mark,

      Do you mean for hardware other than ESP8266?

      Currently not possible, and my guess is that it’d be quite a large undertaking.

      The current software relies pretty heavily on the ESP8266-specific SDK for things like WiFi, TCP, etc.

  3. Is it possible convert RF packets/signals from a supported Milight remote control using the Milight WiFi Gateway to MQTT?

  4. I have a couple of Milights that I have not used for a while. They where paired to some gateway when I last used them. How can I add the bulbs using the web UI?

    • Hi Cliff,

      If you’re not able to pair the devices with a Device ID you choose (under normal circumstances, you can just pick whatever ID you want in the range 0x0000 — 0xFFFF), then you’ll need to figure out what the Device ID of your old gateway is. You can do this using the sniffing function on espMH.

  5. I have this workin great by itself, but currently I am trying to integrate it with OpenHAB 2.

    I have the UDP server set like this:
    Device ID: 0xCD86

    UDP Port: 8899

    Protocol V: 6.

    My OH2 can not detect the gateway. Which version gateway does this emulate?

    I can successfully control the bulbs though MQTT running on my OH sever but I am limited with that method of control. I am using this binding.

    Not entirely sure what different settings I need.

    To others wanting to control these through MQTT, my  OH instance can only send certain commands it seems through MQTT, so the command the bulbs need wouldn’t work unless  I had another ESP with a callback function listening for me to publish an “On” from a OH item to a MQTT topic then having the other ESP wait for that and publish the actual command. Haven’t tested that, its just speculation of what could work.

    However using the built in UDP with the OH would be much more efficient and easier, and allow for more control.

    Any ideas what UDP version I should use? And what version bridge this emulates?

  6. Hi Chris,

    Excellent work with this hub software. I have it working with a Wemos D1 (R1) and only had to adapt the pin out on this board for the R24. Have the MiLight manager smart app installed and have Alexa controlling all the lamps (had to convert Hex to Dec to get the codes into the manager). Works flawlessly with the RBC+CCT (Lighteu) led lamps that I got off Amazon for a bargain (3 for £13.10 with controller!) together with NRF24L01 transmitters (2 for £10). I can get all the modes and speeds operating from voice so a very happy bunny!


    Many thanks for the effort you put in to pull all this together!

  7. Hello Chris,

    Using version 1.6.4  which after all the help over the last few months is working fantastic for me, I have come across something that may be an issue.

    Using Advanced IP Scanner to find out IP addresses in my network (my memory is terrible and I forgot my router password…. hence using the scanner –  would usually just look at the IP table on router), when the software scans the gateway some of my milight bulbs flash random, then settle back to their current setting.  Its nothing more than an amusing blip but I thought I should mention this – in case its a symptom of something dodgy that needs looked at 🙂

    Great work as ever ! I have been very pleased with my slapped together home automation using DIY stuff like your gateway its a great educational hobby for me.

    I experienced my first major power cut and power flickers last week and my home automation was going nuts !!!  Hahahaha but it all settled down within a few minutes of power restoration.





    • Hi Mark,

      That sounds pretty weird. Have no idea what would be causing that. Would need some packet logs and a dump of your ESPMH settings to know what’s going on.

  8. Hi Chris,

    It’s mostly working great. On/off is fine..colours are fine..

    If I alter the brightness though sometimes it gets stuck. Can’t do anything with that bulb until I reset the gateway. Doesn’t work from the gateway or home assistant

    Once it’s reset it all starts working again.

    How do i go about checking logs for errors?




  9. Having some issues getting this to work.


    I have flashed my NodeMCU v3 and have the web portal working.

    I can sniff traffic and get the device id’s of my current Mi-Light controllers.


    How ever as soon as I try to control lights it seems to be causing the NodeMCU to reset.

    Any help would be greatly appreciated.

  10. I’m back on the project now as I have OpenHAB all up and running.


    For the benefit of everyone else I would like to post a solution to what has just taken me a few hours to understand 🙂


    From the web interface the bulbs respond as expected when setting rgb values

    From MQTT they do nothing

    I send {“state”:”ON”,”brightness”:”255″,”bulb_mode”:”color”,”color”:{“r”:”0″,”g”:”0″,”b”:”255″}} and status reports {“state”:”ON”,”brightness”:255,”bulb_mode”:”color”,”color”:{“r”:255,”g”:131,”b”:0}} or some other random rgb value. Bulb does not react.

    It never misses a beat from the web gui though.

    I changed the packet repeats from 5 to 50 and now it seems to work perfectly. The tx (Bangdoog long-range one) is 2m from the bulbs so not far. I do though have lots of 2.4GHz wifi around so perhaps it’s noisy.


    Anyway, all away now. Thanks again for the good effort!

  11. Just wanted to say thank you for this awesome code!! I have hooked up CCT LED light strip and also RGBW lights bulbs to this gateway, without any issues, and connected them to my home assistant with minimal effort. You rock for sharing this code with everyone!!

    • Hi Patrick,
      Can you tell me exactly how you connected the CCT LED strip to the ESP8266? I’d also like to try this.

  12. Hi Chris,

    Thanks a lot for this. I’m using 2 nodemcu v2 with about 25 bulbs of various types. This works great most of the time.

    I do have 2 issues that I could not solve in spite of research:

    Bulb icons in Home Assistant stay black. I have read: and My hubs are set up with states: state, brightness, mode, kelvin, color_temp, bulb_mode and computed_color. My HASS config is:

    Played around with setting for a while, with no luck… Am I missing something?

    When switching groups that contain more than 4 or 5 bulbs, quite often some stay in their previous state. Settings for repeats are: Packet Repeats: 50. The rest is defaulted. I’ve noticed this behaviour with both RGB CCT and RGBW. Are there better settings to apply?

    Here are the states published in home assistant:

    I’m not far from having all working together and hope you can help to make it that little bit better as I’ve run out of ideas.


    PS: Here are the states recorded in Hass:

    brightness: 255 color_temp: 150 min_mireds: 154 max_mireds: 500 rgb_color: 0,0,0 friendly_name: Patio Bench assumed_state: false supported_features: 59

    • So, I checked again on the Github repo and found the issue about black bulbs and the recommendation to use computed_color instead of color or rgb.
      Now doing this works, as in the bulb icons in Hass change color to reflect the changes. On the other hand, there is no more any optiom to change the color in Hass.
      Using both rgb: true and computed_color:true makes the color picker reappear in Hass, but again there the bulbs remain black. Has anyone managed to get both the color picker and the Home Assistant icons to change color?

  13. I can’t seem to get this connected to my wifi. It just continues to boot back as an access point prompting me for WiFi details.

    I used platformIO to build and upload the flash.

    Any help would be appreciated.

    • Hi Paul,

      I’d recommend checking serial logs. It’s very unlikely that this is a problem with espMH, as lots of people have got it working with their WiFi.

    • It turns out it was the router. I was using an crappy old one I had laying about. I could connect to it fine with other devices, but the esp didn’t like it.

      It worked perfectly with the one exception that I needed to touch the transmitter onto the bulb to get it to pair. Very snappy response time, I just have to get the rest of the ecosystem figured out now.

      It is a shame however that the standard bulbs can’t do RGB and white at the same time however. It would be very useful for tweaking an exact white point.


    Hey I would really appreciate if you can give me an advice or point me to the right direction..

    I was trying to use your software using mqtt in homeassistant, but I’m having a hard time to set it up. I can control the lights using my browser but I’m not able to make it work in homeassistant, it won’t do anything.

    I have these settings:

    milight hub:
    mqtt_topic_pattern: milight/commands/0xF63/rgb_ctt/3
    mqtt_state_topic_patter: milight/states/0xF63/rgb_ctt/3

    mqtt_username: test
    mqtt_password: test

    configuration.yaml in homeassistant

    port: 1883
    username: test
    password: test

    – platform: mqtt_json
    name: “bedroom”
    command_topic: “milight/0xF63/rgb_ctt/3”
    state_topic: “milight/states/0xF63/rgb_ctt/3”
    brightness: true
    rgb: true
    color_temp: true

    In group_state_fields I have level,hue, saturation, state, mode, color_temp, bulb_mode and computed_color enabled.

    I would appreciate any help, I don’t know what else to do..

  15. Pingback: Milight Gateway - Dinstructions

  16. Hello Chris and Group,

    Chris you mention that the emulator can support virtually unlimited groups, however I’m having a hard time finding how to add the additional groups beyond the 4 on the GUI interface.

    If you or someone else in the group would be able to point me in the right direction that would be appreciated.

  17. Hello Chris,


    I’m probably blind but I can’t find a section on how to create ‘unlimited’ groups, can you point me to it?

    I’ve received yesterday the nrf2401+ with external antenna, I have used an NodeMCUv2 who had other firmware on it and it took me some time to find out that erasing the flash was necesary(I’m on Ubuntu), after that I could correctly flash the firmware, second problem was that I could sniff my only remote but  couldn’t  send commands to the bulbs, after some fiddling with the dupont wires that’s fixed too.

    (I only have 4 CCT warm/cold white Milights in 3 groups), recently I bought a 9 W RGB + CCT LED Lamp (according to the well known chinese webshop it’s a  FUT012) without a remote but with a wifi ibox2 (the one without a led light).

    I want to get rid of the wifi Ibox2 because I never got it to work in home assistant and now your solution works great !!!

    The only thing I want to know is how to ‘create’ a new group for my rgb+cct led lamp.


    Thank you !


    • Hi Dirk,

      This is achieved by using different Device IDs. You can set a different device ID in the UI, the REST API, and in the MQTT topic.

      Each Device ID is limited to four (eight in the case of the FUT089 remote type) groups, but you can use an arbitrary number of device IDs with espMH.


    • Hello,

      Tried to add a new ID, that works as long as I don’t select the first ID, if I do that I’m not able to select the second ID anymore, however I still can access the paired bulbs from the second ID via MQTT, a bug?


    • Forgot to mention that if I restart the milight hub, then the second ID is gone (only the first ID is in the dropdown list), but I still can access the paired bulbs from the second ID via MQTT

    • The IDs in the UI are just cosmetic. They’re only there for the convenience of not needing to type it in each time.

      They’re not saved automatically. Click on the “Save” button way down at the bottom and they’ll be persisted. There’s an open Github issue to make this less goofy. They should just be persisted automatically, but aren’t for now.

  18. Hi, Cheers for this project. Maybe I am having a bit of brain fade, but I can’t seem to get the Web UI to load. I load up the compiled image (Have tried from both Platformio and Loading the Release file), then I connect to the Wifi, and make the ESP connect to my home Wifi. From here I am able to get the JSON data from the “/settings”, “/about” and “/radio_configs” addresses, but the “/” WebUI refuses to load correctly. My PC just seems to sit there waiting for the page to load, and I do get the “MiLight Hub” in the title bar sometimes.

    I note that on the Readme file you indicate that the WebUI must be uploaded, but I can’t find instructions on how to achieve this. From looking at the logic, it would appear that the HTML file gets compiled and the webpage is available as a variable, so I don’t think this should be the issue.

    I have tried it on a couple of ESPs that I have with the same result, although they have both had other files loaded previously (ESPEasy and McLighting), so it may be related to those having been loaded previously? I have a new one that just arrived which I will test when I get a chance.

    • Hi,

      Nah, you’re right. The web page has been baked into the firmware since v1.5. There’s no need to upload it. I removed the outdated language from the README. Thanks for pointing that out.

      The page that’s served references some cloud-hosted javascripts and stylesheets. Just basic libraries like jquery and bootstrap. Are you on a wifi connection that doesn’t have Internet access? That’s the only thing I can think of that’s consistent with being able to access /about but not /.

      It’d be possible to compact the libraries and put them on the ESP as well, but it comes at the cost of flash space.

  19. Hey! This is awesome! It seems to be working really well for me for standard toggles of lights however, I seem to have run into an issue when trying to use scenes.

    I have my lights setup like this:

    And scenes setup like this:

    Yet is seems that every time I activate something like Lounge Dim, the standard white lights seem to crash. They will dim but then thats it, if I try and turn them on or off or activate another scene they are stuck until I unplug and replug the esp?

    Any ideas? Some help would be greatly appreciated! 🙂

    • Thanks so much for the speedy reply!

      I’m finding it only relates to the white lights? I’ve tried all of your suggestions in the performance tuning guide to no avail.

      I decided to hook it up to the serial monitor and get this response for all of those which fail:

      ERROR: packet buffer full! Cannot buffer a new packet. THIS IS A BUG!

      Any ideas? :-/

    • Ah, that’s definitely a problem. That should be failing for one single brightness command. Are you able to isolate which one it’s for? Maybe I miscalculated the packet buffer size.

    • I’m not sure this will help but I’m not sure what info is useful,

      One simple way i can get it to crash is to mess with the brightness slider for a given white light in home assistant.

      The last MQTT command which was sent was:

      {“state”: “ON”, “brightness”: 93}
      to milight/0x4F7D/cct/1

      then I immediately started to see “ERROR: packet buffer full! Cannot buffer a new packet. THIS IS A BUG!” in the serial monitor.

      Does that help at all?

      It doesn’t seem limited to a given brightness but does seem sporadic.

      Let me know if i can give you anything else?

    • I’ve just been manually publishing new messages which change the brightness to the same topic (milight/0x4F7D/cct/1) with an app on my phone to try and get a common crash and I can’t quite work out the pattern.

      There does seem to be something tied to going from one brightness to another in close succession but nothing reliably repeatable, or if there is, i can’t yet find it! haha.

      Does any of the above give you anything to work off? :-/

    • Hi Chris

      Can i ask if the packet buffer size needs to match the biggest potential or could I just double its size, just to account for any possible miscalculations you mentioned?

      Would there be any implications to just making it a chunk bigger?

      Cheers, John

  20. Hi there, very thanks for this great project.

    I own a CCT bulb and CCT remote, which is paired and working fine. I build a standart nrf & d1_mini hub. It sniffs traffic however I can’t control bulb. To check nrf sending real values, I build another hub with nrf+nodemcu. They can sniff eachothers traffic and remote. Therefore my hubs send data, yet bulb doesn’t respond them. Also pairing doesn’t work

    I tried Web UI, Rest API for upd gateway and mqtt, but either one has same situation. Mqtt updates are published also serial debug shows no problem.

    It’s definitely a radio-link problem, but basic trobleshooting shows no problem in there. Do anyone have an idea or similar situation?

    Thank you.

    • Sounds like the same Problem that i have on an ESP12. Sniffing is wokring great but my Bulbs doesn’t receive anything. With the remote everything is okay. Did already a check of the cabeling. Looks fine so far. Could it be that my Bulbs are too old? Because I have them installed 1,5 years ago. Is this Gateway also compatible with older Bulbs?



    • Thanks for providing all of the troubleshooting info.

      What’s the model number of the bulbs you’re using? I think newer CCT devices don’t work well with the FUT091 (CCT-only) protocol implemented by espMH. Others have had luck using FUT092 (RGB+CCT) instead. Most of the newer CCT-only devices also support the RGB+CCT remotes. There’s some discussion in this Github issue:

      This should be fixed in a later version. However, the FUT092 protocol is actually a lot better because it allows you to set brightness and color temperature directly. With FUT091, you can only send increase/decrease commands.

  21. Hi, great write up! Could we use the sonoff rff  bridge, exchange the current rff module for the nordic 2.4ghz one? Then we have an esp and a nice casing already made for 10usd or so.

    • Hi Kim,

      I’m not familiar with the Sonoff RF bridge. Really the only requirements on the ESP8266 are:

      1. 4MB flash. The firmware image is large enough that 1MB of flash is not sufficient.
      2. SPI pins (GPIOs 12, 13, 14, 15) and one additional GPIO exposed.

      If the Sonoff RF bridge has those two things, it should work just fine.

  22. Hi,

    I am new so bare with me. I have setup the Nodemcu and I can operate a light through the web interface, but now I want to control the light through IFTTT (using Google assistant),


    I can get Google assistant to send me an email so I know that part of the function is working, but to operate the light I am trying to use the IFTTT webhooks services, I assume this is the way to go?

    I am not getting any response though from the bulb.

    The Webhooks section asks for 4 items:


    (Which is correct as I can get this to work from an external network device)


    Method: PUT


    Content type: application/json (other options are text/plain and x-www-form-urlencoded)


    Body: {“status”:”off”}


    If you can advise me of whether this is even possible? Or what I need to change I would greatly appreciate it, have been looking online for hours


    • It should be:

      the true% is extraneous. The integer parsing probably just ignores it, but it’s possible it causes issues.

      Everything else looks correct. If you can send the request externally and it works, and it’s possible to configure IFTTT to send the same request, it should work.

      I’d strongly advise against exposing the interface the world, though. There’s an endpoint that allows firmware upgrades, and an attacker could upload whatever they want.

      At the very least would recommend enabling username/password and putting the ESP8266 in front of a TLS proxy with e.g. nginx.

      Best would be to use something like HomeAssistant, which would take care of the Google Home integration as well.

  23. Hi Chris,

    Interesting project ! Tks for your work.

    This afternoon I tried to setup the hub using a Wemoz D1 Mini and NRF. I successfully write the delivery 1.5 image, configured the WIFI and perform the wiring however, impossible to snif a signal from my remote….

    I’m wondering if I correctly wired the NRF to the D1. I followed this tutorial to perform the wiring (the NRF is one of the ships I really don’t know how it works :-). The wiring is different compared to a NodeMCU.

    Do you have any idea ?

    It seams the WS connection is alive but when I push the buttons of my remote, nothing appears.

    This is a classic Milight remote and I have 4 bulbs E27 RGBWW.

    Tks for your help !


  24. Thanks Chris, weird this is that in Sniff traffic it is showing that it is sending. I don’t know how it works but the request type is different…. (B8 on other 2 but B0 on the emulator). is this significant

    rgbw packet received (4 bytes): (sent from Anymote, channel 2 on)
    Request type : B8
    Device ID : 4D8D
    b1 : 00
    b2 : 01
    b3 : 03
    Sequence Num. : 16

    rgbw packet received (4 bytes): (sent from home assistant)
    Request type : B8
    Device ID : 4D8D
    b1 : 04
    b2 : B9
    b3 : 0E
    Sequence Num. : 93

    rgbw packet received (4 bytes): (sent from milight emulator)
    Request type : B0   <—?
    Device ID : 4D8D
    b1 : 00
    b2 : 02
    b3 : 05
    Sequence Num. : 3C



  25. Hi,

    Wondered if anyone could help!

    Got a nodeMcU v2 and a NRF24L01+ with the external aerial.

    All flashed and connected to network. I have used Sniff Traffic and can see the Device ID. I have entered that as a device Id but doesn’t do anything.

    Also tried setting up a server and sending and I can see that too. Tried pairing lights with this server that I’ve set up and not working either.

    Firmware is 1.5.0. Been reading the comments and saw people moving the CE pin and having some luck with it . Tried it on GPIO 4, not working either. Checked wiring but cant see anything obvious (if I got this wrong would I see and Traffic?)

    Thanks in advance



    • Hi Wayne,

      I recently put this together, maybe it’ll help:

      You might have a bad nRF module. In my experience, it’s possible for modules to be bad in the way that they can receive, but not send packets. Worth swapping it out.

      For what it’s worth, the two I have with external antennae actually perform significantly worse than the ones I have with a PCB trace, but not sure if I just got bad ones.

  26. Hi Chris,

    This project is great! very impressive 🙂

    I’ve just hit the 4 group limit on my single (v4) hub and require more groups, so ordered the bits and am flashing the nodemcu as i write.

    I have seen other questions relating to this, but couldn’t find a clear answer so would appreciate any info:

    Can a fully loaded milight hubs bulbs and groups be easily ‘moved over’ to this hub? I’d rather use your code for my whole milight setup rather than have multiple hubs, and wondered if there’s a simple process beyond unpairing from the legit hub, creating a vhub in your software, and pairing the bulbs in the same  order.

    Thanks in advance,


  27. Hi,


    I have this set up now using mqtt but the light seems to oscillate between on and off even thought there are no more messages being published.

    I have mqtt
    I can see the message with mqtt spy
    When I publish {“status”:”on”} the light turns on but then off after a few seconds and then on again.
    I can see in mqtt spy that the message is not cycling or repeating.
    In your firmware I have repeat packets to zero or 1 (tried both)
    I have turned off the original controller so it is not a conflict.


    In short – turning the bulb on causes it to cycle on and off.

    Any idea why it might be doing this?







    • Ok,

      Seems there is a bug in your transmit code?

      When I do this, via mqtt, and I have sniffing turned on, I can see you send out a huge amount of messages.

      See here:

      That scrollbar just keeps going.
      In this instance I sent “off” but the “on” does the same.


    • Hi Bob,

      I know you’ve said that your MQTT spy is showing that things aren’t being repeated, but I can’t think of a reason something would go into an infinite loop aside from the MQTT update topic being the same as the MQTT command topic. Have you tried pointing your MQTT spy at a wildcard? It might not be showing up because the hex ID is getting coalesced into a decimal value.

      If you’re still having trouble, can you provide the output of http://milight-hub.local/settings and http://milight-hub.local/about ? (Might need to substitute milight-hub.local for the IP of your ESP if your client doesn’t support mDNS).


  28. Cool Project. Thanks for your work!

    I have problems to get it work… 🙁
    I erased the esp8266 and flashed it.

    I could change the WiFi Settings and can find the device in my router.
    Unfortunately I only found 2 times the UI.

    The serial communications gives me the following:

    I had two messages “Setup complete”. But after that it started again.
    How can I get a stable WiFi connection?


    • Hi Gunther,

      Does this happen after you try to do something, or is it just in a restart loop? Did you flash it with a pre-compiled image, or something you compiled yourself?

      If you have the nRF connected, try booting with it disconnected. I’ve seen the initialization routine for the nRF hang and cause watchdog timer resets.


    • Hi Chris,

      after a few nights I found the reason.

      My SSID has “blanks” and a “comma” like
      “Max Mustermann 2,4GHZ”
      I changed it to “Max” and it works.
      Is it possible in the future to have an SSID like mine?

      Unfortunately I cannot pair.
      I switch power of my milight on and press pair. nothing happens.
      What I have to do?


  29. Hello!

    I’m having a hard time making mqtt work with openhab2.

    On MQTT.fx i’m subscribed to :


    and publishing this code turns the light on and off correctly :



    When I go to my openhab2 home.items file I added this code :

    Dimmer Test_Light_1 “Test Light 1″ {mqtt=”>[broker:milight/0x6C8F/rgbw/1:command:ON:{“status”:”ON”}],>[broker:milight/0x6C8F/rgbw/1:command:OFF:{“status”:”OFF”}]”}

    and it doesn’t work.

    I think it’s because of the ” and the : when I tried to remove the ” and the :   milight/0x6C8F/rgbw/1 returns :


    but with the ” and : I get nothing on my subscribed topic

    Please help!

    PS Good work with this by the way!

    • Thanks Chris for the reply! the link worked like a charm!

      Just a follow up question why does the mqtt work very inconsistent, sometimes it works sometimes it doesn’t.

      Sometimes in a group of 3 bulbs in 1 zone 1 light doesn’t change colors unless clicked multiple times.

      The nodeMCU is located 1 feet away the bulbs so I don’t think it’s an issue with range.

      here are my settings :

      admin_username “”
      admin_password “”
      ce_pin 16
      csn_pin 15
      reset_pin 0
      radio_interface_type “nRF24”
      packet_repeats 10
      http_repeat_factor 5
      auto_restart_period 0
      mqtt_server “”
      mqtt_username “”
      mqtt_password “”
      mqtt_topic_pattern “milight/commands/:device_id/:device_type/:group_id”
      mqtt_update_topic_pattern “milight/updates/:device_id/:device_type/:group_id”
      mqtt_state_topic_pattern “milight/state/:device_id/:device_type/:group_id”
      discovery_port 8899
      listen_repeats 3
      state_flush_interval 0
      mqtt_state_rate_limit 500
      0 6851
      1 27787
      2 27791

      Should I change anything to make the mqtt work more consistently?

    • Hi there! This didn’t help too much. 1 sometimes 2 bulbs still doesn’t reply as fast as the milight hub.

      by the way i’m using mqtt, what does the milight hub use? it works flawlessly and a lot faster on the hub i wonder why.

      Great project still!

      PS. do you have skype? need to ask you something regarding work. Thank you!

    • Sorta sounds like you’ve got a flaky nRF or the connections aren’t stable. I’d switch to pin/header or soldered connections and try a different nRF.

      I’d prefer email. My address is listed on my Github profile:

  30. Hello. This is my first time messing around with the little ESP8266, and the first time with DIY electronics like this. I have played with arduino and stuff before, but have not in 3 years. Great with soldering, no problem hooking the two boards together. But I am having some issues. Using a NodeMCU v3 and I installed Atom, the platform package and clang onto my Mac running the latest OS. Connected the boards, downloaded the zip and built in in Atom. Uploaded it and went. Can connect through the web UI and connected to my wifi network. However, to send more than one command, I have to reset. It seems the board freezes after the first command. This is something I did. I did not do anything else. Am I supposed to install anything to the other wifi module, or select my board version or install firmware? I only built it and installed it. Thank you.

    • I believe the Node is crashing. I can issue a command from the WEB UI, then watching the serial monitor, it does a bunch of characters then I can see it rebooting.

    • If you’re positive everything’s hooked up correctly (and sounds like you are), it’s likely a hardware problem. I think there are a ton of knockoff NRF24L01s on the market, and they’re really hit or miss. Something like 10-20% of the units I’ve dealt with are entirely or nearly useless.

      I’d try:

      1. Compiling with debug flags (these are in platformio.ini) and checking Serial output.
      2. Making sure the pin labels on your ESP match expectations. Sometimes they’re mislabeled.
      3. Trying a different ESP / NRF
    • Don’t know what I did, but it stopped and now I have a reliable bridge. However, I can not control them through the normal milight app and another milight app I use for iOS, Home Remote. It seems they can not see the bridge. Any ideas? And, what if I want to change the network its connected to? Hitting the reset wifi config in the Web UI did nothing, neither did refreshing the board with new firmware. Granted, I am probably doing something wrong.

  31. This is a REALLY great piece of software. Tried an implementation of the protocol on a raspi some years ago. So had a transceiver lurking around here. 🙂
    Orderd a NodeMCU yesterday and just set it up, following your great tutorial. Works like a charm! Will try to spoof my bridges at home later and then configure my Light-Switching-App to use it. 🙂

    If you guys are interessed: You can check out this project here:

    Supports 433 MHz-Gateways, MiLight (up to v6), Actions, Timers, Groups, different User-Profiles and much more. 🙂


  32. Hi Chris,

    Looks like a great project that inspired me to get hold of some Nodemcuv3’s and NRF24’s.

    I was having similar problems to Phil above when attempting to transmit it looks like the system crashed when building with debug mode turned on.  I have two boards and can sniff on the second board – it picks up the remote but not from the transmitting nodemcu. I was using source built using PlatformIO on Windows.

    I just flashed the boards using the your 1.6.0-dev6 bin file.  I can now see packets transmitted when I have the second nodemcu setup to sniff.

    I have some LED Downlights dual white CCT that I am trying to get to work, that I have not been successful as yet.   The lights work with a dual white CCT milight remote and I also have a iBox1 that they work with.



    • Hi Justin,

      Thanks for providing all of that info upfront. That narrows it down quite a bit.

      There’s an open issue about binaries built on Windows crashing (link). I’ve not had the time to look into it yet.

      There’s also an issue about FUT035s (dual-white LED controller) not responding to CCT packets (link). It sounds like it’s because newer devices have stricter expectations about the protocol. This is another one I’ll look at soon, but haven’t had the time for yet. A couple of people have had luck unpairing the device with the remote, and then re-pairing with the ESP using the RGB+CCT protocol.


  33. Ok, so I will open a issue on GitHub. And I will try tomorrow to integrate it with Domoticz. I will keep you in touch about this. Thanks again for your answer 😉

  34. Hi and thanks for your work, it’s really amazing !

    I have planned to buy a NodeMCU tomorrow and I want to know some point :

    Can I use the android APP to see the emulated bridge ?
    The emulated bridge use the same protocol than the officila v6 ? So, theoretically, I can include it in my domoticz installation like the official one ? (it’s support the official ibox (like a bulb) bridge actually)

    • Hi Romain,

      This has worked in the past by setting up a UDP server on the default port (5987), but newer versions of the android app don’t seem discover the ESP. Probably because of some minor differences in the expected packet (the protocol is very sparsely documented). If this is an important feature to you, please open an issue on the Github project.

      Yes, the UDP protocol is the same. I believe there are other uses that integrate with Domoticz.

  35. Hello there! I wonder how hard it could be to port this to a Raspberry? I am asking because I already have an RPi with NRF24L01 sitting around as my MySensors gateway and would love to – if this would at all be possible – to sometimes switch a few MiLights (RGB-CCT type) (thus sharing the NRF module between the two running programs / services)

    My problem is that all other solutions I found so far, namely OpenMilight dont seem to support RGBCCT.

    On the other hand I immediately had success with the ESP8266 solution presented here!

    Thank you for the effort to develop this gem. If I cant make it work on the RPi, I will stay with the ESP – even though I’d love to spare the extra power consumption/hardware.

    • I will give it a go when I get back from work and let you know.

      And thanks again for this.


  36. I tried both the pre-compiled and compiling my own and deploying with PlatformIO.

    Same crash regardless of which type of bulb, I’m probably doing something very stupid.




    • How do you have the nRF connected to the ESP? I’d recommend double-checking the wiring is correct and making sure nothing is loose.

      If you’re still getting it, can you flash with v1.5.0 and paste the whole stacktrace like you did before?

    • Hi,

      Sorry been away for a few days. Ok so I double checked the pins the photo below shows how I have them set up…

      I downloaded and installed the 1.5 firmware but serial port debugging looks to be turned off. Just trying to build a 1.5 version but platformio is broken. Just trying to sort it.




    • Hi Chris,

      I managed to narrow down the crash to this line..

      currentRadio->write(packet, currentRadio->config().getPacketLength());

      in MiLightClient.cpp

      Unfortunately this is where my c knowledge fails me.

      Thanks for looking into it for me.

    • No luck with the latest dev build. I am deploying the right version? I have been using the “nodemcuv2” build this is my board…

      My Board

      But I get similar results deploying the “d1_mini” build with this board…


    • nodemcuv2 should be fine. The only real thing that matters with these is the size of the flash chip, and almost everything has 4 MB.

      This is what I get when I decode your stacktrace:

      Can you try 1.4.1?

      Given the trace, I’m thinking there’s a change in 1.5 that is probably related, but I think it would only cause problems if something is screwy with your ESP.

      Have you already tried erasing flash and starting fresh? I usually do that with

    • Hi Mike,

      I couldnt get the 1.4.1 to build in PlatformIO and when I installed the image downloaded from github it didnt seem to work. I’m going to assume that there is something wrong with my hardware and try again.

      Thanks for your help.


  37. Hi,

    I trying to control some Mi-Light RGBW lights (FUT018)

    I have tried using both a “WeMos D1 Mini V2 ESP8266” and a “NodeMcu Lua ESP8266 CH340”

    I can sniff packets from the remote fine…

    This is from the On command

    Running version “1.6.0-dev3-3-gbb28224 (nodemcuv2)” when I click the on button through the web page I get this through the serial port

    Any help gratefully received.


  38. Pingback: ESP8266 + nRF2401 MiLight Gateway Leiterplatten „Sandwich“ –

  39. I was searching for weeks to get remote control for the old (the very old) RGB bulbs and the new ones and finally i found your Gateway. Just perfect, thank you 😀

  40. I have what it seems a Mi-Light WiFi gateway with this firmware:  V1.0.04a-JCY-1.

    Don’t know if that is v4/v5 definitelty not v6. Bulbs & LEDS are paired and working. I tried setup your code on NodeMCUv2 (thanks for clarifying on your website. It seemd Ali seller send me v2 .. ordered v3.) Well in this case I followed the windows instructions to flash the NodeMCUv2 binary directly.

    Web Interface runs. However If I press ‘sniffing’.  Nothing appears. I double checked the cables to NRF and checked them again with your images. Nothing strange. Any chance I ‘sniff’ nothing because I probably have v4 devices and those are not supported?



  41. Dear Chris,

    Thanks for the great work. It was really useful.

    I managed to setup the nodemcu V3. When i try to control the lights using the UI, i see that the packets that my remote sends are different than the one from the UI.

    For Ex: When I switch on the third button of my RBGW remote i get the below packets:

    rgbw packet received (4 bytes):
    Request type : B0
    Device ID : C17A
    b1 : 06
    b2 : BB
    b3 : 07
    Sequence Num. : 1F

    But when i do the same with UI, i get the below.

    rgbw packet received (4 bytes):
    Request type : B0
    Device ID : C17A
    b1 : 00
    b2 : 03
    b3 : 07
    Sequence Num. : 06

    Am I missing something here? Your inputs would be very helpful.



    • Can you find the device you’re trying to control here?

      It’s possible this is just a device issue. The NRF might not be transmitting, or might be transmitting a very weak signal.

      There’s a REST endpoint to send raw RF packets. You could try using that to rule that out. Example:

      You might need to fiddle with the last byte as it’s the sequence number, and bulbs ignore commands having the same sequence number as the last command they handled.

      If bulbs aren’t responding to commands sent that way, you probably have a faulty NRF24L01. Also possible the wiring is mixed up or loose.

    • Glad it’s working for you.

      I’m not familiar with Blynk, so it’s hard for me to say. But there are a lot of integration paths with this project. It supports the original Milight UDP protocol, has a REST API, and an MQTT integration.

    • Hi Chris,

      Thank you for your fast reply. I will look into it with my limited knowledge, but i am sure i will figure it out!


  42. Quick one…

    Managed to get it all working well with 1.5 dev 4

    I am now wondering about MQTT update messages when sending a command to

    command_topic: “milight/0xAB11/rgbw/0”

    Which is the group for simultaneous control of the 4 light channels on 0xAB11

    In my case I sort of expected 5 mqtt update messages back for 0 1 2 3 and 4 not just on 0. This would ensure in my case that Home Assistant updates the state of the individual bulbs as well as the group of bulbs.


    But only get the update back on


    I tend to use the ‘0 group’ in scenes so the changes look smoother and manually alter individual bulbs through the home assistant web interface.

    Does this make sense ? Perhaps there is some way to make home assistant toggle all 4 bulbs with the 0 topic that i dunno about. But I kinda thought would make sense for the hub to send the 5 updates since its unique to milight setup.

    Also does the software support transition times on the bulbs?

    Cheers everyone for the help so far…


    • Yeah noticed the same thing for my setup and accomplished it by expanding the forward out in HomeAssistant:

  43. Firstly, thanks for this! I’ve bought all the goodies and got everything loaded and working.


    When I click Start Sniffing nothing happens. In the console I have an error “sniffing is not defined”. Full message is Uncaught Reference: Sniffing is not defined at HTMLButton.

    This is followed by Sniffing is not defined at WebSocket.Websocket.onmessage ((index:3))

    I have no preceding errors which suggest jquery did not load.


    Anything I have done wrong?

    • It should’ve happened automatically, but Travis CI is being a jerk. Don’t have the time to look at it right now, but will look when I get the chance.

    • Thanks! Downloaded and flashed it.

      I now click “Start Sniffing” and the button changes to “Stop sniffing” but nothing else. Should another window / info shown up?
      No errors in console.

    • Ok, so there must be something wrong with my radio setup as I see nothing.

      Is there some method in the REST to get radio status / availability to ensure it’s working?

      I’m using a D1 Mimi node.

    • No REST endpoints for radio status. Not sure if the NRF exposes anything like that. Could add if so.

      There is an endpoint to sniff packets (request just hangs until a packet is intercepted) if that’s helpful.

      What kind of remote are you expecting to see sniffed packets from?

    • I’m using remote from phone with a mi-light controller. Both work and the bulbs change accordingly but the sniffing shows up nothing.

      I’m not convinced it’s not my radio so still digging at that.

      I’ll try the method you mentioned and see if it returns anything.

    • ok, so tried 3 different radios (gotta love Amazon pack of ten 🙂
      I did an erase_flash on it and then reflashed with the dev 4 version.

      Clicking on Start Sniffing says “Stop sniffing” but nothing else changes.

      I can see the bridge and I can see the bulb changing but nothing seems to be picked up on the gui.


    • “It’s ALIVE!” he screamed.

      It looks like it was just a range thing. The bridge sitting near the Hue bridge, the Lightwaverf bridge and an AP.

      I guess the height of the bulb gave it an advantage over my and my breadboard on the floor near another AP 🙂

      Anyway – it works now and I can control it from the laptop too.

      Awesome software, thanks for the effort!

    • Will do.
      Need to get it all integrated into Domoticz now so may well have some comments from that.

      That’s my weekend sorted 🙂

  44. Hey Chris, been using this for a while now with the NRF. I am doing UDP servers with a server for each light. I have about 10 milights. Everything works perfect if I am doing one at a time, but if I trigger a scene in Home Assistant (ie: turn everything off) 1-2 lights don’t seem to be getting the message and then are the wrong state. I have to go in and manually toggle each light on/off again before it’s back. This happens like 70% of the time. All the lights are within about 5 meters of the hub and there are no walls in between any of them. Any advice for getting this more reliable?

    • Hi Brad,

      My guess is that the UDP packets are getting dropped.

      I’ve noticed that the ESP isn’t great at handling a flood of UDP traffic. I think fundamentally a buffer is filling up and packets are getting dropped. The firmware doesn’t run ontop of a RTOS, so it only context switches to system functions when it explicitly chooses to do so. Might be possible to insert some yields in more places, but I kind of doubt it.

      The easiest fix, I think, is to switch to an integration that uses TCP. I use the mqtt_json component for my own setup, and it works flawlessly. I also have fewer lights, but I would expect you’d at least not get dropped packets.

      There’s some documentation on the integration here:

      My HASS config looks like this:

      In the off chance that it’s not UDP, you can try increasing the number of repeated packets (there’s a setting in the UI). Increasing this probably makes the chance that UDP packets get dropped higher, though, because more time is being spent outside of system functions.

Leave a Reply

Your email address will not be published. Required fields are marked *


This site uses Akismet to reduce spam. Learn how your comment data is processed.