I wanted a passive ambient display that tells me something useful without picking up my phone — weather at a glance during the day, a wind-down mode at night, green at 6:30am if it’s worth cycling to work. The IKEA Varmblixt is $30, Zigbee-native, and pairs directly to ZHA without an IKEA hub.

Pairing

Not obvious. There’s no reset button. To enter pairing mode, power-cycle the lamp 12 times in rapid succession — plug, unplug, plug, unplug… It flashes white 3–4 times when it’s ready. A smart plug makes this way easier than fumbling with the physical outlet. Source

Entity after pairing: light.led_light0x07c2_varmblixt_table_wall_lamp

Scripts

Three color scripts in scripts.yaml. All use mode: restart — calling a new one immediately kills whatever’s running, no cleanup needed.

cotton_candy_sunset

The default after sunset. Two warm amber tones crossfading on 45-second transitions. Runs until midnight.

cotton_candy_sunset:
  alias: Cotton Candy Sunset
  sequence:
  - repeat:
      count: 500
      sequence:
      - action: light.turn_on
        target:
          entity_id: light.led_light0x07c2_varmblixt_table_wall_lamp
        data:
          rgb_color: [220, 80, 5]
          brightness_pct: 50
          transition: 45
      - delay: 00:00:10
      - action: light.turn_on
        target:
          entity_id: light.led_light0x07c2_varmblixt_table_wall_lamp
        data:
          rgb_color: [255, 130, 10]
          brightness_pct: 50
          transition: 45
      - delay: 00:00:10
  mode: restart

The count: 500 at this pace is ~14 hours — long enough to cover any night. The midnight automation kills it before the loop ends.

color_drift

Six colors, 4-second transitions, 5-second holds. Lava lamp pacing.

color_drift:
  alias: Color Drift
  sequence:
  - repeat:
      count: 500
      sequence:
      - action: light.turn_on
        target:
          entity_id: light.led_light0x07c2_varmblixt_table_wall_lamp
        data: {rgb_color: [255, 134, 8], brightness_pct: 50, transition: 4}
      - delay: 00:00:05
      - action: light.turn_on
        target:
          entity_id: light.led_light0x07c2_varmblixt_table_wall_lamp
        data: {rgb_color: [200, 0, 180], brightness_pct: 50, transition: 4}
      - delay: 00:00:05
      - action: light.turn_on
        target:
          entity_id: light.led_light0x07c2_varmblixt_table_wall_lamp
        data: {rgb_color: [0, 180, 180], brightness_pct: 50, transition: 4}
      - delay: 00:00:05
      - action: light.turn_on
        target:
          entity_id: light.led_light0x07c2_varmblixt_table_wall_lamp
        data: {rgb_color: [120, 0, 220], brightness_pct: 50, transition: 4}
      - delay: 00:00:05
      - action: light.turn_on
        target:
          entity_id: light.led_light0x07c2_varmblixt_table_wall_lamp
        data: {rgb_color: [255, 60, 0], brightness_pct: 50, transition: 4}
      - delay: 00:00:05
      - action: light.turn_on
        target:
          entity_id: light.led_light0x07c2_varmblixt_table_wall_lamp
        data: {rgb_color: [0, 210, 40], brightness_pct: 50, transition: 4}
      - delay: 00:00:05
  mode: restart

party_pulse

Five colors, 1-second transitions. For when you want it to be annoying on purpose.

party_pulse:
  alias: Party Pulse
  sequence:
  - repeat:
      count: 500
      sequence:
      - action: light.turn_on
        target:
          entity_id: light.led_light0x07c2_varmblixt_table_wall_lamp
        data: {rgb_color: [255, 0, 120], brightness_pct: 80, transition: 1}
      - delay: 00:00:01
      - action: light.turn_on
        target:
          entity_id: light.led_light0x07c2_varmblixt_table_wall_lamp
        data: {rgb_color: [50, 255, 0], brightness_pct: 80, transition: 1}
      - delay: 00:00:01
      - action: light.turn_on
        target:
          entity_id: light.led_light0x07c2_varmblixt_table_wall_lamp
        data: {rgb_color: [0, 220, 255], brightness_pct: 80, transition: 1}
      - delay: 00:00:01
      - action: light.turn_on
        target:
          entity_id: light.led_light0x07c2_varmblixt_table_wall_lamp
        data: {rgb_color: [255, 100, 0], brightness_pct: 80, transition: 1}
      - delay: 00:00:01
      - action: light.turn_on
        target:
          entity_id: light.led_light0x07c2_varmblixt_table_wall_lamp
        data: {rgb_color: [160, 0, 255], brightness_pct: 80, transition: 1}
      - delay: 00:00:01
  mode: restart

Automations

Weather + Sunset

Triggers on sunrise, sunset, and every hour. After sunset it kicks off cotton_candy_sunset. During the day it sets a static color based on current conditions.

SF has brutal microclimate variance — Met.no (the HA default) was consistently wrong about fog and made the cycling trigger useless. Switched to PirateWeather, which is a free Dark Sky API replacement using the same model. Night and day difference for fog. Setup docs: pirateweather.net/en/latest/ha

