H801 with tasmota firmware, rule example with sliders, setpoint and colorpicker in openHAB 3

After spending a lot of time understanding things, items and rules I want to share a simple example how to create a basic set of rules for a H801 controller flashed with tasmota firmware in openHAB 3. (should work in openHAB 2 as well). Many examples from the source are taken from the community and put together here.

The focus of this example is the setup of items and rules. I recommend a basic knowledge about things, items, rules and sitemaps. Mandatory is a working Mosquitto (“mqtt”) server and a mqtt 2 (or higher) binding installed. You also need a “things” file to set up the mqtt bridge and the h801 thing with its channels. (There are more comfortable ways to create a thing in openHAB 3, but lets see how it works with a manual setup).

Let’s have a quick look on the things file:

Bridge mqtt:broker:openHAB3 "MQTT Bridge" [ host="192.168.1.15", secure=false, username="openhabian", password="openhabian" ]
{
    Thing topic h801 "H801" {
    Channels:
        Type switch : h801_power [ stateTopic="stat/h801_219/power", commandTopic="cmnd/h801_219/power", on="ON", off="OFF" ]
        Type string : h801_color [ stateTopic="stat/h801_219/color", commandTopic="cmnd/h801_219/color" ]
    }
}

First line: connect to your mqtt server by providing connect parameters and set up a mqtt bridge.
You are free to define your own bridge name (“openHAB3”) and label (“MQTT Bridge”).
(don’t use unsafe user and password :sweat_smile:)

Define your H801 controller as a “thing”, in this example with thing name “h801” and label “H801”. You can use a mqtt client like “MQTT Explorer” (for Windows) to explore your mqtt infrastructure. Much easier to explore the topics of your H801 controller (and others).

In this example I just defined the power switch and the color as channels. With a channel you can read the status (“stateTopic”) and write a new status (“commandTopic”) to the channel.

Now have a look to the items file:

// these are real h801 channels: 
Switch Led1_power "Power" <light> { channel="mqtt:topic:openHAB3:h801:h801_power" }
String Led1_color "Color" <colorlight> { channel="mqtt:topic:openHAB3:h801:h801_color" }

// colorpicker
Color  Led1_ctrl_colorpicker "Farbe" <colorlight>

// color slider
Number Led1_ctrl_red "Red [%.0f]" <colorlight>
Number Led1_ctrl_green "Green [%.0f]" <colorlight>
Number Led1_ctrl_blue "Blue [%.0f]" <colorlight>

// color setpoints
Number Led1_ctrl_red2 "Red [%.0f]" <colorlight>
Number Led1_ctrl_green2 "Green [%.0f]" <colorlight>
Number Led1_ctrl_blue2 "Blue [%.0f]" <colorlight>

The items file creates elements which are used in rules, but also shown in your sitemap.
Here I defined the two real H801 channels for power and color, and also some more elements I want to use in the sitemap to change the color settings of the H801. Here are three different ways to set a color: the great “colorpicker” from openHAB, simple sliders for setting red, green and blue component from 0 to 100 percent, and the third way: choosing red, green and blue from a selector (dropdown) field named “setpoint” in openHAB.

Colorpicker, sliders and setpoints are not a representation of a h801 channel, their functionality is fully defined with the following rule file:

import java.awt.Color
import java.util.List


// system startup rule
rule "System_started" 
when
    System started
then
	// initial set switch
	if (Led1_power.state === NULL) Led1_power.sendCommand(OFF)

	// set colorpicker
	if (Led1_color.state === NULL) Led1_color.sendCommand('0,0,0')

	// initial set slider
	if (Led1_ctrl_red.state === NULL) Led1_ctrl_red.postUpdate(0)
	if (Led1_ctrl_green.state === NULL) Led1_ctrl_green.postUpdate(0)
	if (Led1_ctrl_blue.state === NULL) Led1_ctrl_blue.postUpdate(0)

	// initial set setpoint
	if (Led1_ctrl_red2.state === NULL) Led1_ctrl_red2.postUpdate(0)
	if (Led1_ctrl_green2.state === NULL) Led1_ctrl_green2.postUpdate(0)
	if (Led1_ctrl_blue2.state === NULL) Led1_ctrl_blue2.postUpdate(0) 
