One Guys Technical Trials and Woes

LimitlessLED WiFi Bridge 4.0 Conversion to Raspberry Pi

Recently I purchased a few “Smart” LEDs from a site called LimitlessLED due to positive feedback from a close friend. After all was said and done, I walked away with 3 RGB LED Bulbs, a remote control, and one of their cool WiFi Receiver Bridges. After waiting a few weeks everything showed up and was working fine out of the box, except the WiFi Bridge. Thus started my journey to figure out what in the hell was going on which ended with me converting the adapter to work from a Raspberry Pi.

So after receiving my stuff, I set off to setup the little WiFi receiver. When I first got it, I took it out and set it up with its companion android application which worked great, but once it was paired to my home network the problems started coming. The problem is I live in a somewhat high density area, so there are TON’s of wireless networks in my area, and for some reason this little receiver bridge loves to drop, ignore, or just plain not forward any packets sent to it over my network. I tried different areas, rooms, hell even WiFi channels, but no matter what I did it was impossible to get a consistent link to the unit.

So with that, I decided the hell with it, and tore the sucker apart. Inside of the thing, you won’t find very much:

The mainboard (Ignore the cables, we will get to that later)

The WiFi Bridge

Now normally these are soldered together, but I forgot to take beforehand pictures (sorry!). So, at this point, I started by researching both boards. I was unable to find anything on the mainboard, but I found quite a bit of documentation on the WiFi controller, which is a High-Flying HF-LPT100 unit. With that, I was able to get a pinout for the leads and was able to find UART on pins 5 and 6. So using my new Saleae Logic 8 I decided to hook up to those leads and see if anything was coming across the leads.

So this is where it gets interesting. During boot and normal operation nothing is broadcasted over UART, and it does not seem to accept any input, but as soon as a command is sent to the controller to control my lights, the packet data was displayed in my serial session. So we can conclude from this that the packet data sent to control the LED’s is sent over the UART directly to the mainboard where it is converted and transmitted vi RF to the bulbs!

The bridge passes all UDP packets on port 8899 to the UART TX port (9600 baud)

All UDP packets on port 48899 are used to interface with the HF-LPT100 (WiFi settings, etc)

The RF radio listens on UART, forwards commands to LEDs

Everything is powered by 3.3V

Now is where the fun starts. I soldered the WiFi receiver unit off of the mainboard, and hooked up the 3.3V, GND, and RX from the mainboard to a USB TTL device and opened a serial session on the interface. I then took the API Documentation from LimitlessLED, and mapped out the Hex value for “RGBW COLOR LED ALL OFF” to its ASCII character of A. I then turned the LEDs on in my room, sent A over my serial session… and the lights turned off! So from this I was able to confirm once again that the transmitter is directly using the UDP commands sent to the Wi-Fi receiver.

Now that everything was mapped, it was time to map it to the Raspberry Pi pinout. Here is the mapping I went with:

Pi to Transmitter
1 -> 2 (3.3V)
6 -> 1 (GND)
8 -> 6 (TX -> RX)

NOTE: If you do this you need to disable console from your Pi’s bootcmd, as you don’t want a console to be given over UART.

Once that was mapped, I tested again from the Raspberry PI to confirm things still work and as expected they did, but we still have some work to do. How do we go about getting native apps to work? Even better, how do we get it so the API documentation can still be used so all currently developed apps and API’s will run with this?

Well as the transmitter listens and runs off of raw UDP packet data, I coded up a little python listener to do the task! But wait, how about the auto discovery and setup in the iOS and Android apps? Don’t worry, that was taken care of as well! 🙂

First of all, thanks. My house is wired up with Milight and I had some Ardiuno set up that would kill the power to the bridge when it couldn’t be pinged, this “worked” but didn’t fix the issue.

I had my devices added to my bridge, so the following isn’t a huge issue for me, but I’m unable to get the admin.py to work. Under python 2.7 is doesn’t like the bytes command, so I ran it under python 3.2. I uncommented the prints and it seems to be sending the Pi’s IP and mac address out but it does;t show up in the Milight app, any ideas why?

