Integrate Shelly RGBW2 with MQTT in openHab

Dear community!

A few days ago I got my new Shelly RGBW2 and fighted to get it working with the MQTT binding in openHAB 2.4

Here the result! I hope its helpful for others. But I am also interested to get feedback, if others solved it in more simple way.

The MQTT API can be found here: RGBW2 MQTT API

After experimenting around, I finally created state topics for all parameters in the JSON string send by
shellies/shellyrgbw2-5A36B7/color/0/status
and use the command
shellies/shellyrgbw2-/color/0/set
to change the settings. But this mean, I need to build the complete JSON string always completly.

So, I created the following thing:

    Thing topic WohnzimmerTisch "WohnzimmerTisch" @ "Wohnzimmer" {
        Channels:
            Type string : ison      "IsOn"                  [ stateTopic="shellies/shellyrgbw2-5A36B7/color/0/status", transformationPattern="JSONPATH:$.ison"]
            Type string : overpower "OverPower"             [ stateTopic="shellies/shellyrgbw2-5A36B7/color/0/status", transformationPattern="JSONPATH:$.overpower"]
            Type string : mode      "Mode"                  [ stateTopic="shellies/shellyrgbw2-5A36B7/color/0/status", transformationPattern="JSONPATH:$.mode"]
            Type number : gain      "Gain"                  [ stateTopic="shellies/shellyrgbw2-5A36B7/color/0/status", transformationPattern="JSONPATH:$.gain"]
            Type number : red       "Red"                   [ stateTopic="shellies/shellyrgbw2-5A36B7/color/0/status", transformationPattern="JSONPATH:$.red"]
            Type number : green     "Green"                 [ stateTopic="shellies/shellyrgbw2-5A36B7/color/0/status", transformationPattern="JSONPATH:$.green"]
            Type number : blue      "Blue"                  [ stateTopic="shellies/shellyrgbw2-5A36B7/color/0/status", transformationPattern="JSONPATH:$.blue"]
            Type number : white     "White"                 [ stateTopic="shellies/shellyrgbw2-5A36B7/color/0/status", transformationPattern="JSONPATH:$.white"]
            Type number : effect    "Effect"                [ stateTopic="shellies/shellyrgbw2-5A36B7/color/0/status", transformationPattern="JSONPATH:$.effect"]
            Type number : power     "Power"                 [ stateTopic="shellies/shellyrgbw2-5A36B7/color/0/status", transformationPattern="JSONPATH:$.power"]
            Type string : cmd       "Command"               [ commandTopic="shellies/shellyrgbw2-5A36B7/color/0/set" ]
    }

To have all the values available, I connected the following items to this channels:

//
// Wohnzimmertisch
//
// Status
Number Gain_WohnzimmerTisch  "Wohnzimmertisch [%d %%]" { channel="mqtt:topic:mosquitto:WohnzimmerTisch:gain" }
String IsOn_WohnzimmerTisch    "Wohnzimmertisch [%s]" { channel="mqtt:topic:mosquitto:WohnzimmerTisch:ison" }
String OverPower_WohnzimmerTisch    "Wohnzimmertischoverpower [%s]" { channel="mqtt:topic:mosquitto:WohnzimmerTisch:overpower" }
String Mode_WohnzimmerTisch    "Wohnzimmertischmode [%s]" { channel="mqtt:topic:mosquitto:WohnzimmerTisch:mode" }
Number Effect_WohnzimmerTisch    "Wohnzimmertischeffekt [%s]" { channel="mqtt:topic:mosquitto:WohnzimmerTisch:effect" }
Number Red_WohnzimmerTisch    "Wohnzimmertisch rot [%d]" { channel="mqtt:topic:mosquitto:WohnzimmerTisch:red" }
Number Green_WohnzimmerTisch    "Wohnzimmertisch blau [%d]" { channel="mqtt:topic:mosquitto:WohnzimmerTisch:green" }
Number Blue_WohnzimmerTisch    "Wohnzimmertisch grün [%d]" { channel="mqtt:topic:mosquitto:WohnzimmerTisch:blue" }
Number White_WohnzimmerTisch    "Wohnzimmertisch weiss [%d]" { channel="mqtt:topic:mosquitto:WohnzimmerTisch:white" }
Number Power_WohnzimmerTisch    "Wohnzimmertischverbrauch [%.2f W]" { channel="mqtt:topic:mosquitto:WohnzimmerTisch:power" }
String Command_WohnzimmerTisch    "Wohnzimmertischkommando [%s]" { channel="mqtt:topic:mosquitto:WohnzimmerTisch:cmd" }

