LIFX Tiles are square devices containing an 8x8 matrix of 64 individually controllable LEDs. These devices are also special in that you can join up to 5 of them in a chain which then behaves like a single device. The tile closest to the power supply will be the master tile and is the one you send messages to for control of any tile in the chain.
When not using the Tile messages (essentially any message that doesn't have a
tile_indexattribute) the whole chain is controlled. For example if you send a SetColor (102) message to a tile, all the tiles in the chain will change to the chosen color. This means applications that already support the current protocol do not need to make any changes to support controlling all the tiles at once.
When you set colors on the Tile you specify an array of 64 colors. The order of that array for a right side up tile is as follows:
Tiles can be controlled individually using the
length properties for Tile messages. Tiles are indexed with the master tile being represented with zero, and increasing by one for each tile after. When addressing tiles the
tile_index represents the first tile that should process the command, and the
length value represents how many tiles should process the command beginning with the tile specified in
tile_index and continuing to the tiles immediately following that one.
The following diagrams illustrate the use of
user_y fields from StateDeviceChain (702) contain positioning information for each tile. Each tile is positioned in a 2D space. The point represents the location of the center of the tile and the unit of measurement is one tile width. So if you have 3 tiles in a chain with
user_y of (0, 0), (-0.5, 1) and (0.5, -1) then you'd have something like:
These position values are stored in the tile and are meant to be used by client applications in order to locate the tiles on a 2D plane. This can then be used to apply images across the set of tiles, or match up the borders of a tile when displaying a pattern. You may change these values using SetUserPosition (703)
The LIFX tiles have an accelerometer in them that allows the device to know what orientation the tiles are in (upright, rotated left, rotated right, upside down, face up, face down)
This information is given back to you as a
(x, y, z) triplet for each tile from the StateDeviceChain (702) packet. You may use the following code to determine the rotation of your tile.
def nearest_orientation(x, y, z): """ Determine which orientation maps to the provided x, y, z """ absX = abs(x) absY = abs(y) absZ = abs(z) if x == -1 and y == -1 and z == -1: # Invalid data, assume right-side up. return "RightSideUp" elif absX > absY and absX > absZ: if x > 0: return "RotatedRight" else: return "RotatedLeft" elif absZ > absX and absZ > absY: if z > 0: return "FaceDown" else: return "FaceUp" else: if y > 0: return "UpsideDown" else: return "RightSideUp"
You can also "rotate" the 64 colors you send to a tile with the following code
def reorient(colors, orientation): """ Return the colors in the different order given our orientation """ if orientation in ("RightSideUp", "FaceUp", "FaceDown": # The colors are already in the correct order return colors new_colors =  for index, color in enumerate(colors): new_index = rotated_index(i, orientation) new_colors.append((new_index, color)) # We now sort the new_colors array so that it appears like # [(0, c1), (1, c2), ...] new_colors = sorted(new_colors) # and we return a list of just the colors return [color for index, color in new_colors] def rotated_index(i, orientation): """ Give new index for i given our orientation """ x = i % 8 y = i // 8 if orientation == "UpsideDown": new_x = 7 - x new_y = 7 - y elif orientation == "RotatedLeft": new_x = 7 - y new_y = x elif orientation == "RotatedRight": new_x = y new_y = 7 - x else: # For all other orientations the x and y don't change new_x = x new_y = y return new_x + (new_y * 8)
Updated 2 months ago