Building a LIFX packet

In trying to implement the packet format in C# in notice that the frame description says that the origin and flag bits go before the protocol number but that’s only true if you view it as a 16 bit field that gets byte flipped for little endian but as a bit layout it’s backwards.

To assure that I understand things right it would be helpful to have an example of a “getservices” packet with the fields marked, I presume that

28 00 00 34 7B 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 64 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00

is wrong but need an example to compare it against.

decodes as


Which looks alright to me.

I agree the ordering does seem a little weird because you build is as a bit field, and then perform the endian swap. When you read the C structure at the bottom of the Header Description page it is a little bit clearer (if you know C).

Apparently C# is allocating an extra 4 bytes at the end so I programmed around that for now so I can find the payload. But otherwise is working fine now. Yes, I know C but you should fix the diagram to avoid the confusion.

SOLVED – added pack=1 to StructLayout

Looking at the Payload for StateService I see two response – one for service 1 (UDP) and the other 5 for ???

I’ll make a note to update the diagram and text to better match the layout of the packet in bits.

All values other than 1 are undocumented and thus can be ignored. Some have uses for LIFX only, and others are reserved for future use.

I get SetColor and SetPower to work but in testing if I do a GetService all bulbs respond but if I do a Get only a subset respond. Is there a reason for that?

Can I see the packet that you are sending for the ‘Get’ where only a subset respond?

OK, tracked down a problem. I was doing the queries in parallel threads but apparently that confuses the bulbs. This could a serious scaling problem when there are multiple clients controlling the devices. I can interlock on a single system but not across systems. I also turned on that tagged flag to be safe.

One strange result - I just got
D0:73:D5:12:6B:4E kwall3 StateInfo Since 2015-12-16 22:12:40 Down()
but that bulb is reporting itself offline via the http interface
12-17 00:28:31.116 17 [LifxUpdater] 12/16 23:49:07 kwall3 offline kwall3 126b4e

BTW, the received bytes count is very high – are the bulbs eavesdropping on all the traffic on my network?

Even then some devices don’t respond though most do. Since your system can only handle images I"m uploading the results. Notice the number of responses is 20 or 21 but getservice has only 38 but should have 42.
The columns show the count (#) and the number of seconds since the query was sent out. I wait 1 second since the response all come with less the .5 or don’t come at all.

Tried again and this time got up to 23 devices (Apparently your uploads overwrite) and 42 responses to getservice

Markdown can also handle preformatted text. You just need to indent the text by four spaces. You can either do that manually, or just highlight the text and hit the </> button in the toolbar. For example:

Label            Pwr Color             Temp        Uptime DevID  FW  HW    Group
---------------- --- ----------------- ------ ----------- ------ --- ----- -----
Traditional floo On  120   0 100 9000K 71.3°C 40d4h19m32s 029e03 2.1 O1000 Bedro

Will try </>. I notice I’m getting lots of lost packets. But I"m also confused – is the response to LightSetPower the resulting value or the previous level. It should be the current so I can do clsoed loop signaling. In this case the 41 in the last message is the sequence number (or before that, 40 etc)

1  34 0.02 D0:73:D5:03:26:73 officetest           LightStatePower  Level=65535
To[]  35  Msg(LightSetColor   )
To[]  36  Msg(LightSetColor   )
To[]  37  Msg(LightSetColor   )
 1  37 0.33 D0:73:D5:03:26:73 officetest           LightState       test 032673
To[]  38  Msg(LightSetPower   ) Level=65535
To[]  39  Msg(LightSetPower   ) Level=65535
To[]  40  Msg(LightSetPower   ) Level=65535
 1  40 0.02 D0:73:D5:03:26:73 officetest           LightStatePower  Level=65535
To[]  41  Msg(LightSetPower   ) Level=0
 1  41 0.02 D0:73:D5:03:26:73 officetest           LightStatePower  Level=65535

As one last test I set all my kitchen bulbs to green creating separate threads for speed and it worked nicely. Even seemed to reach bulbs deemed “offline”. But now they keep turning green even after I’ve used the app (Windows) to set them to white! What is making them go green again even after I’ve exited the program and visual studio? And how do I stop it! , OK, I think it finally stopped and the one bulb remaining claiming to be Green is a white one so that’s moot.

I presume the bulbs themselves have a buffering problem in keeping a queue long after I’ve assumed the message has been lost and without signaling the change i can’t know what is really happening short of polling often. Or maybe the app is … might as well stop guessing.

Yes, that seems to be a common problem.

When res_required is set, the response is the previous level, which I don’t think is very useful. I always set ack_required but never set res_required on my messages.

OK, that clarifies the out of phase responses. But since we’re using UDP I do need some acknowledgement to know the message wasn’t lost.

OK, one last thing – there is a huge amount of broadcast chatter on port 56700. Why so much – when there is no activity why flood the network?

It’s not just my app. Using the Lifx app I turn off a light but it doesn’t go off though the app shows it off. A few seconds later the app is again showing the bulb on. So the bulb is communicating and is able to get a message but just doesn’t do what is told. I don’t think I can do much more second guessing but you should consider disclosing your source code and algorithms so that I can make sense of what I’m observing.

Just looking out for the next guy

I think that having this information available where it’s easily found via the official protocol documentation would be helpful. Although there are some diagrams showing where the bits go, all bets are off with that once dealing with little-endian ordering.

FYI - ‘origin’ can be a 0 or a 1 from what I can see happening on the wire. The bulbs are sending 1’s. (i.e. bytes 3 and 4 are 00 54). This threw me for a loop since when encountering it I had not yet proven to myself that my assumption about the bit packing strategy used was correct. Turns out I was correct all along but not before some hair pulling occurred. The official documentation says that origin must be 0 so my first inclination was that I was doing something wrong.

1 Like

Thanks for the feedback @TomBruser. I just wanted to let you know that it has been received loud and clear, this post in now included in the official documentation.



I want to write a JavaScript program to control a Lifx bulb over LAN and I need to identify first how things work.

For this, I am sending the packet you described using Packet Sender app. I proceeded this way:

  • First, I created a LAN (Wifi hotspot)
  • I downloaded the Lifx app, configured the bulb and it works perfectly.
  • Using arp command, I found out the ip address of the bulb
  • Using Packet sender, I sent over UDP the packet you built to the ip-address of the bulb, pot 57600

However, nothing happens!
Can you please help me figure out what is wrong?

Thanks in advance.