Yeah, the scripts were designed for python 3+ so that is why it failed to run. As for the IP and mac address for the milight application, did you add your devices IP and MAC address to lines 10 and 11? If so, try wiping the application data for the Milight application on your device, and then try to re-scan for receivers. You may have to press it twice, but as long as you are on the same network it should work.

192.168.0.3 is the phone that’s running the milight app, 192.168.0.24,B827EB597AD8 is the IP and MAC of the Pi. I see that when the app tries to find the Pi it responds, but it only responds 5 times, is that correct? I removed the iOS and reinstalled it, what Milight app are you using? I can try that one as I have Android devices too. Thanks for your help.

Interesting… It should respond each time a request is made as there is no loop or timeout, so that might be a limitation of the Milight iOS application. Sadly I do not own any apple products, so I am unable to test. Everything I use is Android.

If you could, can you possibly get a packet capture of the Milight iOS app doing a handshake with the normal adapter? Then I can try to find what the variance might be and add it to the python script.

Just to follow up, I’m at work at the moment but can now sniff UDP packets from my iOS device. I’ll search for an unmodified device as well as a modified device and send you the logs too, should deb quite easy to spot the difference. Do you have an email address I could get to send them to you?

I did a similar project last year. Instead of using a Pi i used a XPort Ethernet-to-TTL chip. Once configured, worked like a charm. No more drops or broken re-joins. Plain ethernet now! :/)
I steered everything from openhab.org which is just perfect to use. After contacting futlight the actual manufactor of milight and all mutants, saying that their wifi sucks, they rejected the idea of coming up with a ethernet (heck, even PoE) device. So I started my own and interest is increasing (with PoE).

I would like to ask if you know how the RF module and the Wifi module are linked together on a software level. I’ve managed to update the firmware of my milight and now its not completely functional and a bit out of ideas how to proceed with the fix. I think I uploaded an official hi-flying firmware and that might have overwritten something what actually would be needed to communicate. (No app is identifying the wifi bridge).

David:
the wifi firmware is 100% stock. The one from the high-flying website has the same checksum as the one on the limitlessled sdk page..
So whatever is wrong it ain’t that. You should probably try re flashing over serial!

Great article, man! This is the first project that I see about reverse engineering the MiLight bridge. I have one request: could you please add a picture in which we can see which pin of the WiFi receiver is connected to which pin of the RPI? Thanks!

Thanks for sharing this! I just performed the mod, tonight! Such a simple mod, for such a huge stability gain! My V1 Bridge has been going strong for 2+ years with no dropouts. The V4 Bridge has never worked properly, so this was a very welcome find!

Brilliant stuff
I have a V3 bridge that has worked without a glitch for 6+ months now
Wanted to add more zones but after going through three V4 bridges , I was ready to give up till i found this
Cherry on the cake – Just hooked up the main board to an existing RpI that was running xbian

Have you tried to go a step further and directly send the 2.4GHz WiFi signal? I have found, that the transmitter chip is a PL1167 and could communicate through SPI.
I first tried with a logic analyzer but looks a bit weired for me. Basically this chip can send or receive and is really cheep, so I ordered some of them to see how far I get.

I was looking to have a dozen or so bulbs in the house and the requirement of one hub per 4 lights (if you want to control each lamp individually) was a bit of a limit. Looks like it will still be a limit, but thanks for the reply.

Just got some help with the logic and the correct spec of the PL1167 (I had an old spec with wrong pinout). So sniffing SPI communication was possible.
The protocol seems simple. It’s not encrypted and seems to simply contain a 16bit controller ID.

The data contains a frame counter and is send around 50 times on 3 channels to “ensure” it’s received. I did not found any answers from the bulbs, so really seems to be a one way communication and the color really seems to only be 8bit (was hoping for a 24bit field internally).

The idea is to simply “emulate” multiple bridges by making the controller ID changeable.

I’m still waiting to receive my orde (5 chips for ~$15) to test sending own signals, will come back and post results of the tests, as soon as I have more info.