To control the brightness and color with rules, I created additionally a Color and Dimmer item

// Control
Dimmer Dimmer_WohnzimmerTisch  "Wohnzimmertisch [%d %%]" [ "Lighting" ] 
Color Color_Wohnzimmertisch	"Wohnzimmer Tisch" <colorlight> (gWohnzimmer)

For changing the color, I wrote a script which reacts on changes of the Color item.
It extracts the new color and builds a complete JSON string which is than send to the command item.

rule "Set Shelly RGBW2 LEDs from Color item using ColorPicker"
when
    Item Color_Wohnzimmertisch changed
then
	var jsonString = "{"
	val int red = (Color_Wohnzimmertisch.state as HSBType).red.intValue
	val int green = (Color_Wohnzimmertisch.state as HSBType).green.intValue
	val int blue = (Color_Wohnzimmertisch.state as HSBType).blue.intValue
 	var int b = (Color_Wohnzimmertisch.state as HSBType).getBrightness.intValue

	if (b > 0)
		jsonString = jsonString + "\"turn\":" + "\"on\""
	else
		jsonString = jsonString + "\"turn\":" + "\"off\""

	jsonString = jsonString + ",\"red\":" + red.toString
	jsonString = jsonString + ",\"green\":" + green.toString
	jsonString = jsonString + ",\"blue\":" + blue.toString
	jsonString = jsonString + ",\"white\":" + White_WohnzimmerTisch.state.toString
	jsonString = jsonString + ",\"gain\":" + b.toString
	jsonString = jsonString + ",\"effect\":" + Effect_WohnzimmerTisch.state.toString
	jsonString = jsonString + "}"
	sendCommand(Command_WohnzimmerTisch, jsonString)
 	//logInfo("LED_RGB_Values.rules", "R:" + red + " G:" + green + " B:" + blue)
 	//logInfo("LED_RGB_Values.rules", "Brightness:" + b)
end

Finally I created two scripts for the Dimmer item. One if the dimmer value is changed by openHAB and one if the dimmer value is changes by the Shelly App from outside:

/* Shelly RGBW2 Dimmer update */
rule "WohnzimmerTisch_DimEvent"
when
	Item Dimmer_WohnzimmerTisch changed
then
	var jsonString = "{"
	val Number dimValue = Dimmer_WohnzimmerTisch.state as DecimalType;
	
	if (dimValue > 0)
			jsonString = jsonString + "\"turn\":" + "\"on\""
	else
			jsonString = jsonString + "\"turn\":" + "\"off\""
	

	jsonString = jsonString + ",\"red\":" + Red_WohnzimmerTisch.state.toString
	jsonString = jsonString + ",\"green\":" + Green_WohnzimmerTisch.state.toString
	jsonString = jsonString + ",\"blue\":" + Blue_WohnzimmerTisch.state.toString
	jsonString = jsonString + ",\"white\":" + White_WohnzimmerTisch.state.toString
	jsonString = jsonString + ",\"gain\":" + dimValue.toString
	jsonString = jsonString + ",\"effect\":" + Effect_WohnzimmerTisch.state.toString
	jsonString = jsonString + "}"
	sendCommand(Command_WohnzimmerTisch, jsonString)
end

