{"__v":0,"_id":"57fdb17c4defec0e0064228f","category":{"__v":0,"_id":"57fdb17c4defec0e0064228e","project":"5581248904ae5b0d0026289a","version":"57fdb17c4defec0e0064228b","sync":{"url":"","isSync":false},"reference":false,"createdAt":"2015-06-18T03:15:52.144Z","from_sync":false,"order":3,"slug":"message-types","title":"Protocol Messages"},"parentDoc":null,"project":"5581248904ae5b0d0026289a","user":"557e2561eb75d80d00af3dab","version":{"__v":2,"_id":"57fdb17c4defec0e0064228b","project":"5581248904ae5b0d0026289a","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":["55996f6ce1a84019001ef283","55b828a8aea7c8190058bb99","564434dc5439df170071d4b8"],"next":{"pages":[],"description":""},"createdAt":"2015-06-18T03:18:35.906Z","link_external":false,"link_url":"","githubsync":"","sync_unique":"","hidden":false,"api":{"results":{"codes":[]},"settings":"","auth":"required","params":[],"url":""},"isReference":false,"order":0,"body":"Each LIFX Protocol message has the following format:\n\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/rr6TDgvSly0T2Gqu9bHL_Screenshot%20from%202015-06-18%2013-30-22.png\",\n        \"Screenshot from 2015-06-18 13-30-22.png\",\n        \"466\",\n        \"44\",\n        \"#dddddd\",\n        \"\"\n      ]\n    }\n  ]\n}\n[/block]\nThe header is composed of the Frame, Frame Address and Protocol header. The Payload is covered separately in the documentation for the various message types.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Frame\"\n}\n[/block]\nThe Frame section contains information about the following:\n* Size of the entire message\n* LIFX Protocol number: must be 1024 (decimal)\n* Use of the Frame Address _target_ field\n* Source identifier\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/PSMBmGcxS8mEf2uLDMM2_frame.png\",\n        \"frame.png\",\n        \"475\",\n        \"75\",\n        \"#040404\",\n        \"\"\n      ]\n    }\n  ]\n}\n[/block]\n\n[block:parameters]\n{\n  \"data\": {\n    \"h-0\": \"Field\",\n    \"h-1\": \"Bits\",\n    \"h-2\": \"Type\",\n    \"h-3\": \"Desciption\",\n    \"0-0\": \"size\",\n    \"0-1\": \"16\",\n    \"0-2\": \"`uint16_t`\",\n    \"0-3\": \"Size of entire message in bytes including this field\",\n    \"1-0\": \"origin\",\n    \"1-1\": \"2\",\n    \"1-2\": \"`uint8_t`\",\n    \"1-3\": \"Message origin indicator: must be zero (0)\",\n    \"2-0\": \"tagged\",\n    \"2-1\": \"1\",\n    \"2-2\": \"`bool`\",\n    \"2-3\": \"Determines usage of the Frame Address _target_ field\",\n    \"3-0\": \"addressable\",\n    \"3-1\": \"1\",\n    \"3-2\": \"`bool`\",\n    \"3-3\": \"Message includes a target address: must be one (1)\",\n    \"4-0\": \"protocol\",\n    \"4-1\": \"12\",\n    \"4-2\": \"`uint16_t`\",\n    \"4-3\": \"Protocol number: must be 1024 (decimal)\",\n    \"5-0\": \"source\",\n    \"5-1\": \"32\",\n    \"5-2\": \"`uint32_t`\",\n    \"5-3\": \"Source identifier: unique value set by the client, used by responses\"\n  },\n  \"cols\": 4,\n  \"rows\": 6\n}\n[/block]\nThe _tagged_ field is a boolean flag that indicates whether the Frame Address _target_ field is being used to address an individual device or all devices. For discovery using [Device::GetService](doc:device-messages#section-getservice-2) the _tagged_ field should be set to one (1) and the _target_ should be all zeroes. In all other messages the _tagged_ field should be set to zero (0) and the _target_ field should contain the device MAC address. The device will then respond with a [Device::StateService](doc:device-messages#section-stateservice-3) message, which will include its own MAC address in the target field. In all subsequent messages that the client sends to the device, the target field should be set to the device MAC address, and the tagged field should be set to zero (0).\n\nThe _source_ identifier allows each client to provide an unique value, which will be included by the LIFX device in any message that is sent in response to a message sent by the client. If the _source_ identifier is a non-zero value, then the LIFX device will send a unicast message to the IP address and port of the client that sent the originating message. If the _source_ identifier is a zero value, then the LIFX device may send a broadcast message that can be received by all clients on the same sub-net. See _ack\\_required_ and _res\\_required_ fields in the Frame Address.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Frame Address\"\n}\n[/block]\nThe Frame Address section contains the following routing information:\n\n* Target device address\n* Acknowledgement message is required flag\n* State response message is required flag\n* Message sequence number\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/xViGWJYtTVGonbYFKxMr_g12.png\",\n        \"g12.png\",\n        \"577\",\n        \"103\",\n        \"#040404\",\n        \"\"\n      ]\n    }\n  ]\n}\n[/block]\n\n[block:parameters]\n{\n  \"data\": {\n    \"h-0\": \"Field\",\n    \"h-1\": \"Bits\",\n    \"h-2\": \"Type\",\n    \"h-3\": \"Description\",\n    \"0-0\": \"target\",\n    \"1-0\": \"reserved\",\n    \"2-0\": \"reserved\",\n    \"3-0\": \"ack_required\",\n    \"4-0\": \"res_required\",\n    \"5-0\": \"sequence\",\n    \"0-1\": \"64\",\n    \"1-1\": \"48\",\n    \"2-1\": \"6\",\n    \"3-1\": \"1\",\n    \"4-1\": \"1\",\n    \"5-1\": \"8\",\n    \"0-2\": \"`uint64_t`\",\n    \"1-2\": \"`uint8_t[6]`\",\n    \"2-3\": \"Reserved\",\n    \"6-2\": \"\",\n    \"4-2\": \"`bool`\",\n    \"5-2\": \"`uint8_t`\",\n    \"3-2\": \"`bool`\",\n    \"0-3\": \"6 byte device address (MAC address) or zero (0) means all devices\",\n    \"1-3\": \"Must all be zero (0)\",\n    \"3-3\": \"Acknowledgement message required\",\n    \"4-3\": \"Response message required\",\n    \"5-3\": \"Wrap around message sequence number\"\n  },\n  \"cols\": 4,\n  \"rows\": 6\n}\n[/block]\nThe _target_ device address is 8 bytes long, when using the 6 byte MAC address then left-justify the value and zero-fill the last two bytes. A _target_ device address of all zeroes effectively addresses all devices on the local network. The Frame _tagged_ field must be set accordingly.\n\nThere are two flags that cause a LIFX device to send a message in response. In these cases, the _source_ identifier in the response message will be set to the same value as that in the requesting message sent by the client.\n\n* _ack\\_required_ set to one (1) will cause the device to send an [Device::Acknowledgement](doc:device-messages#section-acknowledgement-45) message\n* _res\\_required_ set to one (1) within a Set message, e.g [Light::SetPower](doc:light-messages#section-setpower-117) will cause the device to send the corresponding State message, e.g [Light::StatePower](doc:light-messages#section-statepower-118)\n\nThe client can use acknowledgments to determine that the LIFX device has received a message.  However, when using acknowledgments to ensure reliability in an over-burdened lossy network ... causing additional network packets may make the problem worse.\n\nClient that don't need to track the updated state of a LIFX device can choose not to request a response, which will reduce the network burden and may provide some performance advantage.  In some cases, a device may choose to send a state update response independent of whether _res\\_required_ is set.\n\nThe _sequence_ number allows the client to provide a unique value, which will be included by the LIFX device in any message that is sent in response to a message sent by the client. This allows the client to distinguish between different messages sent with the same _source_ identifier in the Frame. See _ack\\_required_ and _res\\_required_ fields in the Frame Address.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Protocol Header\"\n}\n[/block]\nThe Protocol header contains the following information about the message:\n* Message type which determines what action to take (based on the Payload)\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/MzpSjhmSuaMED6viWVUc_protocol.png\",\n        \"protocol.png\",\n        \"577\",\n        \"68\",\n        \"#040404\",\n        \"\"\n      ]\n    }\n  ]\n}\n[/block]\n\n[block:parameters]\n{\n  \"data\": {\n    \"h-0\": \"Field\",\n    \"h-1\": \"Bits\",\n    \"h-2\": \"Type\",\n    \"h-3\": \"Description\",\n    \"0-0\": \"reserved\",\n    \"0-1\": \"64\",\n    \"1-1\": \"16\",\n    \"2-1\": \"16\",\n    \"1-0\": \"type\",\n    \"2-0\": \"reserved\",\n    \"0-2\": \"`uint64_t`\",\n    \"1-2\": \"`uint16_t`\",\n    \"0-3\": \"Reserved\",\n    \"2-3\": \"Reserved\",\n    \"1-3\": \"Message type determines the payload being used\"\n  },\n  \"cols\": 4,\n  \"rows\": 3\n}\n[/block]\nReserved fields must be set to zero by the client.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Example\"\n}\n[/block]\n\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"#pragma pack(push, 1)\\ntypedef struct {\\n  /* frame */\\n  uint16_t size;\\n  uint16_t protocol:12;\\n  uint8_t  addressable:1;\\n  uint8_t  tagged:1;\\n  uint8_t  origin:2;\\n  uint32_t source;\\n  /* frame address */\\n  uint8_t  target[8];\\n  uint8_t  reserved[6];\\n  uint8_t  res_required:1;\\n  uint8_t  ack_required:1;\\n  uint8_t  :6;\\n  uint8_t  sequence;\\n  /* protocol header */\\n  uint64_t :64;\\n  uint16_t type;\\n  uint16_t :16;\\n  /* variable length payload follows */\\n} lx_protocol_header_t;\\n#pragma pack(pop)\",\n      \"language\": \"c\"\n    }\n  ]\n}\n[/block]\nNumeric data-type byte-order is [little-endian](http://en.wikipedia.org/wiki/Endianness#Little-endian), which means that dumping serialized data structures or viewing network packet sniffing may show the content of numeric fields in reversed byte-order.","excerpt":"","slug":"header-description","type":"basic","title":"Header Description"}

Header Description


Each LIFX Protocol message has the following format: [block:image] { "images": [ { "image": [ "https://files.readme.io/rr6TDgvSly0T2Gqu9bHL_Screenshot%20from%202015-06-18%2013-30-22.png", "Screenshot from 2015-06-18 13-30-22.png", "466", "44", "#dddddd", "" ] } ] } [/block] The header is composed of the Frame, Frame Address and Protocol header. The Payload is covered separately in the documentation for the various message types. [block:api-header] { "type": "basic", "title": "Frame" } [/block] The Frame section contains information about the following: * Size of the entire message * LIFX Protocol number: must be 1024 (decimal) * Use of the Frame Address _target_ field * Source identifier [block:image] { "images": [ { "image": [ "https://files.readme.io/PSMBmGcxS8mEf2uLDMM2_frame.png", "frame.png", "475", "75", "#040404", "" ] } ] } [/block] [block:parameters] { "data": { "h-0": "Field", "h-1": "Bits", "h-2": "Type", "h-3": "Desciption", "0-0": "size", "0-1": "16", "0-2": "`uint16_t`", "0-3": "Size of entire message in bytes including this field", "1-0": "origin", "1-1": "2", "1-2": "`uint8_t`", "1-3": "Message origin indicator: must be zero (0)", "2-0": "tagged", "2-1": "1", "2-2": "`bool`", "2-3": "Determines usage of the Frame Address _target_ field", "3-0": "addressable", "3-1": "1", "3-2": "`bool`", "3-3": "Message includes a target address: must be one (1)", "4-0": "protocol", "4-1": "12", "4-2": "`uint16_t`", "4-3": "Protocol number: must be 1024 (decimal)", "5-0": "source", "5-1": "32", "5-2": "`uint32_t`", "5-3": "Source identifier: unique value set by the client, used by responses" }, "cols": 4, "rows": 6 } [/block] The _tagged_ field is a boolean flag that indicates whether the Frame Address _target_ field is being used to address an individual device or all devices. For discovery using [Device::GetService](doc:device-messages#section-getservice-2) the _tagged_ field should be set to one (1) and the _target_ should be all zeroes. In all other messages the _tagged_ field should be set to zero (0) and the _target_ field should contain the device MAC address. The device will then respond with a [Device::StateService](doc:device-messages#section-stateservice-3) message, which will include its own MAC address in the target field. In all subsequent messages that the client sends to the device, the target field should be set to the device MAC address, and the tagged field should be set to zero (0). The _source_ identifier allows each client to provide an unique value, which will be included by the LIFX device in any message that is sent in response to a message sent by the client. If the _source_ identifier is a non-zero value, then the LIFX device will send a unicast message to the IP address and port of the client that sent the originating message. If the _source_ identifier is a zero value, then the LIFX device may send a broadcast message that can be received by all clients on the same sub-net. See _ack\_required_ and _res\_required_ fields in the Frame Address. [block:api-header] { "type": "basic", "title": "Frame Address" } [/block] The Frame Address section contains the following routing information: * Target device address * Acknowledgement message is required flag * State response message is required flag * Message sequence number [block:image] { "images": [ { "image": [ "https://files.readme.io/xViGWJYtTVGonbYFKxMr_g12.png", "g12.png", "577", "103", "#040404", "" ] } ] } [/block] [block:parameters] { "data": { "h-0": "Field", "h-1": "Bits", "h-2": "Type", "h-3": "Description", "0-0": "target", "1-0": "reserved", "2-0": "reserved", "3-0": "ack_required", "4-0": "res_required", "5-0": "sequence", "0-1": "64", "1-1": "48", "2-1": "6", "3-1": "1", "4-1": "1", "5-1": "8", "0-2": "`uint64_t`", "1-2": "`uint8_t[6]`", "2-3": "Reserved", "6-2": "", "4-2": "`bool`", "5-2": "`uint8_t`", "3-2": "`bool`", "0-3": "6 byte device address (MAC address) or zero (0) means all devices", "1-3": "Must all be zero (0)", "3-3": "Acknowledgement message required", "4-3": "Response message required", "5-3": "Wrap around message sequence number" }, "cols": 4, "rows": 6 } [/block] The _target_ device address is 8 bytes long, when using the 6 byte MAC address then left-justify the value and zero-fill the last two bytes. A _target_ device address of all zeroes effectively addresses all devices on the local network. The Frame _tagged_ field must be set accordingly. There are two flags that cause a LIFX device to send a message in response. In these cases, the _source_ identifier in the response message will be set to the same value as that in the requesting message sent by the client. * _ack\_required_ set to one (1) will cause the device to send an [Device::Acknowledgement](doc:device-messages#section-acknowledgement-45) message * _res\_required_ set to one (1) within a Set message, e.g [Light::SetPower](doc:light-messages#section-setpower-117) will cause the device to send the corresponding State message, e.g [Light::StatePower](doc:light-messages#section-statepower-118) The client can use acknowledgments to determine that the LIFX device has received a message. However, when using acknowledgments to ensure reliability in an over-burdened lossy network ... causing additional network packets may make the problem worse. Client that don't need to track the updated state of a LIFX device can choose not to request a response, which will reduce the network burden and may provide some performance advantage. In some cases, a device may choose to send a state update response independent of whether _res\_required_ is set. The _sequence_ number allows the client to provide a unique value, which will be included by the LIFX device in any message that is sent in response to a message sent by the client. This allows the client to distinguish between different messages sent with the same _source_ identifier in the Frame. See _ack\_required_ and _res\_required_ fields in the Frame Address. [block:api-header] { "type": "basic", "title": "Protocol Header" } [/block] The Protocol header contains the following information about the message: * Message type which determines what action to take (based on the Payload) [block:image] { "images": [ { "image": [ "https://files.readme.io/MzpSjhmSuaMED6viWVUc_protocol.png", "protocol.png", "577", "68", "#040404", "" ] } ] } [/block] [block:parameters] { "data": { "h-0": "Field", "h-1": "Bits", "h-2": "Type", "h-3": "Description", "0-0": "reserved", "0-1": "64", "1-1": "16", "2-1": "16", "1-0": "type", "2-0": "reserved", "0-2": "`uint64_t`", "1-2": "`uint16_t`", "0-3": "Reserved", "2-3": "Reserved", "1-3": "Message type determines the payload being used" }, "cols": 4, "rows": 3 } [/block] Reserved fields must be set to zero by the client. [block:api-header] { "type": "basic", "title": "Example" } [/block] [block:code] { "codes": [ { "code": "#pragma pack(push, 1)\ntypedef struct {\n /* frame */\n uint16_t size;\n uint16_t protocol:12;\n uint8_t addressable:1;\n uint8_t tagged:1;\n uint8_t origin:2;\n uint32_t source;\n /* frame address */\n uint8_t target[8];\n uint8_t reserved[6];\n uint8_t res_required:1;\n uint8_t ack_required:1;\n uint8_t :6;\n uint8_t sequence;\n /* protocol header */\n uint64_t :64;\n uint16_t type;\n uint16_t :16;\n /* variable length payload follows */\n} lx_protocol_header_t;\n#pragma pack(pop)", "language": "c" } ] } [/block] Numeric data-type byte-order is [little-endian](http://en.wikipedia.org/wiki/Endianness#Little-endian), which means that dumping serialized data structures or viewing network packet sniffing may show the content of numeric fields in reversed byte-order.