Building a LIFX packet

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[192.55.226.195]  35  Msg(LightSetColor   )
To[192.55.226.195]  36  Msg(LightSetColor   )
To[192.55.226.195]  37  Msg(LightSetColor   )
 1  37 0.33 D0:73:D5:03:26:73 officetest           LightState       test 032673
To[192.55.226.195]  38  Msg(LightSetPower   ) Level=65535
To[192.55.226.195]  39  Msg(LightSetPower   ) Level=65535
To[192.55.226.195]  40  Msg(LightSetPower   ) Level=65535
 1  40 0.02 D0:73:D5:03:26:73 officetest           LightStatePower  Level=65535
To[192.55.226.195]  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.

Nice!

Hi,

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.

Can you share the code you’re using? I would like to try that out as well.

In my own project, I use the node-lifx library, but I don’t know what it’s actually doing under the hood. It might be worth looking into; specifically this file which assembles a packet:

Using this folder of packets:

Thanks for the answer.

I didn’t write any code yet. I tried to understand how it works first. I used the application Packet Sender, where I entered the long hexedecimal expression in HEX field, the ip address of the bulb in Address field, 56700 in Port field, slected UDP and then Send. However, nothing happens.

I also tried to use node-lifx library but failed to make it work. In examples/interactive-cli.js, I added some parameters as follows:
client.init({
address: ‘10.42.0.1’, // this is the ip address of the wifi interface
broadcast: ‘10.42.0.255’, // got this by running ipconfig
lights: [‘10.42.0.68’] // this is the ip address of the lifx bulb
});

However, nothing happened, even with the discovery turned on or off. Is there any missing parameter/configuration?
Thanks again,

That’s strange. I just init without any parameters as it will auto-discover using my machine’s IP range etc. If your lights are on a different network, that’s when you’ll wanna put in that info.

When you say “nothing happened”, what do you mean? There should be a callback function that you pass into the discovery function such as lifxClient.init().on('light-new', () => {})

Here’s a project I wrote that does just that:

I was digging around for an example on how to build and send @daniel_hall 's packet using Ruby but couldn’t find one. Pasting this here in case anyone finds it useful:

#!/usr/bin/env ruby

lifx_message = "310000340000000000000000000000000000000000000000000000000000000066000000005555FFFFFFFFAC0D0004000"

# split string to 2 chars in an array and convert each char pair to hex values
udp_payload = lifx_message.scan(/../).map { |s| sprintf("0x%s", s).hex }

# pack all (*) hex values as 8-bit unsigned (C)
udp_payload = udp_payload.pack('C*')

UDP_HOST   = "10.0.1.255" # broadcast to subnet with 255, or the IP address of specific bulb
UDP_PORT   = 56700
UDP_FLAGS = 0

# build socket, send broadcast option and send the packet
socket = UDPSocket.new
socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_BROADCAST, true)
socket.send(udp_payload, UDP_FLAGS, UDP_HOST, UDP_PORT)
socket.close

puts "done!"

It’s a shame there is no more Ruby LAN Protocol support since the original lifx-gem is defunct. Using bindata (as the original gem did) - it should be pretty straightforward to build one…

If anyone would find it helpful, I have created Java libraries for working with Lifx smart lights. You can download the source code here: https://github.com/olsenn1/LifxCommander_v1.0

I see that there is set group and get group…but maybe I am misreading its intent. Can I use the group unique ID tags to set power state via broadcast. I cant imagine sending unicast to 75 bulbs are being efficient.

Would like to use broadcast with unique group addresses to control multiples lights (large scale.)

Hi, Thanks for the code.
Is it possible do this in Java?

Thanks
JR