{"_id":"57fdb5c21646dc0e00104806","user":"557e2561eb75d80d00af3dab","project":"5581248904ae5b0d0026289a","__v":0,"category":{"_id":"57fdb520bcc07b0e00d1ef41","__v":0,"project":"5581248904ae5b0d0026289a","version":"57fdb17c4defec0e0064228b","sync":{"url":"","isSync":false},"reference":false,"createdAt":"2016-10-12T03:59:28.475Z","from_sync":false,"order":1,"slug":"guides","title":"Guides"},"parentDoc":null,"version":{"_id":"57fdb17c4defec0e0064228b","project":"5581248904ae5b0d0026289a","__v":2,"createdAt":"2016-10-12T03:43:56.009Z","releaseDate":"2016-10-12T03:43:56.009Z","categories":["57fdb17c4defec0e0064228c","57fdb17c4defec0e0064228d","57fdb17c4defec0e0064228e","57fdb520bcc07b0e00d1ef41"],"is_deprecated":false,"is_hidden":false,"is_beta":false,"is_stable":true,"codename":"","version_clean":"2.0.0","version":"2.0"},"updates":[],"next":{"pages":[],"description":""},"createdAt":"2016-10-12T04:02:10.418Z","link_external":false,"link_url":"","githubsync":"","sync_unique":"","hidden":false,"api":{"results":{"codes":[]},"settings":"","auth":"required","params":[],"url":""},"isReference":false,"order":1,"body":"This was [originally posted](https://community.lifx.com/t/building-a-lifx-packet/59) on the LIFX Developer Community, by request it has been added to the official protocol documentation.\n\nBefore reading this documentation there are a few concepts that you will need to be familiar with. Here are a few Wikipedia articles you may wish to review:\n\n - [Binary numeral system][1]\n - [Hexadecimal][2]\n - [Endianness][3]\n - [Bitwise operations][4]\n \n# Binary protocols\n\nBinary protocols usually exist as several layers applied one after the other, with each layer describing details of the next. When all combined together these make up what is called a frame or a packet. The LIFX protocol looks like this too. In the LIFX protocol there are two major sections, the headers and the payload. The headers describe the action that is being taken and the way in which it will work and the payload provides the data for that specific action. Sometimes the action requires no data, and in these cases the payload is not included.\n\nIn the LIFX protocol there are three headers that are included in every message.\n\n - The [frame header](doc:header-description#frame) frame header includes details about how to process the frame itself. This includes the protocol version and the size of the frame.\n - The [frame address](doc:header-description#frame-address) header includes details about the destination and the processing of the frame.\n - The [protocol header](doc:header-description#protocol-header) describes the type of the payload.\n\nThese headers are included in the order above, with the payload included at the end if required.\n\n# An example packet\n\nLets build a packet to change all of the lights on our network to green. We will be representing the packet in hexidecimal format, which means every character corresponds to 4 bits, we will group them in groups of two, representing a full byte. \n\nTo do this we first need to build the frame header. You can find the description of what is included in the frame header here. The documentation says we start with 16 bits which indicate the size of the message. Since we don't have the frame yet we cant possibly know its size. But we do know that the size is stored in two bytes. So lets write them as `?` for now. So our packet starts out as:\n\n**?? ??**\n\n## A Binary Field\n\nNext up is a byte split up into several fields, so we will have to manually assemble it ourselves. You will need to do this whenever you encounter fields that are partial bytes. So lets start with two zero bytes:\n\n    ???? ????  ???? ????\n\nThe documentation says that the first two bits here are the message origin indicator and must be zero.\n\n    00?? ????  ???? ????\n\nThe next bit represents the `tagged` field. We want this packet to be processed by all devices that receive it so we need to set it to one (1).\n\n    001? ????  ???? ????\n\nThe next bit represents the `addressable` field. This indicates that the next header will be a frame address header. Since all of our frames require this it will always be set to 1.\n\n    0011 ????  ???? ????\n\nThe final 12 bits are the `protocol` field. This must be set to 1024 which is `0100 0000 0000` in binary. Now our two bytes are complete.\n\n    0011 0100  0000 0000\n\nLets look at them in hexidecimal:\n\n    34 00\n\n## Back to the packet\n\nBefore we add these to the packet there is one final thing to note. The protocol is specified to be little endian. We have been working in big endian for ease of explanation, so we need to switch the two bytes around before we add them to the frame. Now the frame looks like this:\n\n?? ?? **00 34**\n\nThe next 32 bit (4 bytes) are the source, which are unique to the client and used to identify broadcasts that it cares about. Since we are a dumb client and don't care about the response, lets set this all to zero (0). If you are writing a client program you'll want to use a unique value here.\n\n?? ?? 00 34 **00 00 00 00**\n\nThat finishes off the frame header, and we move onto the frame address. The frame address starts with 64 bits (8 bytes) of the `target` field. Since we want this message to be processed by all device we will set it to zero.\n\n?? ?? 00 34 00 00 00 00 **00 00 00 00 00 00 00 00**\n\nThis is followed by a reserved section of 48 bits (6 bytes) that must be all zeros.\n\n?? ?? 00 34 00 00 00 00 00 00 00 00 00 00 00 00 **00 00 00 00 00 00**\n\nThe next byte is another field so follow the steps above to build the binary then hex representations. In this example we will be setting the `ack_required` and `res_required` fields to zero (0) because our bash script wont be listening for a response. This leads to a byte of zero being added.\n\n?? ?? 00 34 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 **00**\n\nSince we aren't processing or creating responses the sequence number is irrelevant so lets also set it to zero (0).\n\n?? ?? 00 34 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 **00**\n\nNext we include the protocol header. which begins with 64 reserved bits (8 bytes). Set these all to zero.\n\n?? ?? 00 34 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 **00 00 00 00 00 00 00 00**\n\nNow we have to indicate the message type. The different message types are listed in the Device Messages and Light Messages pages of the documentation. We are changing the color of our lights, so lets use [SetColor](doc:light-messages#section-setcolor-102), which is message type 0x66 (102 in decimal). Remember to represent this in little endian.\n\n?? ?? 00 34 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 **66 00**\n\nFinally another reserved field of 16 bits (2 bytes).\n\n?? ?? 00 34 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 66 00 **00 00**\n\nNow we have finished with the headers. All that's left now is the payload. Since our packet is getting quite long I'm going to build the payload separately for now. But imagine it is included at the end of the packet we have been building so far.\n\nThe payload starts with a reserved field of 8 bits (1 bytes).\n\n**00**\n\nNext up is the color described in HSBK. The HSBK format is described at the top of the [Light Messages](doc:light-messages#section-hsbk) page. It starts with a 16 bit (2 byte) integer representing the Hue. The hue of green is 120 degrees. Our scale however goes from 1-65535 instead of the traditional 1-360 hue scale. To represent this we use a simple formula to find the hue in our range. `120 / 360 * 65535` which yields a result of `21845`. This is 0x5555 in hex. In our case it isn't important, but remember to represent this number in little endian.\n\n00 **55 55**\n\nWe want maximum saturation which in a 16bit (2 byte) value is represented as 0xFFFF.\n\n00 55 55 **FF FF**\n\nWe also want maximum brightness.\n\n00 55 55 FF FF **FF FF**\n\nFinally we set the Kelvin to mid-range which is 3500 in decimal or 0x0DAC.\n\n00 55 55 FF FF FF FF **AC 0D**\n\nThe final part of our payload is the number of milliseconds over which to perform the transition. Lets set it to 1024ms because its an easy number and this is getting complicated. 1024 is 0x00000400 in hex.\n\n00 55 55 FF FF FF FF AC 0D **00 04 00 00**\n\nSo there we are, with 36 bytes of header information and 13 bytes of payload we have a frame that is 49 bytes big (or 0x31 in hex). So lets combine the two and fill in the size field.\n\n**31 00** 00 34 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 66 00 00 00 00 55 55 FF FF FF FF AC 0D 00 04 00 00\n\nAnd we have a packet! If you send this to any LIFX bulb it will turn green, and if you broadcast it to your entire network it will turn all LIFX bulbs green.\n\nOf course building packets by hand is time consuming and annoying, best to use a computer.\n\n\n  [1]: https://en.wikipedia.org/wiki/Binary_number\n  [2]: https://en.wikipedia.org/wiki/Hexadecimal\n  [3]: https://en.wikipedia.org/wiki/Endianness\n  [4]: https://en.wikipedia.org/wiki/Bitwise_operation\n  [8]: http://lan.developer.lifx.com/v2.0/docs/light-messages#section-setcolor-102\n  [9]: http://lan.developer.lifx.com/v2.0/docs/light-messages#section-hsbk","excerpt":"","slug":"building-a-lifx-packet","type":"basic","title":"Building a LIFX Packet"}