Hi,
I first wanted to wait with the next response until I finished my tests. Unfortunately I’m currently stuck in work. So a short update.
I received the chips and soldered a first test one. It worked well. I was able to send signals from a PI through SPI to the chip and the bulbs accepted the signal. Additionally I confirmed that the bridge code is coded in the message. I’m not 100% sure, but I think it’s a 8bit bridge code. I successfully linked my test bulbs with two pseudo bridges.
Unfortunatelly I killed my first chip (not sure why/how) so I did not finished my tests.

I additionally ordered a pack of LT8900 chips, that should be compatible, but are much cheeper. I will send some more infos, as soon as I find some free time.

How can I fix this? I followed your instruction but when I want to connect trough the MiLight app this error shows up.
Traceback (most recent call last):
File "/home/pi/RFServer/listen.py", line 35, in
adminsock.sendto(bytes('+ok', "utf-8"),adminaddr) # Send OK for each packet we get
TypeError: str() takes at most 1 argument (2 given)

I found after this conversion my lag from the app -> my lights was gone as well as my reliability problems being solved. They need to just sell them as a wired device and save everybody the trouble of fixing it themselves, but at least it works 100% now!

Sorry for a stupid question …. How can I register a bulb to the wifi box, without a smartphone ? I would like to use direct API to handle the bulbs. I ‘m testing a java and a PHP api … but something is still missing. I think that I should have a link (registration whatever) between wifi box and bulb.
Any suggestion ?

Normally registration is just done by turning on the outlet switch for the bulbs, and holding on the Power On option on a remote for the LED group you want the bulbs to be in, so technically this can be done by sending on the Power On command for a group over the API when you apply power to the bulbs from the socket. If I remember correctly, there is a 5~ second window to pair.

Indeed, I was able to connect from api (based on Chris B advice) in the following way:
I did a loop, sending “on” command to a certain group (3 in my case) and then I have connected the bulb to the power supply, wait until 3 flashes.

No is all ok, I can switch on/off/change color, etc using java api.

One more thing.. I have noticed a network traffic between the wireless module and internet with the TCP frame bellow:

Hello,
Please i wanted to know if you know how to find in the web the official milight bridge firmware. because i updated the firmware with LPB-100 hi-flying download page but its a raw firmware so it doesnt support milight anymore 🙁

Did you update the admin.py and led.py script to bind to your new device’s IP and mac addresses? Normally the error you are seeing is a sign the service is already running, or is not configured correctly.

On my RPi model B (Raspbian Jessie) rfled-server is working, but it on my RPi 3 (also Jessie) it won’t