/* Shelly RGBW2 value update */
rule "WohnzimmerTisch_GainEvent"
when
	Item Gain_WohnzimmerTisch changed
then
	val Number dimValue = Gain_WohnzimmerTisch.state as DecimalType;
	sendCommand(Dimmer_WohnzimmerTisch, dimValue)
end

It works fine now!
I can control the brightness and state over Alexa (hue emulation) and with sitemap:

Slider item=Dimmer_WohnzimmerTisch switchSupport icon="slider"
Colorpicker item=Color_Wohnzimmertisch icon="colorpicker"
Text item=Power_WohnzimmerTisch icon=""

RGBW2Sitemap

also HABpanel works fine.

But I think, it is a lot of code for such a simple thing.
I also did not mange to update the Color Item in OpenHAB when the color is changed over the Shelly app. I did’t find any way to update only the rgb values of the color item. Does anyone have a hint?

This code is done for a rgb led stripe. For rgbw it must be adapted. Hope it helps someone…

4 Likes

Because shelly uses json, that is indeed a lot of code required on openHABs side.
Shelly probably deserves its own protocol support in the MQTT binding.

:slight_smile: Possible…

@David_Graeff
That would on top of the homie and HASS convention.
There is also Tasmota, EspEasy and others.
Would some sort of a binding plugin concept make sense?

I observe a strange output in the log file when I send the JSON string to the String command item.
It shows always a strange “predicted valule”:

Item 'Command_WohnzimmerTisch' received command {"turn":"on","red":0,"green":1,"blue":100,"white":0,"gain":40,"effect":0}
Command_WohnzimmerTisch predicted to become {"turn":"on","red":1,"green":3,"blue":1,"white":0,"gain":3,"effect":0}

The receive command value is what I send. Where is the predicted value coming from? Does anyone have an idea?

Nobody an idea where this strange “predicted to become” value comes from?

It’s new logging from OH. Started with 2.4. I think.
Doesn’t change any behaviour.

It’s coming from the item auto-update service. Since 2.4 (or 2.3, not sure) you can tell OH if you want your item to be changed to the desired value immediately (like in older OH versions) or if the value is left unchanged and only a command is send (which in turn makes the device respond and update the item).

I don’t think that extensive logging was the correct choice here, the service could as well just operate silently.

Thanks Guys, but yes, I noticed that this logging is new in OH 2.4. I am only confused of the totally stupid content ot the predicted value .
In other cases the contend make sense. But here it has nothing to do with what I want to switch. I only ask, because sometimes the RGBW switch is not reacting correctly. Wondering if this has to do with this strange log string.

Hi,
I’m trying to interface OH2 with a Shelly RGBW2 in white mode without success.
I’ve modified Your files to match the white mode parameters (brightness and on/ff) for channel 3 but with no success at all.
If possible could be a good plus to have a feedback of the status of the device (brightness value and on/off status) so if the shelly is turned on by an external switch in OH is on.
A plus could be to have a device online status control that enable or disable panel controls…

I’m a total noob in OH, so help is very needed.

The opensource milight hub is very similar and uses json via MQTT, so feel free to look and use this binding source code as an example. I also attempted doing it with rules which are also posted on this forum and look similar to yours.

I know ppl will recommend creating a thing in the MQTT binding, but that was not around when I created the binding and I wanted to create more in depth features like halogen emulation and other features which was better in its own binding.

It probably is a good idea to come up with a better way to handle JSON as it is very simple in home assistant to handle it so a lot of projects go that direction which creates another hurdle for Openhab especially when they use 0-255 values and we need 0-100 values.

Hey Diego, in white mode you need to rework the scripts for shure…
Did you consider the different rest API for white mode here:

https://shelly-api-docs.shelly.cloud/#rgbw2-mqtt

I would create dimmer items for each channel and than also a script for each channel to build and send the rest command strings like described abouve…

1 Like