- id: varmblixt_sf_weather_sunset
  alias: 'Varmblixt: SF Weather & Sunset'
  triggers:
  - trigger: sun
    event: sunset
  - trigger: sun
    event: sunrise
  - trigger: time_pattern
    hours: /1
  actions:
  - choose:
    - conditions:
      - condition: sun
        after: sunset
      sequence:
      - action: script.turn_on
        target:
          entity_id: script.cotton_candy_sunset
    - conditions:
      - condition: sun
        after: sunrise
        before: sunset
      sequence:
      - action: light.turn_on
        target:
          entity_id: light.led_light0x07c2_varmblixt_table_wall_lamp
        data:
          brightness_pct: 70
          rgb_color: >
            {% set s = states("weather.pirateweather") %}
            {% if s == "fog" %}[200,200,255]
            {% elif s == "sunny" %}[255,200,0]
            {% elif s in ["rainy","pouring"] %}[0,100,255]
            {% elif s in ["cloudy","partlycloudy"] %}[150,200,255]
            {% else %}[255,150,50]{% endif %}
  mode: single
Condition Color
Sunny Yellow [255,200,0]
Cloudy / Partly Cloudy Light blue [150,200,255]
Rainy / Pouring Blue [0,100,255]
Fog Blue-white [200,200,255]
Other Warm orange [255,150,50]

Cycling Green Light

At 6:30am, if it’s 55–78°F, wind under 15mph, and no rain or fog, the lamp goes green. Go/no-go without touching a phone. At 9am it reverts to the weather color.

- id: cycling_weather_green
  alias: Cycling Weather - Green Light
  triggers:
  - trigger: time
    at: 06:30:00
  conditions:
  - condition: template
    value_template: >
      {% set temp = state_attr('weather.pirateweather', 'temperature') | float(0) %}
      {% set wind = state_attr('weather.pirateweather', 'wind_speed') | float(99) %}
      {% set cond = states('weather.pirateweather') %}
      {{ temp >= 55 and temp <= 78
         and wind < 15
         and cond not in ['rainy', 'pouring', 'fog', 'hail', 'snowy',
                          'snowy-rainy', 'lightning', 'lightning-rainy', 'exceptional'] }}
  actions:
  - action: light.turn_on
    target:
      entity_id: light.led_light0x07c2_varmblixt_table_wall_lamp
    data:
      rgb_color: [0, 210, 40]
      brightness_pct: 50
  mode: single

- id: cycling_weather_revert
  alias: Cycling Weather - Revert at 9am
  triggers:
  - trigger: time
    at: 09:00:00
  actions:
  - action: automation.trigger
    target:
      entity_id: automation.varmblixt_sf_weather_sunset
  mode: single

Door Open Alert

If the front door stays open more than 10 seconds, the lamp goes solid red at full brightness — visible from anywhere in the apartment. Reverts automatically when the door closes.

- id: door_open_light_flash
  alias: Alert - Door Open Light Red
  triggers:
  - trigger: state
    entity_id: binary_sensor.ikea_of_sweden_parasoll_door_window_sensor
    to: 'on'
    for:
      seconds: 10
  actions:
  - action: light.turn_on
    target:
      entity_id: light.led_light0x07c2_varmblixt_table_wall_lamp
    data:
      rgb_color: [255, 0, 0]
      brightness_pct: 100
  - wait_for_trigger:
    - trigger: state
      entity_id: binary_sensor.ikea_of_sweden_parasoll_door_window_sensor
      to: 'off'
    timeout:
      hours: 1
    continue_on_timeout: true
  - choose:
    - conditions:
      - condition: sun
        after: sunset
      sequence:
      - action: script.turn_on
        target:
          entity_id: script.cotton_candy_sunset
    - conditions:
      - condition: sun
        after: sunrise
        before: sunset
      sequence:
      - action: light.turn_on
        target:
          entity_id: light.led_light0x07c2_varmblixt_table_wall_lamp
        data:
          brightness_pct: 70
          rgb_color: >
            {% set s = states("weather.pirateweather") %}
            {% if s == "fog" %}[200,200,255]
            {% elif s == "sunny" %}[255,200,0]
            {% elif s in ["rainy","pouring"] %}[0,100,255]
            {% elif s in ["cloudy","partlycloudy"] %}[150,200,255]
            {% else %}[255,150,50]{% endif %}
  mode: single

Midnight Off

Stops all running scripts and kills the lamp at midnight.

- id: '1758620017271'
  alias: Midnight
  triggers:
  - trigger: time
    at: 00:00:00
  actions:
  - action: script.turn_off
    target:
      entity_id:
      - script.cotton_candy_sunset
      - script.color_drift
      - script.party_pulse
  - action: light.turn_off
    target:
      entity_id:
      - light.all_lights
      - light.led_light0x07c2_varmblixt_table_wall_lamp
  mode: single

The lamp is listed explicitly alongside light.all_lights because it wasn’t reliably included in the group before a full HA restart. Turning off all_lights alone didn’t always catch it.