Building a LIFX Packet


This was [originally posted](https://community.lifx.com/t/building-a-lifx-packet/59) on the LIFX Developer Community, by request it has been added to the official protocol documentation. Before reading this documentation there are a few concepts that you will need to be familiar with. Here are a few Wikipedia articles you may wish to review: - [Binary numeral system][1] - [Hexadecimal][2] - [Endianness][3] - [Bitwise operations][4] # Binary protocols Binary protocols usually exist as several layers applied one after the other, with each layer describing details of the next. When all combined together these make up what is called a frame or a packet. The LIFX protocol looks like this too. In the LIFX protocol there are two major sections, the headers and the payload. The headers describe the action that is being taken and the way in which it will work and the payload provides the data for that specific action. Sometimes the action requires no data, and in these cases the payload is not included. In the LIFX protocol there are three headers that are included in every message. - The [frame header](doc:header-description#frame) frame header includes details about how to process the frame itself. This includes the protocol version and the size of the frame. - The [frame address](doc:header-description#frame-address) header includes details about the destination and the processing of the frame. - The [protocol header](doc:header-description#protocol-header) describes the type of the payload. These headers are included in the order above, with the payload included at the end if required. # An example packet Lets build a packet to change all of the lights on our network to green. We will be representing the packet in hexidecimal format, which means every character corresponds to 4 bits, we will group them in groups of two, representing a full byte. To do this we first need to build the frame header. You can find the description of what is included in the frame header here. The documentation says we start with 16 bits which indicate the size of the message. Since we don't have the frame yet we cant possibly know its size. But we do know that the size is stored in two bytes. So lets write them as `?` for now. So our packet starts out as: **?? ??** ## A Binary Field Next up is a byte split up into several fields, so we will have to manually assemble it ourselves. You will need to do this whenever you encounter fields that are partial bytes. So lets start with two zero bytes: ???? ???? ???? ???? The documentation says that the first two bits here are the message origin indicator and must be zero. 00?? ???? ???? ???? The next bit represents the `tagged` field. We want this packet to be processed by all devices that receive it so we need to set it to one (1). 001? ???? ???? ???? The next bit represents the `addressable` field. This indicates that the next header will be a frame address header. Since all of our frames require this it will always be set to 1. 0011 ???? ???? ???? The final 12 bits are the `protocol` field. This must be set to 1024 which is `0100 0000 0000` in binary. Now our two bytes are complete. 0011 0100 0000 0000 Lets look at them in hexidecimal: 34 00 ## Back to the packet Before we add these to the packet there is one final thing to note. The protocol is specified to be little endian. We have been working in big endian for ease of explanation, so we need to switch the two bytes around before we add them to the frame. Now the frame looks like this: ?? ?? **00 34** The next 32 bit (4 bytes) are the source, which are unique to the client and used to identify broadcasts that it cares about. Since we are a dumb client and don't care about the response, lets set this all to zero (0). If you are writing a client program you'll want to use a unique value here. ?? ?? 00 34 **00 00 00 00** That finishes off the frame header, and we move onto the frame address. The frame address starts with 64 bits (8 bytes) of the `target` field. Since we want this message to be processed by all device we will set it to zero. ?? ?? 00 34 00 00 00 00 **00 00 00 00 00 00 00 00** This is followed by a reserved section of 48 bits (6 bytes) that must be all zeros. ?? ?? 00 34 00 00 00 00 00 00 00 00 00 00 00 00 **00 00 00 00 00 00** The next byte is another field so follow the steps above to build the binary then hex representations. In this example we will be setting the `ack_required` and `res_required` fields to zero (0) because our bash script wont be listening for a response. This leads to a byte of zero being added. ?? ?? 00 34 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 **00** Since we aren't processing or creating responses the sequence number is irrelevant so lets also set it to zero (0). ?? ?? 00 34 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 **00** Next we include the protocol header. which begins with 64 reserved bits (8 bytes). Set these all to zero. ?? ?? 00 34 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 **00 00 00 00 00 00 00 00** Now we have to indicate the message type. The different message types are listed in the Device Messages and Light Messages pages of the documentation. We are changing the color of our lights, so lets use [SetColor](doc:light-messages#section-setcolor-102), which is message type 0x66 (102 in decimal). Remember to represent this in little endian. ?? ?? 00 34 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 **66 00** Finally another reserved field of 16 bits (2 bytes). ?? ?? 00 34 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 66 00 **00 00** Now we have finished with the headers. All that's left now is the payload. Since our packet is getting quite long I'm going to build the payload separately for now. But imagine it is included at the end of the packet we have been building so far. The payload starts with a reserved field of 8 bits (1 bytes). **00** Next up is the color described in HSBK. The HSBK format is described at the top of the [Light Messages](doc:light-messages#section-hsbk) page. It starts with a 16 bit (2 byte) integer representing the Hue. The hue of green is 120 degrees. Our scale however goes from 1-65535 instead of the traditional 1-360 hue scale. To represent this we use a simple formula to find the hue in our range. `120 / 360 * 65535` which yields a result of `21845`. This is 0x5555 in hex. In our case it isn't important, but remember to represent this number in little endian. 00 **55 55** We want maximum saturation which in a 16bit (2 byte) value is represented as 0xFFFF. 00 55 55 **FF FF** We also want maximum brightness. 00 55 55 FF FF **FF FF** Finally we set the Kelvin to mid-range which is 3500 in decimal or 0x0DAC. 00 55 55 FF FF FF FF **AC 0D** The final part of our payload is the number of milliseconds over which to perform the transition. Lets set it to 1024ms because its an easy number and this is getting complicated. 1024 is 0x00000400 in hex. 00 55 55 FF FF FF FF AC 0D **00 04 00 00** So there we are, with 36 bytes of header information and 13 bytes of payload we have a frame that is 49 bytes big (or 0x31 in hex). So lets combine the two and fill in the size field. **31 00** 00 34 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 66 00 00 00 00 55 55 FF FF FF FF AC 0D 00 04 00 00 And we have a packet! If you send this to any LIFX bulb it will turn green, and if you broadcast it to your entire network it will turn all LIFX bulbs green. Of course building packets by hand is time consuming and annoying, best to use a computer. [1]: https://en.wikipedia.org/wiki/Binary_number [2]: https://en.wikipedia.org/wiki/Hexadecimal [3]: https://en.wikipedia.org/wiki/Endianness [4]: https://en.wikipedia.org/wiki/Bitwise_operation [8]: http://lan.developer.lifx.com/v2.0/docs/light-messages#section-setcolor-102 [9]: http://lan.developer.lifx.com/v2.0/docs/light-messages#section-hsbk