Your question sounds as you may not be familiar with rules…is so please read the documentation before you proceed.
I have everything defined in a text file, so you will need to adjust if you configure things and items in PaperUI (and I cannot help a lot there as I am not using it). Finally, do NOT mix textual configuration and configuration in text files.
So here my thing definition:
Bridge mqtt:broker:mosquitto "Mosquitto" @ "Systems" [ host="127.0.0.1", secure=false ]
{
Thing topic Shelly_Down_front_left "Bulb Front left" @ "Downstairs" {
Channels:
Type string : Power "Switch" [ stateTopic="shellies/shellybulb-3CC48E/color/0", commandTopic="shellies/shellybulb-3CC48E/color/0/command" ]
Type string : Shelly_status "Status" [ stateTopic="shellies/shellybulb-3CC48E/color/0/status", commandTopic="shellies/shellybulb-3CC48E/color/0/set" ]
}
}
My corresponding items:
String Down_front_left_proxy "Proxy for Wall Downstairs Front left" {channel="mqtt:topic:mosquitto:Shelly_Down_front_left:Power"}
Switch Down_front_left "Wall Downstairs Front left" (gShelly_power, gShelly_lamps, gTwilightLightsON, gTwilightLightsOFF, gWeatherTwoLightsON, gWeatherTwoLightsOFF, gDownstairs,
gMorningLightsON, gMorningLightsOFF, gLights,gLightPanel,gEveningLightsON, gNightLightsOFF) // {channel="mqtt:topic:mosquitto:Shelly_Down_front_left:Power"}
String Down_front_left_status "Status bulb down front left" (gShelly_status) {channel="mqtt:topic:mosquitto:Shelly_Down_front_left:Shelly_status"}
Color Down_front_left_color "Wall Downstairs Front left Color" (gShelly_color, gShelly_lamps)
Switch Down_front_left_mode "bulb mode" (gShelly_mode, gShelly_lamps) //white or color
Dimmer Down_front_left_dim "Brightness" (gShelly_dim, gShelly_lamps)
Dimmer Down_front_left_coldim "Color Temperature" (gShelly_coldim, gShelly_lamps)
My Rules:
Maybe a quick remark: the code is not optimized and I am sure can be improved. I have four bulbs and I wrote one rule for each function that works for all four; however, it is relying on groups and naming schemes.
I left a lot of commented out login statements in here that I use to debug, you can delete as you wish.
A lot of the rules deals with parsing the JSON, and more importantly putting it back together.
You will need the JSON transform loaded in your system.
import org.eclipse.smarthome.model.script.ScriptServiceUtil
rule "shelly Sitemap to MQTT"
when
Member of gShelly_power received command
then
//logInfo("Sitemap to MQTT", "rule triggered, triggering item: " + triggeringItem.name.toString)
//logInfo("Sitemap to MQTT", "Item to be used: " + ScriptServiceUtil.getItemRegistry.getItem(triggeringItem.name.toString +"_proxy").name.toString)
Thread::sleep(10)
//val proxy = triggeringItem.name.toString +"_proxy"
//val testItem = ScriptServiceUtil.getItemRegistry.getItem(proxy)
if (triggeringItem.state == ON ) {//sendCommand(triggeringItem.name.toString +"_proxy", "on")
ScriptServiceUtil.getItemRegistry.getItem(triggeringItem.name.toString +"_proxy").sendCommand("on")
}
if (triggeringItem.state == OFF ) {
ScriptServiceUtil.getItemRegistry.getItem(triggeringItem.name.toString +"_proxy").sendCommand("off")
}
Thread::sleep(10) //wait for persistence to catch up
end
rule "HSB value to RGB color value"
when
Member of gShelly_color received command
then
if ((triggeringItem == NULL) || (triggeringItem == UNDEF))
return;
//logInfo("Colorpicker", "colorpicker" + Down_front_left_color.state.toString)
val hsbValue = triggeringItem.state as HSBType
val brightness = hsbValue.brightness.intValue
val redValue = ((((hsbValue.red.intValue * 255) / 100) *brightness) /100).toString
val greenValue = ((((hsbValue.green.intValue * 255) / 100) *brightness) /100).toString
val blueValue = ((((hsbValue.blue.intValue * 255) / 100) *brightness) /100).toString
val String new_color = "\"red\":" + redValue + ",\"green\":" + greenValue + ",\"blue\":" + blueValue
val trig_name_base = triggeringItem.name.toString.split("_color").get(0)
val trig_base = ScriptServiceUtil.getItemRegistry.getItem(trig_name_base)
val trig_status = ScriptServiceUtil.getItemRegistry.getItem(trig_name_base + "_status")
//logInfo("Colorpicker", "original status: "+trig_status.state.toString)
//logInfo("colorpicker", "This is the new color: "+ new_color)
var String new_status = trig_status.state.toString.split("\"red\"").get(0) + new_color + ",\"white\"" + trig_status.state.toString.split("\"white\"").get(1)
new_status = new_status.split("\"mode\"").get(0) + "\"mode\":" + "\"color\"" + ",\"red\"" + new_status.split("\"red\"").get(1)
//logInfo("colorpicker", "New Status: "+new_status)
trig_status.sendCommand(new_status)
trig_base.sendCommand(ON)
Thread::sleep(10) //wait for persistence to catch up
end
rule "set colortemp and brightness"
when
Member of gShelly_coldim received command or
Member of gShelly_dim received command
then
if ((triggeringItem == NULL) || (triggeringItem == UNDEF))
return;
Thread::sleep(10)
//logInfo("brightness", "Dimmer value is: " + Down_front_left_dim.state.toString)
//logInfo("brightness", "Colortemp is: " + Down_front_left_coldim.state.toString)
var String trig_name_base
if (triggeringItem.name.toString.contains("_coldim")) {
trig_name_base = triggeringItem.name.toString.split("_coldim").get(0)
}
else trig_name_base = triggeringItem.name.toString.split("_dim").get(0)
val trig_base = ScriptServiceUtil.getItemRegistry.getItem(trig_name_base)
val trig_status = ScriptServiceUtil.getItemRegistry.getItem(trig_name_base + "_status")
val trig_coldim = ScriptServiceUtil.getItemRegistry.getItem(trig_name_base + "_coldim")
val trig_dim = ScriptServiceUtil.getItemRegistry.getItem(trig_name_base + "_dim")
val color_temp = new DecimalType(trig_coldim.state.toString) * 35 +3000
//logInfo("brightness", "New colortemp is: " + color_temp.toString)
var String new_status = trig_status.state.toString.split("\"temp\"").get(0) + "\"temp\":" + color_temp.toString + ",\"brightness\":" + trig_dim.state.toString + ",\"effect\"" + trig_status.state.toString.split("\"effect\"").get(1)
new_status = new_status.split("\"mode\"").get(0) + "\"mode\":" + "\"white\"" + ",\"red\"" + new_status.split("\"red\"").get(1)
//logInfo("brightness", "old status is: " + Down_front_left_status.state.toString)
//logInfo("brightness", "new status is: " + new_status)
trig_status.sendCommand(new_status)
trig_base.sendCommand(ON)
Thread::sleep(10) //wait for persistence to catch up
end
rule "color or white mode"
when
Member of gShelly_mode received command
then
Thread::sleep(10)
//logInfo("CWmode", "triggeringItem: " + triggeringItem.name.toString)
val trig_name_base = triggeringItem.name.toString.split("_mode").get(0)
//logInfo("CWmode", "trig_name_base = " + trig_name_base)
val trig_base = ScriptServiceUtil.getItemRegistry.getItem(trig_name_base)
//logInfo("CWmode", "first one down")
val trig_status = ScriptServiceUtil.getItemRegistry.getItem(trig_name_base + "_status")
if (triggeringItem.state == OFF) {
trig_status.sendCommand(trig_status.state.toString.split("\"mode\"").get(0) + "\"mode\":" + "\"white\"" + ",\"red\"" + trig_status.state.toString.split("\"red\"").get(1))
trig_base.sendCommand(ON)
}
if (triggeringItem.state == ON) {
trig_status.sendCommand(trig_status.state.toString.split("\"mode\"").get(0) + "\"mode\":" + "\"color\"" + ",\"red\"" + trig_status.state.toString.split("\"red\"").get(1))
trig_base.sendCommand(ON)
}
Thread::sleep(10) //wait for persistence to catch up
end
rule "Update OH from Shellies"
when
Member of gShelly_status changed
then
Thread::sleep(10)
//logInfo("update", "triggering Item: " + triggeringItem.name.toString)
val trig_name_base = triggeringItem.name.toString.split("_status").get(0)
//logInfo("update", "trig_name_base = " + trig_name_base)
val trig_base = ScriptServiceUtil.getItemRegistry.getItem(trig_name_base)
val trig_coldim = ScriptServiceUtil.getItemRegistry.getItem(trig_name_base + "_coldim")
val trig_dim = ScriptServiceUtil.getItemRegistry.getItem(trig_name_base + "_dim")
val trig_mode = ScriptServiceUtil.getItemRegistry.getItem(trig_name_base + "_mode")
val trig_color = ScriptServiceUtil.getItemRegistry.getItem(trig_name_base + "_color")
val json = triggeringItem.state.toString
//logInfo("update", "json is: " + json)
//logInfo("update", "temp: " + transform("JSONPATH", "$.temp", json))
//logInfo("update", "Updating temp with: " + Math.round((Float::parseFloat(transform("JSONPATH", "$.temp", json))-3000)/35))
trig_coldim.postUpdate(Math.round((Float::parseFloat(transform("JSONPATH", "$.temp", json))-3000)/35))
trig_dim.postUpdate(Integer::parseInt(transform("JSONPATH", "$.brightness", json)))
if ("white" == transform("JSONPATH", "$.mode", json)) trig_mode.postUpdate(OFF)
if ("color" == transform("JSONPATH", "$.mode", json)) trig_mode.postUpdate(ON)
trig_color.postUpdate(HSBType.fromRGB(Integer::parseInt(transform("JSONPATH", "$.red", json)) , Integer::parseInt(transform("JSONPATH", "$.green", json)) , Integer::parseInt(transform("JSONPATH", "$.blue", json))))
if ("true" == transform("JSONPATH", "$.ison", json)) trig_base.postUpdate(ON) else trig_base.postUpdate(OFF)
end
As I said earlier, not pretty but it works for me.
and just for completeness, here my sitemap entries:
Switch item=Down_front_left
Switch item=Down_front_left_mode mappings=[ON="Color",OFF="White"]
Colorpicker item=Down_front_left_color visibility=[Down_front_left_mode==ON]
Slider item=Down_front_left_dim visibility=[Down_front_left_mode==OFF]
Slider item=Down_front_left_coldim visibility=[Down_front_left_mode==OFF]
Visibility is used to display colorpicker only in color mode and color temperature and intensity only in white mode.
Hope that helps