Ceiling Lights¶
LIFX Ceiling lights are unique fixtures that combine two lighting components in one device:
- Downlight: Main illumination with multiple addressable zones (63 or 127 zones)
- Uplight: Ambient/indirect lighting via a single zone
The CeilingLight class provides high-level control over these components while inheriting full matrix functionality from MatrixLight.
Supported Devices¶
| Product | Zones | Layout |
|---|---|---|
| LIFX Ceiling (US/Intl) | 64 | 8x8 grid, zone 63 = uplight |
| LIFX Ceiling Capsule (US/Intl) | 128 | 16x8 grid, zone 127 = uplight |
Quick Start¶
from lifx import CeilingLight
from lifx.color import HSBK
async def main():
async with await CeilingLight.from_ip("192.168.1.100") as ceiling:
# Set downlight to warm white
await ceiling.set_downlight_colors(
HSBK(hue=0, saturation=0, brightness=1.0, kelvin=3000)
)
# Set uplight to a dim, warm ambient glow
await ceiling.set_uplight_color(
HSBK(hue=30, saturation=0.2, brightness=0.3, kelvin=2700)
)
Component Control¶
Setting Colors¶
Downlight¶
Set all downlight zones to the same color:
# Single color for all zones
await ceiling.set_downlight_colors(
HSBK(hue=0, saturation=0, brightness=0.8, kelvin=4000)
)
Or set each zone individually:
# Create a gradient across all zones
zone_count = len(range(*ceiling.downlight_zones.indices(256)))
colors = [
HSBK(hue=(i * 360 / zone_count), saturation=1.0, brightness=0.5, kelvin=3500)
for i in range(zone_count)
]
await ceiling.set_downlight_colors(colors)
Uplight¶
Reading Current Colors¶
# Get current uplight color
uplight_color = await ceiling.get_uplight_color()
print(f"Uplight: H={uplight_color.hue}, B={uplight_color.brightness}")
# Get all downlight colors
downlight_colors = await ceiling.get_downlight_colors()
print(f"Downlight zones: {len(downlight_colors)}")
Turning Components On/Off¶
The turn_*_on() and turn_*_off() methods provide smart state management:
# Turn off uplight (stores current color for later restoration)
await ceiling.turn_uplight_off()
# Turn uplight back on (restores previous color)
await ceiling.turn_uplight_on()
# Turn on with a specific color
await ceiling.turn_uplight_on(
color=HSBK(hue=0, saturation=0, brightness=1.0, kelvin=3500)
)
The same pattern works for downlights:
# Turn off downlight
await ceiling.turn_downlight_off()
# Turn downlight back on
await ceiling.turn_downlight_on()
# Turn on with specific colors
await ceiling.turn_downlight_on(
colors=HSBK(hue=0, saturation=0, brightness=0.8, kelvin=4000)
)
Checking Component State¶
# Check if components are on
if ceiling.uplight_is_on:
print("Uplight is on")
if ceiling.downlight_is_on:
print("Downlight is on")
State Properties Require Recent Data
The uplight_is_on and downlight_is_on properties rely on cached data.
Call get_uplight_color() or get_downlight_colors() first to ensure
accurate state.
Device State¶
After connecting to a CeilingLight, you can access the complete device state via the state property, which returns a CeilingLightState dataclass:
from lifx import CeilingLight, CeilingLightState
async with await CeilingLight.from_ip("192.168.1.100") as ceiling:
state: CeilingLightState = ceiling.state
# Access ceiling-specific state
print(f"Uplight color: {state.uplight_color}")
print(f"Uplight is on: {state.uplight_is_on}")
print(f"Downlight zones: {len(state.downlight_colors)}")
print(f"Downlight is on: {state.downlight_is_on}")
# Access inherited state from MatrixLightState/LightState
print(f"Device label: {state.label}")
print(f"Power: {'on' if state.power else 'off'}")
print(f"Model: {state.model}")
CeilingLightState Attributes¶
CeilingLightState extends MatrixLightState with ceiling-specific attributes:
| Attribute | Type | Description |
|---|---|---|
uplight_color |
HSBK |
Current color of the uplight component |
downlight_colors |
list[HSBK] |
Colors for each downlight zone (63 or 127) |
uplight_is_on |
bool |
True if uplight brightness > 0 |
downlight_is_on |
bool |
True if any downlight zone brightness > 0 |
uplight_zone |
int |
Zone index for uplight (63 or 127) |
downlight_zones |
slice |
Slice for downlight zones |
Plus all attributes inherited from MatrixLightState: chain, tile_colors, tile_count, effect, and from LightState: color, power, label, model, serial, mac_address, capabilities, etc.
Zone Layout¶
Access the component zone indices directly:
async with await CeilingLight.from_ip("192.168.1.100") as ceiling:
# Get uplight zone index (63 or 127 depending on model)
uplight_idx = ceiling.uplight_zone
print(f"Uplight zone: {uplight_idx}")
# Get downlight zones as a slice
downlight_slice = ceiling.downlight_zones
print(f"Downlight zones: {downlight_slice}") # slice(0, 63) or slice(0, 127)
# Calculate number of downlight zones
zone_count = len(range(*downlight_slice.indices(256)))
print(f"Number of downlight zones: {zone_count}")
State Persistence¶
CeilingLight supports optional state persistence to preserve component colors across sessions:
async with await CeilingLight.from_ip(
"192.168.1.100",
state_file="~/.lifx/ceiling_state.json"
) as ceiling:
# Colors are automatically loaded from file on connection
# and saved when using turn_*_off() methods
await ceiling.turn_uplight_off() # Saves current color to file
# ... later ...
await ceiling.turn_uplight_on() # Restores from file if available
The state file stores colors per device serial number, supporting multiple devices:
{
"d073d5123456": {
"uplight": {
"hue": 30.0,
"saturation": 0.2,
"brightness": 0.4,
"kelvin": 2700
},
"downlight": [
{"hue": 0.0, "saturation": 0.0, "brightness": 0.8, "kelvin": 4000}
]
}
}
Brightness Determination¶
When calling turn_uplight_on() or turn_downlight_on() without a color parameter, CeilingLight uses the following priority to determine brightness:
- Stored state: If a color was previously saved (via
turn_*_off()orset_*_color()) - Infer from other component: Average brightness of the other component
- Default: 80% brightness
This ensures a reasonable brightness level even when no state is available.
Transition Duration¶
All color-setting methods support smooth transitions:
# 2-second transition to new color
await ceiling.set_uplight_color(
HSBK(hue=0, saturation=0, brightness=1.0, kelvin=3500),
duration=2.0 # seconds
)
# Instant change (default)
await ceiling.set_downlight_colors(
HSBK(hue=240, saturation=1.0, brightness=0.5, kelvin=3500),
duration=0.0
)
MatrixLight Compatibility¶
CeilingLight extends MatrixLight, so all matrix operations are available:
async with await CeilingLight.from_ip("192.168.1.100") as ceiling:
# Use MatrixLight methods directly
all_colors = await ceiling.get_all_tile_colors()
tile_chain = await ceiling.get_tile_chain()
# Set raw matrix colors (bypasses component abstraction)
await ceiling.set_matrix_colors(0, colors)
# Apply effects
from lifx.protocol.protocol_types import TileEffectType
await ceiling.set_tile_effect(
effect_type=TileEffectType.MORPH,
speed=5000,
)
Example: Night Mode¶
Create a subtle night light with dim uplight and downlight off:
from lifx import CeilingLight
from lifx.color import HSBK
async def night_mode(ip: str):
async with await CeilingLight.from_ip(ip) as ceiling:
# Store current colors before turning off
await ceiling.turn_downlight_off()
# Set uplight to very dim warm glow
await ceiling.set_uplight_color(
HSBK(hue=30, saturation=0.3, brightness=0.05, kelvin=2200),
duration=2.0
)
Example: Daytime Productivity¶
Bright, cool white for focus:
async def daytime_mode(ip: str):
async with await CeilingLight.from_ip(ip) as ceiling:
# Bright cool downlight for task lighting
await ceiling.set_downlight_colors(
HSBK(hue=0, saturation=0, brightness=1.0, kelvin=5500),
duration=1.0
)
# Turn off uplight during the day
await ceiling.turn_uplight_off(duration=1.0)
Example: Evening Ambiance¶
Warm tones with accent uplight:
async def evening_mode(ip: str):
async with await CeilingLight.from_ip(ip) as ceiling:
# Dimmed warm downlight
await ceiling.set_downlight_colors(
HSBK(hue=30, saturation=0.1, brightness=0.4, kelvin=2700),
duration=2.0
)
# Colorful uplight accent
await ceiling.set_uplight_color(
HSBK(hue=280, saturation=0.6, brightness=0.3, kelvin=3500),
duration=2.0
)
API Reference¶
See CeilingLight API Reference for complete method documentation.