Light control (on/off/brightness/color temp/color change) using Ikea Styrbar wireless remote

Summary

User interface:

  • UP = turn light on
  • DOWN = turn light off
  • HOLD UP = gradually increase light brightness when held down
  • HOLD DOWN = gradually decrease light brightness when held down
  • LEFT / RIGHT = cycle through White / Various colours
  • HOLD LEFT = gradually change colour temperature to cool when held down
  • HOLD RIGHT = gradually change colour temperature to warm when held down
  • When the increase / decrease of setting has reached its max/min value, blink the light to inform the user
  • When the light is in colour mode, changing brightness or colour temperature will reset the light to white mode. This behaviour is from the light itself. No special coding to make it work this way.

Implementation:

Things file:

Thing mqtt:topic:masterbedroom-dimmer "Master Bed Room Dimmer" (mqtt:broker:mosquitto) [ availabilityTopic="zigbee/masterbedroom-dimmer/availability", payloadAvailable="online", payloadNotAvailable="offline" ] {
    Channels:
         Type string        : action       [ stateTopic="zigbee/masterbedroom-dimmer/action", commandTopic="zigbee/masterbedroom-dimmer/action/openhab-command"  ]
         Type number        : linkquality  [ stateTopic="zigbee/masterbedroom-dimmer/linkquality" ]
         Type number        : battery      [ stateTopic="zigbee/masterbedroom-dimmer/battery" ]
}

items file:

Group gDimmers

String MasterBedRoom_Dimmer_Action (gDimmers, MasterBedRoom_Light1_Bulb) ["Control"] { channel="mqtt:topic:masterbedroom-dimmer:action" }
Number MasterBedRoom_Dimmer_Battery "Master Bed Room Dimmer Battery [%d%%]" <battery> (gBatteries) { channel="mqtt:topic:masterbedroom-dimmer:battery", expire="3h" }
Number MasterBedRoom_Dimmer_Link "Master Bed Room Dimmer Link" <network>          (gSignalStrength) { channel="mqtt:topic:masterbedroom-dimmer:linkquality" }

Note: MasterBedRoom_Light1_Bulb is the light to control - it’s an equipment in the openhab semantic model
To augment the semantic model, a custom tag is used for the Color item, since no such property exists in the official openhab semantic model

lightbulb items:

Group   MasterBedRoom_Light1_Bulb    "Master Bed Room Light1 Bulb"    <light>       (gMasterBedRoom, gMasterBedRoomLights)  ["Lightbulb"]
Switch  MasterBedRoom_Light1         "Master Bed Room Light1"         <light>       (MasterBedRoom_Light1_Bulb)             ["Control", "Power"]             
Dimmer  MasterBedRoom_Light1_Dimmer  "Master Bed Room Light1 Dimmer"                (MasterBedRoom_Light1_Bulb)             ["Control", "Light"]             
Dimmer  MasterBedRoom_Light1_CT      "Master Bed Room Light1 CT"                    (MasterBedRoom_Light1_Bulb)             ["Control", "ColorTemperature"]  
Color   MasterBedRoom_Light1_Color   "Master Bed Room Light1 Color"   <colorwheel>  (MasterBedRoom_Light1_Bulb)             ["Control", "Color"]             

Rule

# frozen_string_literal: true

require 'openhab'

module ButtonAction
  ON = 'on'
  OFF = 'off'

  BRIGHTNESS_UP = 'brightness_move_up'
  BRIGHTNESS_DOWN = 'brightness_move_down'
  BRIGHTNESS_STOP = 'brightness_stop'

  LEFT = 'arrow_left_click'
  LEFT_HOLD = 'arrow_left_hold'
  LEFT_RELEASE = 'arrow_left_release'

  RIGHT = 'arrow_right_click'
  RIGHT_HOLD = 'arrow_right_hold'
  RIGHT_RELEASE = 'arrow_right_release'
end

COLORS = {
  white: '#ffffff',
  red: '#ff0000',
  yellow: '#FFFF00',
  green: '#00FF00',
  aqua: '#00FFFF',
  blue: '#0000FF',
  fuchsia: '#FF00FF'
}.freeze

def blink(dimmer)
  power = dimmer.points(Semantics::Power).first
  power.off
ensure
  after(350.ms) do
    power.on
  end
end

@colors = Hash.new { |hash, key| hash[key] = COLORS.values }

def adjust(dimmer, delta)
  return timers[dimmer]&.cancel if delta.zero?

  dimmer.points(Semantics::Power).first&.ensure.on

  after(0.ms, id: dimmer) do |timer|
    next blink(dimmer) if (dimmer == '100 %' && delta.positive?) || (dimmer <= '1 %' && delta.negative?)

    dimmer << (dimmer.to_i + delta).clamp(1, 100)
    timer.reschedule 100.ms
  end
end

rule 'Ikea Dimmer Handler' do
  updated gDimmers.members
  triggered do |action|
    light = action.equipment
    next unless light

    dimmer = light.points(Semantics::Light).first
    power = light.points(Semantics::Power).first
    ct = light.points(Semantics::ColorTemperature).first
    color = light.tagged('Color').first

    case action.state
    when ButtonAction::ON then power.ensure.on
    when ButtonAction::OFF then power.ensure.off
    when ButtonAction::BRIGHTNESS_UP then adjust(dimmer, 5)
    when ButtonAction::BRIGHTNESS_DOWN then adjust(dimmer, -5)
    when ButtonAction::BRIGHTNESS_STOP then adjust(dimmer, 0)
    when ButtonAction::LEFT then color << @colors[dimmer].rotate!.first
    when ButtonAction::RIGHT then color << @colors[dimmer].rotate!(-1).first
    when ButtonAction::LEFT_HOLD then adjust(ct, -10)
    when ButtonAction::RIGHT_HOLD then adjust(ct, 10)
    when ButtonAction::RIGHT_RELEASE, ButtonAction::LEFT_RELEASE then adjust(ct, 0)
    end
  end
end
1 Like