Thank you,
I’ve tried to rework your work for command the white mode using API’s (IsOn & Brightness are the only parameters) but with no luck for now…
Now I would try to create things in PaperUI via JSONPATH tranformation and see in works…

Was a lot of try and error also in my case… Post your results!

Just for clarify in your OP, the codes have to be saved in:

1 code (Thing topic WohnzimmerTisch "WohnzimmerTisch" @ "Wohnzimmer"....): .things file
2 code (Number Gain_WohnzimmerTisch "Wohnzimmertisch [%d %%]"...): .things file
3 code (Dimmer Dimmer_WohnzimmerTisch "Wohnzimmertisch [%d %%]" [ "Lighting" ]...): .items file
4 code (rule "Set Shelly RGBW2 LEDs from Color item using ColorPicker"...): .script file
5 code (/* Shelly RGBW2 Dimmer update */...): .script file
6 code (/* Shelly RGBW2 value update */...): .script file
7 code (Slider item=Dimmer_WohnzimmerTisch switchSupport icon="slider"...): .items file

Right?

Number in also items and rules in 4,5,6 in .rules other wise it will not work!

1 Like

Hi,
I’ve modified your files , but I can’t see controls in PaperUI Controls tab nor BasicUI or ClassicUI.
I’ve read API’s doc a lot of time but I don’t understand at all the JSon string…
https://shelly-api-docs.shelly.cloud/?shell#rgbw2

I’m a bit confused…

These are my files:

Sottopensile .things:

    Thing topic Sottopensile "Sottopensile" @ "Soggiorno" {
    Channels:
        Type string : ison        "IsOn"              [ stateTopic="shellies/shellyrgbw2-661B1B/white/3/status", transformationPattern="JSONPATH:$.ison"]
        Type number : brightness  "Brightness"        [ stateTopic="shellies/shellyrgbw2-661B1B/white/3/status", transformationPattern="JSONPATH:$.brightness"]
        Type number : power       "Power"             [ stateTopic="shellies/shellyrgbw2-661B1B/white/3/status", transformationPattern="JSONPATH:$.power"]
        Type string : cmd         "Command"           [ commandTopic="shellies/shellyrgbw2-661B1B/white/3/set" ]
}

Sottopensile_Status .items:

//
// Sottopensile
//
// Status
Number Brightness_BL  "Sottopensile [%d %%]" { channel="mqtt:topic:mosquitto:Sottopensile:brightness" }
Number Power    "Consumo [%.2f W]" { channel="mqtt:topic:mosquitto:Sottopensile:power" }
String IsOn_BL    "Sottopensile [%s]" { channel="mqtt:topic:mosquitto:Sottopensile:ison" }
String Command_BL    "Comando [%s]" { channel="mqtt:topic:mosquitto:Sottopensile:cmd" }

Dimmer_BL .items:

// Controllo
Dimmer Dimmer_BL  "Sottopensile [%d %%]" [ "Intensita" ]

Dimmer_BL .rules:

/* Shelly RGBW2 Dimmer update */
rule "Sottopensile_DimEvent"
when
	Item Dimmer_BL changed
then
	var jsonString = "{"
	val Number dimValue = Dimmer_BL.state as DecimalType;
	jsonString = jsonString + ",\"brightness\":" + dimValue.toString
	
	if (dimValue > 0)
			jsonString = jsonString + "\"turn\":" + "\"on\""
	else
			jsonString = jsonString + "\"turn\":" + "\"off\""
	
	jsonString = jsonString + "}"
	sendCommand(Command_BL, jsonString)
end

/* Shelly RGBW2 value update */
rule "BL_BrightEvent"
when
	Item Brightness_BL changed
then
	val Number dimValue = Brightness_BL.state as DecimalType;
	sendCommand(Dimmer_BL, dimValue)
end

Controlli_BL .items:

Slider item=Dimmer_BL switchSupport icon="slider"
Text item=Power icon=""

Can You help me, please?

