Here’s an app with the option to have up to two brighter and two dimmer slave groups as well as the traditional options. (I couldn’t get the ratio code to work, probably because of variable type conflicts; but the live logging wasn’t working for me to debug)
I tested it with only a couple of bulbs, but it seemed to work well including the sanity checks for when the offset would exceed the min/max dim levels.
Let me know if it works for your scenario. I know the Dim with Me app always worked better with virtual masters, but hopefully it correctly subscribes to the wall switch for you.
/**
* Dim With Me - plus offset
*
* Original Author: todd@wackford.net
* Date: 2013-11-12
*/
/**
* App Name: Dim With Me plus Offset
*
* Author: Todd Wackford
* twack@wackware.net
* Date: 2013-11-12
* Version: 0.2
*
* Use this program with a virtual dimmer as the master for best results.
*
* This app lets the user select from a list of dimmers to act as a triggering
* master for other dimmers or regular switches. Regular switches come on
* anytime the master dimmer is on or dimmer level is set to more than 0%.
* of the master dimmer.
*
******************************************************************************
* Changes
******************************************************************************
*
* Change 1: 2014-10-22 (wackford)
* Fixed bug in setlevelwhen on/off was coming in
*
* Change 2: 2014-11-01 (wackford)
* added subscription to switch.level event. Shouldn't change much
* but some devices only sending level event and not setLevel.
*
* Change 3: 2015-05-05 (sticks18)
* added ability to offset slave dimmers in case different lights
* dim differently or have varying lumen output.
*
******************************************************************************
Other Info: Special thanks to Danny Kleinman at ST for helping me get the
state stuff figured out. The Android state filtering had me
stumped.
*
******************************************************************************
*/
// Automatically generated. Make future change here.
definition(
name: "Dim With Me plus Offset",
namespace: "wackware",
author: "todd@wackford.net",
description: "Follows the dimmer level of another dimmer",
category: "My Apps",
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png",
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience%402x.png"
)
preferences {
page(name: "selectMaster", title: "Select Basic Devices", install: true, uninstall: true) {
section("When this...") {
input "masters", "capability.switchLevel",
multiple: false,
title: "Master Dimmer Switch...",
required: true
}
section("Then these will follow with on/off...") {
input "slaves2", "capability.switch",
multiple: true,
title: "Slave On/Off Switch(es)...",
required: false
}
section("And these will follow with the same dimming level...") {
input "slaves", "capability.switchLevel",
multiple: true,
title: "Slave Dimmer Switch(es)...",
required: false
}
section("Slaves with offset...") {
href "addOffset", title:"Additive Offset (Slave = Master Level + Offset)"
href "minusOffset", title: "Negative Offset (Slave = Master Level - Offset)"
// href "ratioOffset", title: "Ratio Offset (Slave X% of Master Level)"
}
section("Name and Mode...") {
label title: "Assign a name", required: false
mode title: "Set for specific mode(s)", required: false
}
}
page(name: "addOffset", title: "addOffset")
page(name: "minusOffset", title: "minusOffset")
// page(name: "ratioOffset", title: "ratioOffset")
}
def addOffset() {
dynamicPage(name: "addOffset", title: "Select Additive Offset Slave Dimmers...", install:false, uninstall: false) {
section("Additive Offset Group 1") {
input "slavesAdd1", "capability.switchLevel", title: "Slave Dimmers...", multiple: true, required: false
input "levelAdd1", "number", title: "Level Offset (number to be added to master level)", required: false
}
section("Additive Offset Group 2") {
input "slavesAdd2", "capability.switchLevel", title: "Slave Dimmers...", multiple: true, required: false
input "levelAdd2", "number", title: "Level Offset (number to be added to master level)", required: false
}
}
}
def minusOffset() {
dynamicPage(name: "minusOffset", title: "Select Negative Offset Slave Dimmers...", install:false, uninstall: false) {
section("Negative Offset Group 1") {
input "slavesMin1", "capability.switchLevel", title: "Slave Dimmers...", multiple: true, required: false
input "levelMin1", "number", title: "Level Offset (number to be subtracted from master level)", required: false
}
section("Negative Offset Group 2") {
input "slavesMin2", "capability.switchLevel", title: "Slave Dimmers...", multiple: true, required: false
input "levelMin2", "number", title: "Level Offset (number to be subtracted from master level)", required: false
}
}
}
/* The math for the ratio isn't working
def ratioOffset() {
dynamicPage(name: "ratioOffset", title: "Select Ratio Offset Slave Dimmers...", install:false, uninstall: false) {
section("Ratio Offset Group 1") {
input "slavesRatio1", "capability.switchLevel", title: "Slave Dimmers...", multiple: true, required: false
input "levelRatio1", "number", title: "X% of Master Level (ie: 10 = 0.10 * Master Level, 110 = 1.10 * Master Level)", required: false
}
section("Ratio Offset Group 2") {
input "slavesRatio2", "capability.switchLevel", title: "Slave Dimmers...", multiple: true, required: false
input "levelRatio2", "number", title: "X% of Master Level (ie: 10 = 0.10 * Master Level, 110 = 1.10 * Master Level)", required: false
}
}
}
*/
def installed()
{
subscribe(masters, "switch.on", switchOnHandler)
subscribe(masters, "switch.off", switchOffHandler)
subscribe(masters, "switch.setLevel", switchSetLevelHandler)
subscribe(masters, "switch", switchSetLevelHandler)
}
def updated()
{
unsubscribe()
subscribe(masters, "switch.on", switchOnHandler)
subscribe(masters, "switch.off", switchOffHandler)
subscribe(masters, "switch.setLevel", switchSetLevelHandler)
subscribe(masters, "switch", switchSetLevelHandler)
log.info "subscribed to all of switches events"
}
def switchSetLevelHandler(evt)
{
if ((evt.value == "on") || (evt.value == "off" ))
return
def level = evt.value.toFloat()
level = level.toInteger()
log.info "switchSetLevelHandler Event: ${level}"
if (levelAdd1) {
def lvlAdd1 = level + levelAdd1
lvlAdd1 = lvlAdd1.toInteger()
if (lvlAdd1 > 100) {lvlAdd1 = 100}
if ((lvlAdd1 < 1) && (level > 0)) {lvlAdd1 = 1}
log.info "switchSetLevelHandler Add 1 Offset Event: ${lvlAdd1}"
slavesAdd1?.setLevel(lvlAdd1)
}
if (levelAdd2) {
def lvlAdd2 = level + levelAdd2
lvlAdd2 = lvlAdd2.toInteger()
if (lvlAdd2 > 100) {lvlAdd2 = 100}
if ((lvlAdd2 < 1) && (level > 0)) {lvlAdd2 = 1}
log.info "switchSetLevelHandler Add 2 Offset Event: ${lvlAdd2}"
slavesAdd2?.setLevel(lvlAdd2)
}
if (levelMin1) {
def lvlMin1 = level - levelMin1
lvlMin1 = lvlMin1.toInteger()
if (lvlMin1 > 100) {lvlMin1 = 100}
if ((lvlMin1 < 1) && (level > 0)) {lvlMin1 = 1}
log.info "switchSetLevelHandler Minus 1 Offset Event: ${lvlMin1}"
slavesMin1?.setLevel(lvlMin1)
}
if (levelMin2) {
def lvlMin2 = level - levelMin2
lvlMin2 = lvlMin2.toInteger()
if (lvlMin2 > 100) {lvlMin2 = 100}
if ((lvlMin2 < 1) && (level > 0)) {lvlMin2 = 1}
log.info "switchSetLevelHandler Minus 2 Offset Event: ${lvlMin2}"
slavesMin2?.setLevel(lvlMin2)
}
/*
if (levelRatio1) {
def lvlRatio1 = math.Round((levelRatio1/100)*level)
lvlRatio1 = lvlRatio1.toInteger()
if (lvlRatio1 > 100) {lvlRatio1 = 100}
if ((lvlRatio1 < 1) && (level > 0)) {lvlRatio1 = 1}
log.info "switchSetLevelHandler Ratio 1 Offset Event: ${lvlRatio1}"
slavesRatio1?.setLevel(lvlRatio1)
}
if (levelRatio2) {
def lvlRatio2 = math.Round((levelRatio2/100)*level)
lvlRatio2 = lvlRatio2.toInteger()
if (lvlRatio2 > 100) {lvlRatio2 = 100}
if ((lvlRatio2 < 1) && (level > 0)) {lvlRatio2 = 1}
log.info "switchSetLevelHandler Ratio 2 Offset Event: ${lvlRatio2}"
slavesRatio2?.setLevel(lvlRatio2)
}
*/
slaves?.setLevel(level)
}
def switchOffHandler(evt) {
log.info "switchoffHandler Event: ${evt.value}"
slaves?.off()
slaves2?.off()
slavesAdd1?.off()
slavesAdd2?.off()
slavesMin1?.off()
slavesMin2?.off()
slavesRatio1?.off()
slavesRatio2?.off()
}
def switchOnHandler(evt) {
log.info "switchOnHandler Event: ${evt.value}"
def dimmerValue = masters.latestValue("level") //can be turned on by setting the level
slaves?.on()
slaves2?.on()
slavesAdd1?.on()
slavesAdd2?.on()
slavesMin1?.on()
slavesMin2?.on()
slavesRatio1?.on()
slavesRatio2?.on()
}