end


// colorpicker rule: manages colorpicker changes
rule "Led1_Colorpicker"
when
	Item Led1_ctrl_colorpicker received command
then
	var Rn = 0
	var Gn = 0
	var Bn = 0
	var output = ''

	if (receivedCommand instanceof HSBType) {
		Rn = (receivedCommand.red * 2.55).intValue
		Gn = (receivedCommand.green * 2.55).intValue
		Bn = (receivedCommand.blue * 2.55).intValue
	} else if (receivedCommand == ON) {
		Rn = 255
		Gn = 255
		Bn = 255
	} else {
		Rn = 0
		Gn = 0
		Bn = 0
	}
	output = (Rn as Number).intValue + "," + (Gn as Number).intValue + "," + (Bn as Number).intValue

	// send command to h801 module to change color
	Led1_color.sendCommand(output)

	// switch off if all colors are 0
	if (Rn == 0 && Gn == 0 && Bn == 0) {
		Led1_power.sendCommand(OFF)
	} else {
		Led1_power.postUpdate(ON) // if a color is set, item is on, just update the switch
	}

	// update the setpoints
	Led1_ctrl_red2.postUpdate(Rn)
	Led1_ctrl_green2.postUpdate(Gn)
	Led1_ctrl_blue2.postUpdate(Bn)

	// update the sliders
	Rn = ((Rn as Number) / 2.55).intValue
	Gn = ((Gn as Number) / 2.55).intValue
	Bn = ((Bn as Number) / 2.55).intValue
	Led1_ctrl_red.postUpdate(Rn)
	Led1_ctrl_green.postUpdate(Gn)
	Led1_ctrl_blue.postUpdate(Bn)
end


// slider rule: manages slider changes
rule "Led1_Sliders"
when
	Item Led1_ctrl_red received command or
	Item Led1_ctrl_green received command or
	Item Led1_ctrl_blue received command
then
	var Rn = (Led1_ctrl_red.state as DecimalType).intValue
	var Gn = (Led1_ctrl_green.state as DecimalType).intValue
	var Bn = (Led1_ctrl_blue.state as DecimalType).intValue

	if (triggeringItemName == 'Led1_ctrl_red') Rn = receivedCommand
	if (triggeringItemName == 'Led1_ctrl_green') Gn = receivedCommand
	if (triggeringItemName == 'Led1_ctrl_blue') Bn = receivedCommand

	Rn = ((Rn as Number) * 2.55).intValue
	Gn = ((Gn as Number) * 2.55).intValue
	Bn = ((Bn as Number) * 2.55).intValue

	// send command to h801 module to change color
	var output = (Rn as Number).intValue + "," + (Gn as Number).intValue + "," + (Bn as Number).intValue
	Led1_color.sendCommand(output)

	// switch off if all colors are 0
	if (Rn == 0 && Gn == 0 && Bn == 0) {
		Led1_power.sendCommand(OFF)
	} else {
		Led1_power.postUpdate(ON) // if a color is set, item is on, just update the switch
	}

	// update the setpoints
	Led1_ctrl_red2.postUpdate(Rn)
	Led1_ctrl_green2.postUpdate(Gn)
	Led1_ctrl_blue2.postUpdate(Bn)

	// update the colorpicker
	val List<Float> hsb = Color.RGBtoHSB(Rn.intValue, Gn.intValue, Bn.intValue, null)
	var float hue = (hsb.get(0)*360).intValue
	var float sat = (hsb.get(1)*100).intValue
	var float bri = (hsb.get(2)*100).intValue
	var HSBType HSB = new HSBType(hue+","+sat+","+bri)
	Led1_ctrl_colorpicker.postUpdate(HSB)
end


// setpoint rule: manages setpoint changes
rule "Led1_setpoints"
when
	Item Led1_ctrl_red2 received command or
	Item Led1_ctrl_green2 received command or
	Item Led1_ctrl_blue2 received command
then
	var Rn = (Led1_ctrl_red2.state as DecimalType).intValue
	var Gn = (Led1_ctrl_green2.state as DecimalType).intValue
	var Bn = (Led1_ctrl_blue2.state as DecimalType).intValue

	if (triggeringItemName == 'Led1_ctrl_red2') Rn = receivedCommand
	if (triggeringItemName == 'Led1_ctrl_green2') Gn = receivedCommand
	if (triggeringItemName == 'Led1_ctrl_blue2') Bn = receivedCommand

	// send command to h801 module to change color
	var output = (Rn as Number).intValue + "," + (Gn as Number).intValue + "," + (Bn as Number).intValue
	Led1_color.sendCommand(output)

	// switch off if all colors are 0
	if (Rn == 0 && Gn == 0 && Bn == 0) {
		Led1_power.sendCommand(OFF)
	} else {
		Led1_power.postUpdate(ON) // if a color is set, item is on, just update the switch
	}

	// update the colorpicker
	val List<Float> hsb = Color.RGBtoHSB((Rn as Number).intValue, (Gn as Number).intValue, (Bn as Number).intValue, null)
	var float hue = (hsb.get(0)*360).intValue
	var float sat = (hsb.get(1)*100).intValue
	var float bri = (hsb.get(2)*100).intValue
	var HSBType HSB = new HSBType(hue+","+sat+","+bri)
	Led1_ctrl_colorpicker.postUpdate(HSB)

	// update the sliders
	Rn = ((Rn as Number) / 2.55).intValue
	Gn = ((Gn as Number) / 2.55).intValue
	Bn = ((Bn as Number) / 2.55).intValue
	Led1_ctrl_red.postUpdate(Rn)
	Led1_ctrl_green.postUpdate(Gn)
	Led1_ctrl_blue.postUpdate(Bn)

end

I will focus on the main functionality of those rules and not on coding details. Understanding those rules bases on understanding how the items used in sitemaps work. The only item directly connected to a H801 channel is the power switch. That means a power on/off command is directly passed to the H801 controller when the power switch in the sitemap has been operated, no rule is needed for this. Contrary to that a change in the colorpicker (or sliders/setpoints) has no effect to the H801, and that is what the rules are for.

The first rule (“System_started”) has a special functionality and is optional: after a reboot all items don’t have a “state” (they are NULL) and this rule just sets a initial state: switches the H801 off (“sendCommand”) and sets the other items to zero value (“postUpdate”). This is an important difference: sending a command to a mqtt item causes a hardware action (power, color…). But just posting a update to a item just updates the controls status in your sitemap, but does not trigger a hardware status change. This rule is optional, not necessarily needed for a working example. But keep the difference between sendCommand and postUpdate in mind!

Now focus on the other three rules. These rules handle changes on a specific sitemap element and trigger a “sendCommand” to the H801. They also update the state of the other elements, that means changing a color in the colorpicker also causes the same color is immediately set in all other color setting elements. Expressed in a simple way:

  • Changing the colorpicker sends the color command to the H801 and sets the choosen color to the sliders and the setpoint elements
  • Changing the color sliders sends the color command to the H801 and sets the choosen color to the colorpicker and the setpoint elements
  • Changing the color setpoints sends the color command to the H801 and sets the choosen color to the sliders and the colorpicker

So, if you decide you don’t need the setpoint elements, just remove the setpoint rule and the setpoint parts from the other rules. Finally, the sitemap file:

sitemap experimental label="H801 LED Controller" {  
	Frame label="Power" {
        Switch item=Led1_power
	}
    Frame label="RGB Colorpicker" {
        Colorpicker label="Colorpicker" item=Led1_ctrl_colorpicker
    }
    Frame label="RGB Slider" {
        Slider item=Led1_ctrl_red
        Slider item=Led1_ctrl_green
        Slider item=Led1_ctrl_blue
    }
    Frame label="RGB Setpoint" {
        Setpoint item=Led1_ctrl_red2 minValue=0 maxValue=255 step=1
        Setpoint item=Led1_ctrl_green2 minValue=0 maxValue=255 step=1
        Setpoint item=Led1_ctrl_blue2 minValue=0 maxValue=255 step=1
    }
}

Thank You for great description.

Please tell me is there any way to add H801 as thing and channels by GUI?
Or with those rgbw we have to do it just in text?

I have the same problem.
Did you solve it yet?