Hi Diego, sorry for late response. May be to late!
But to see something in basic ui you must put slider and text in *.sitemap files

Hi guys, please check out this thread: Shelly Binding
I’m working on an optimized binding for the complete Shelly series of devices. Testers welcome :slight_smile:

I have do it, with Javascript.

My item : Color grill_eg_terasse “Grill” (geg) {mqtt="<[sari:shellies/shellyrgbw2-B0983A/color/0/status:state:JS(rgbjson_hsv.js)],>[sari:shellies/shellyrgbw2-B0983A/color/0/command:command:ON:MAP(shellyonoff.map)],>[sari:shellies/shellyrgbw2-B0983A/color/0/command:command:OFF:MAP(shellyonoff.map)],>[sari:shellies/shellyrgbw2-B0983A/color/0/set:command:*:JS(hsv_rgbjson.js)]"}

rgbjson_hsv.js

// Wrap everything in a function
(function(i) {
var min, max, delta, r, g, b, h, s, v, v1, w, erg=“falsch”;

// r,g,b-Werte zwischen 0 und 1
// h = [0,360], s = [0,1], v = [0,1]
// Wenn s == 0, dann h = -1 (undefined)

obj=JSON.parse(i);
r=Number(obj.red)/255;
g=Number(obj.green)/255;
b=Number(obj.blue)/255;
w=Number(obj.white)
v1=Number(obj.gain)
min=g; if (r<min) {min=r;} if (b<min) {min=b;}
max=g; if (r>max) {max=r;} if (b>max) {max=b;}
delta = max - min;
if( max != 0 ) s = delta / max;
else { s = 0; h = 0; } // r = g = b = 0
if (max == min) { h = 0; s = 0; } // hier ist alles Grau
if (s>0)
{
if( r == max ) { h = ( g - b ) / delta; } // zwischen Gelb und Magenta
else if( g == max ) { h = 2 + ( b - r ) / delta; } // zwischen Cyan und Gelb
else { h = 4.0 + ( r - g ) / delta;} // zwischen Magenta und Zyan
h *= 60; // degrees
if( h < 0 ) h += 360;
}

erg=Number(h)+","+Number(s*100)+","+Number(v1);
//erg=Number(w);
return erg;
})(input)
// input variable contains data passed by openhab

and hsv_rgbjson.js

/ Wrap everything in a function
(function(i) {
var p1, p2, hi, f, p, q, t, r, g, b, h, s, v, v1, w, erg=“falsch”;

if ((i=="ON") || (i=="OFF")) {erg="";}
	
else
	{
	p1= i.indexOf(",");
	p2= i.indexOf(",",p1+1);
	h=Number(i.substring(0,p1));
	s=Number(i.substring(p1+1,p2));
	v1=Number(i.substring(p2+1,99));
	s=s/100;
	//v=v1/100;
	v=1;
	hi=Math.floor(h/60)
	f=(h/60-hi);
	p=v*(1-s);
	q=v*(1-s*f);
	t=v*(1-s*(1-f));
	if ((hi==0) || (hi==6)) {r=v; g=t; b=p; }
	else if (hi==1) {r=q; g=v; b=p;} 
	else if (hi==2) {r=p; g=v; b=t;}
	else if (hi==3) {r=p; g=q; b=v;}
	else if (hi==4) {r=t; g=p; b=v;} 
	else {r=v; g=p; b=q;}
	w=0;
	if (s<0.5) {w=(0.5-s)*2*v1/100;}
	erg="{\"red\":" + (r*255) + ",\"green\":" + (g*255) + ",\"blue\":" + (b*255) + ",\"white\":" + (w*255) + ",\"gain\":" + (v1) + "}";
	}

return erg;

})(input)
// input variable contains data passed by openhab

the onoff maps only convert upper lower case

After a saturation below 50% , I start the White Led also. At Saturation 0 the White is 100%. So I dont need so mutch Items or Swtiches to Controll the RGBW.

I know its not perfect, but it works for me.