Here’s what I got so far:
– The serial port device for the RPi 3 is /dev/ttyS0 (instead of /dev/ttyAMA0)
– Indeed, if I configure led.py to use /dev/ttyS0, short GPIO 14 & 15 (pin 8 & 10 on the pinout) and `screen /dev/ttyS0`, I can observe the MiLight commands being sent.
– On the RPi3, the hardware UART of the Broadcom is used for Bluetooth. The GPIO 14/15 pins use a mini-uart port. The mini-uart clock is linked to the main CPU clock and is supposedly unreliable. (Source: http://www.briandorey.com/post/Raspberry-Pi-3-UART-Overlay-Workaround)
– So, my guess that timing is off or some other spec has changed, which is incompatible with the MiLight bridge. Unfortunately, I don’t have any hardware to inspect the actual output of the UART port.
– A workaround could be to disable Bluetooth en remap the hardware UART to the GPIO pins (see link above). However, I’d like to use bluetooth as well for another project.

Thanks for the awesome info! As for a work around, you can always try adding a USB UART adapter, and then wiring that directly to the MiLight board. This will allow you to have the hardware UART for Bluetooth, and a UART adapter is cheap at around $5 shipped.

Hello
I’ve a raspberry B+…the scripts are working fine (debugging by print and testing with an iOS app) but I have to pair again my lights…and I try to do it with the app and it just does not work : the light do not blink whtn I push the on button on one channel…

great stuff here. Thank You Very Much !
I like the former python script, and I can get a fine “go” solution here, now to.
Maybe it’s a little bit of topic, because I use a FritzBox (Router) with FTDI chip,
instead of the Raspi and the FritzBox with freetz has not that much memory.
Therefore I installed socat over freetz, and the ftdi driver, too.
Then I put the following stuff to my freetz -> rc.local.

I am an industrial designer that has been using the milights in some wall art projects. I can run the devices off the remote, but cannot get the wifi bridge to work. I came across your posting, but I have no experience with Rasberry Pi devices. Would it be too much trouble to ask for a dumbed down version of this guide (complete with photos, and a detailed shopping list).

I tried to follow each step of the topic and it works well using the default serial port /dev/ttyAMA0.
I’m using AMA0 serial port for another project so I tried to connect a USB TTL (like this one : https://cdn.instructables.com/F0L/DZH2/HFD1F0NF/F0LDZH2HFD1F0NF.MEDIUM.jpg).
I detected the USB TTL as /dev/ttyUSB1 when I plugged it to raspberry.
But I was not able to replace the default serial port /dev/ttyAMA0 by /dev/ttyUSB1 in your program … :/

I had this same problem. Did you set it up on one network interface then switched to another later?

I had this same issue when I switched from eth0 to my wireless interface. It worked after I switched back. If you do a clean install you can go WiFi with no issues, switching to eth0 causes the issue to come back.

The one without coulours has is a combined “warm white” / “cold white” LED. Do you also use them?

I tried to control them directly using an nRF24L01+ as described here:http://torsten-traenkner.de/wissen/smarthome/openmilight.php
But I did not succeed. My guess is that my bulbs use a different protocol (I read about differences of the protocols between different MiLight bulbs, but do not recall the reference right now). So I wonder if this very difference might also cause problems using your approach or if it is more universal due to the partial use of the bridge.

As my code only emulates the WiFi bridge and not the transmitter, as long as your LED bridge uses the same ports then this method should still work for that version of the LEDs, but I do now own one of those combined mode lights to verify this for sure. In theory it “should” work as my approach does not mess with, or change the packet structure of data sent to the LEDs.

Then I try to follow your input below, but nano brings up “blank” documents, and I believe I’m failing to install RFLED-Server correctly. Would you mind posting the exact steps on a Rapsberry Pi for a total linux noob? Greatly appreciate the insight and this blog post, very cool! 🙂
# Edit the MAC/IP in /opt/RFLED-Server/source/admin.py
nano /opt/RFLED-Server/source/admin.py

From the commands you shared, it looks like you did it right but now that Go is used, those install instructions are no longer valid. To install the Go version of the service, you will want to download the release .tar.gz which is on the Releases page on GitHub, which will provide a compiled version of the application. One done, follow the install info in the Readme of the repo. https://github.com/riptidewave93/RFLED-Server

I got one from a dutch MiLight webshop. But I’ve also seen them on alibaba.
It’s sold as ‘Wifi iBox’ under the Milight brand, but I haven’t seen it with the other brand names yet.
Works like a charm on my RGB+CCT downlights. I’m now trying to hook it up to an Arduino, trying to figure out what commands I have to send.

And this time the service shows in the MiLight iOS app as a bridge.
The only difference I see in the two service status´ is the CGroup: /system.slice/rfled-server.service
└─717 /usr/sbin/rfled-server
So it seems that the RPi doenst start the correct service on startup/reboot but when the user stops and starts the service it starts the correct service.
Im thinking this is a NOOB problem but Im going nuts because I cant solve it. So any help would be much appriciated 🙂

Maybe off-topic, but you guys seem to have a lot of knowledge of this crappy Mi-light wifi box 🙂

My mi-light bridge stopped working ( did not do anything with it. plugged it in right from the box and it worked for a year an d a half. Now both sys & link leds are off. Whem i plug it in a small tiny flash of both leds and then dead again. Can this be repaired ? I can solder..

Hello,
Sadly sounds like either the power circuitry on the main PCB is toast, or the actual wifi bridge unit is dead. Sadly the only way to check is to diagnose each part. For example, if you use jumpers to apply 3.3v to the wifi bridge manually does it boot then without issue?

Hello, i am a newbie on raspberry
but i think i got everything working only i dont see any milight box in the app on my phone
what do you meen with: Configure your settings in /etc/default/rfled-server as needed
where can i find these settings, i dont know my wifi box mc asdres nor ip adress.
Raspberry pi2 is running on ip 192.168.1.53
when i start; 4. Enable the init.d script systemctl enable rfled-server
its says:
executing /usr/sbin/update-rc.d rfled-server defaults
executing /usr/sbin/update-rc.d rfled-server enabled

And than:
5. Start the service service rfled-server start
it coms back with nothing ??

The first issue is that it is not starting up on the startup. I’ve done a fresh install 3 times now (fully new OS), and on the first setup inputting the commands….

sudo systemctl enable rfled-server

sudo service rfled-server start

…creates a milight server visible to my phone which I can connect to. However when I restart (and every time I restart after) the server does not automatically start up. Even more troublesome, the commands

sudo systemctl enable rfled-server

sudo service rfled-server start

don’t start the server again and my phone can’t connect.

I’ve solved this by manually inputting

sudo rfled-server – debug

This gets the server up and running and is visible to my phone, even better I can see that the app is talking to the server nicely. But… there’s still issues. I’ve burned through 2 bridges now and neither are forwarding the commands onto the bulbs. I have been unsuccessful in pairing a bulb to the bridge thus far. I strongly suspect that there’s something wrong with my hardware, but I cannot pinpoint what.

So I have a few questions. How can you view the output to the serial connections so I know the server is forwarding it’s commands properly, and what should I look for in the bridge? I’m reasonably certain there are no shorts, and I know I got the pins right, I matched it to the picture above (I’m on a pi 2b, and could take a picture of the bridge if it helps).

Any help at all would be appreciated. I’m banging my head against the wall metaphorically.

Okay, so sorry about the string of comments from me but I figured I’d update what I found out just from my own further troubleshooting. Still nothing sadly :-/

First, after browsing these comments I found someone who had the same issue as me in that the service is not auto starting and we both have the issue fixed by issuing the commands

sudo service rfled-server stop
sudo service rfled-server start

Not a permanent ideal solution, and this has happened on 3 consecutive fresh installs of raspbian at this stage for me (on a pi 2b+).

This does create a server which my phone connects to, and I’m confident the commands are being received because debugging is super responsive when I’ve run it, and the activity light is doing its thang.

I’ve taken a multi meter to 1, 2, 6 on the wifi bridge and one of the known grounds on the PI, I’m reading 3.3volts to each. I have no idea how to read any output from the data connection, or any wireless output from the remotes.

If anyone, and I mean anyone has any means of helping me out here I’d be forever in your debt.

So were you able to improve the speed commands are sent? I’d like to control the rate at which my lights dim but the only solution I’ve found has been to send numerous brightness commands and I don’t feel this is ideal. For starters, sometimes some commands get lost to the ether, and there appears to be a required delay of a noticeable amount of milliseconds (I think 20) between each command so I can not achieve the true smooth dimming that I want.

Just wanted to thank you for this excellent software and guide. After struggling with intermittent lights for almost 4 years I finally have a dependable system! Some notes for others who follow:

-The current version requires systemd so that’s Raspbian Jessie at the least. Wheezy won’t work – you must upgrade.
-the armv6 version is for original Pis. My Pi2 rev 1 model B took the armv7 binary. The 64-bit binary is for newer.
-Removing the old WiFi board is by far the most difficult step. Removing *all* the solder so it’s loose, then lifting it straight off the pins so it doesn’t bind, is virtually impossible with a conventional soldering iron and only two hands. I ended up cutting the pins flush and then ripping it off after I removed as much solder as I could. Don’t worry about damaging the pins too badly because they also extend out the underside so you can attach your wires there. Just make sure nothing’s shorted.
-Pin 1 is the inside pin.
-This works very well with the milight utility (http://iqjar.com/jar/home-automation-using-the-raspberry-pi-to-control-the-lights-in-your-home-over-wi-fi/) just put your Pi’s IP address in the milight.conf file. local address – 127.0.0.1 – doesn’t seem to work.

Here you can get a full bridge replacement with MQTT-Integration und state awareness. Just get an esp8266 and a NRF24L01 transceiver. This little project can emulate as many bridges as needed and provides a own REST API.