Last active
March 6, 2021 17:12
-
-
Save neutmute/6a8e44f300b2b5a4971630371cd0dd97 to your computer and use it in GitHub Desktop.
openhab universal dimmer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
RegEx
transformation to be installed