Skip to content

Instantly share code, notes, and snippets.

@neutmute
Last active March 6, 2021 17:12
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save neutmute/6a8e44f300b2b5a4971630371cd0dd97 to your computer and use it in GitHub Desktop.
Save neutmute/6a8e44f300b2b5a4971630371cd0dd97 to your computer and use it in GitHub Desktop.
openhab universal dimmer
import org.eclipse.smarthome.model.script.ScriptServiceUtil
/*
# Universal dimmer
Reliably dim or colour lights to a target value over a set period of time
Thread: https://community.openhab.org/t/rule-to-slowly-fading-in-or-out-any-given-item-based-on-variables/54988/30?u=habau
Source: https://gist.github.com/neutmute/6a8e44f300b2b5a4971630371cd0dd97
*/
val java.util.Map<String, Timer> timerPool = newHashMap
// Uses linear regression to calculate the new brightness value, send the comand and return the new value
var dimm = [GenericItem item, Number startingValue, Number targetValue, Number elapsedMs, Number periodMs |
var slope = ((targetValue - startingValue) / periodMs) as Number
var Number nextBrightness = ((slope * elapsedMs) + startingValue) as Number
item.sendCommand(nextBrightness)
nextBrightness
]
// universaldimmer.sendCommand("item_name,target-value,fade-time-ms")
rule "UniversalDimmer"
when
// syntax: <item name>,<target value>,<fade time>
//
// item name: item to fade
// target value: e.g. 100 for ON or 0 for OFF
// fade time: amount of time (in milliseconds) to reach the target value
//
// sample: lounge_light,100,10000
Item universaldimmer received command
then
val commandArray = receivedCommand.toString.split(",")
val itemName = commandArray.get(0) // Item to handle
var int targetValue = Integer::parseInt(commandArray.get(1)) // The final value we want
val int fadePeriodMs = Integer::parseInt(commandArray.get(2)) // How long to take to get there
val item = ScriptServiceUtil.getItemRegistry.getItem(itemName)
val type = item.getAcceptedDataTypes().get(0).toString.split(" ").get(1).toString.split("\\.").get(6).toString //https://community.openhab.org/t/rule-to-slowly-fading-in-or-out-any-given-item-based-on-variables/54988/32?u=habau
var int iteration = 0
var startedMillis = now.millis
var int timerTickEveryMs = 200;
if (item.state == NULL)
{
logInfo("UniversalDimmer", "Cannot dim " + itemName + ", state is null")
return
}
// Normalise the target value
if (targetValue > 100) {
targetValue = 100
} else if (targetValue < 0) {
targetValue = 0
}
// If a timer for this item is still on, kill it
var existingTimer = timerPool.get(itemName)
if (existingTimer !== null)
{
logInfo("UniversalDimmer", "Cancelling existing timer for " + itemName)
existingTimer.cancel
}
var int startingBrightness = 0
if (type == "HSBType") {
startingBrightness = (item.state as HSBType).getBrightness().intValue
} else if (type == "PercentType") {
startingBrightness = (item.state as DecimalType).intValue
}
else
{
logInfo("UniversalDimmer", String::format("Universal dimmer doesn't know how to handle %s of type %s", itemName, type));
}
logInfo("UniversalDimmer", String::format("Dim %s %s from %d => %d over %d ms", itemName, type, startingBrightness, targetValue, fadePeriodMs));
// create the timer
timerPool.put(itemName, createTimer(now.plusMillis(timerTickEveryMs)) [|
var elapsedMs = now.millis - startedMillis
// Check if finished
var isAtTarget = startingBrightness != targetValue;
if (elapsedMs <= fadePeriodMs && isAtTarget) {
iteration = iteration + 1
var Number brightness = dimm.apply(item, startingBrightness, targetValue, elapsedMs, fadePeriodMs)
logInfo("UniversalDimmer", String::format("itemName=%s set to %.2f, iteration=%d, elapsedMs=%d", itemName, brightness, iteration, elapsedMs));
timerPool.get(itemName).reschedule(now.plusMillis(timerTickEveryMs))
} else {
timerPool.remove(itemName)
if (!isAtTarget)
{
item.sendCommand(targetValue)
}
logInfo("UniversalDimmer", String::format("Finished dimming %s from %d => %d", itemName, startingBrightness, targetValue))
}
])
end
@neutmute
Copy link
Author

neutmute commented Jan 27, 2021

  • See revision 3 for OH2 version
  • Current OH3 version requires the RegEx transformation to be installed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment