|
| 1 | +-- Copyright 2026 SmartThings, Inc. |
| 2 | +-- Licensed under the Apache License, Version 2.0 |
| 3 | + |
| 4 | +local capabilities = require "st.capabilities" |
| 5 | +local st_utils = require "st.utils" |
| 6 | +local clusters = require "st.zigbee.zcl.clusters" |
| 7 | +local log = require "log" |
| 8 | + |
| 9 | +-- The following definitions should be pulled from the `st.zigbee.constants` module once those changes land |
| 10 | +local KELVIN_MAX = "_max_kelvin" |
| 11 | +local KELVIN_MIN = "_min_kelvin" |
| 12 | +local MIREDS_CONVERSION_CONSTANT = 1000000 |
| 13 | +local COLOR_TEMPERATURE_KELVIN_MAX = 15000 |
| 14 | +local COLOR_TEMPERATURE_KELVIN_MIN = 1000 |
| 15 | +local COLOR_TEMPERATURE_MIRED_MAX = st_utils.round(MIREDS_CONVERSION_CONSTANT/COLOR_TEMPERATURE_KELVIN_MIN) -- 1000 |
| 16 | +local COLOR_TEMPERATURE_MIRED_MIN = st_utils.round(MIREDS_CONVERSION_CONSTANT/COLOR_TEMPERATURE_KELVIN_MAX) -- 67 |
| 17 | + |
| 18 | +-- Transition Time: The time that shall be taken to perform the step change, in units of 1/10ths of a second. |
| 19 | +local TRANSITION_TIME = 3 -- default: 0.3 seconds |
| 20 | +-- Options Mask & Override: Indicates which options are being overriden by the Level/ColorControl cluster commands |
| 21 | +local OPTIONS_MASK = 0x01 -- default: The `ExecuteIfOff` option is overriden |
| 22 | +local IGNORE_COMMAND_IF_OFF = 0x00 -- default: the command will not be executed if the device is off |
| 23 | + |
| 24 | +local function step_color_temperature_by_percent_handler(driver, device, cmd) |
| 25 | + local step_percent_change = cmd.args and cmd.args.stepSize or 0 |
| 26 | + if step_percent_change == 0 then return end |
| 27 | + local step_mode = step_percent_change > 0 and (clusters.ColorControl.types.CcStepMode and clusters.ColorControl.types.CcStepMode.DOWN or 3) or (clusters.ColorControl.types.CcStepMode and clusters.ColorControl.types.CcStepMode.UP or 1) |
| 28 | + local min_mireds = device:get_field(KELVIN_MIN) or COLOR_TEMPERATURE_MIRED_MIN -- default min mireds |
| 29 | + local max_mireds = device:get_field(KELVIN_MAX) or COLOR_TEMPERATURE_MIRED_MAX -- default max mireds |
| 30 | + local step_size_in_mireds = st_utils.round((max_mireds - min_mireds) * (math.abs(step_percent_change)/100.0)) |
| 31 | + device:send(clusters.ColorControl.server.commands.StepColorTemperature(device, step_mode, step_size_in_mireds, TRANSITION_TIME, min_mireds, max_mireds, OPTIONS_MASK, IGNORE_COMMAND_IF_OFF)) |
| 32 | +end |
| 33 | + |
| 34 | +local function step_level_handler(driver, device, cmd) |
| 35 | + local step_size = st_utils.round((cmd.args and cmd.args.stepSize or 0)/100.0 * 254) |
| 36 | + if step_size == 0 then return end |
| 37 | + local step_mode = step_size > 0 and clusters.Level.types.MoveStepMode.UP or clusters.Level.types.MoveStepMode.DOWN |
| 38 | + device:send(clusters.Level.server.commands.Step(device, step_mode, math.abs(step_size), TRANSITION_TIME, OPTIONS_MASK, IGNORE_COMMAND_IF_OFF)) |
| 39 | +end |
| 40 | + |
| 41 | +local stateless_handlers = { |
| 42 | + Name = "Zigbee Stateless Step Handlers", |
| 43 | + capability_handlers = { |
| 44 | + [capabilities.statelessColorTemperatureStep.ID] = { |
| 45 | + [capabilities.statelessColorTemperatureStep.commands.stepColorTemperatureByPercent.NAME] = step_color_temperature_by_percent_handler, |
| 46 | + }, |
| 47 | + [capabilities.statelessSwitchLevelStep.ID] = { |
| 48 | + [capabilities.statelessSwitchLevelStep.commands.stepLevel.NAME] = step_level_handler, |
| 49 | + }, |
| 50 | + }, |
| 51 | + can_handle = require("stateless_handlers.can_handle") |
| 52 | +} |
| 53 | + |
| 54 | +return stateless_handlers |
0 commit comments