How to convert RGB to HSB and vice versa?

Hi friends, as the title, my question is how to convert RGB string to HSB string and vice versa in .rule file?
I created this .rules file to convert RGB to HSB values but didn’t success:

import java.awt.Color
var HSBType hsbValue
rule "RED DIMMER"
  when
    Item WIFI_RGB_RED_DIMMER received command
  then
		var int percent = 100
		if(WIFI_RGB_RED_DIMMER.state instanceof DecimalType) percent = (WIFI_RGB_RED_DIMMER.state as DecimalType).intValue 
		if(receivedCommand==INCREASE) percent = percent + 1
		if(receivedCommand==DECREASE) percent = percent - 1
		if(percent<0)   percent = 0
		if(percent>100) percent = 100
		redValue=percent
		var Color color=new Color(redValue,greenValue,blueValue)
		hsbValue = new HSBType(color.toString)
		sendCommand(WIFI_RGB,hsbValue)
end

my purpose is that I want to whenever I adjust the slider item WIFI_RGB_RED_DIMMER then the color item WIFI_RGB must change its color respectively. I am now constantly receive this error:

 Rule 'RED DIMMER': An error occured during the script execution: Could not invoke constructor: java.awt.Color.Color(int,int,int)

Any help? I’d be very appreciated!

I don’t see where you’re assigning/declaring redValue, greenValue, and blueValue. Did you omit that from your posting, or is it missing from your rule too?

Also, color.toString returns something like this: java.awt.Color[r=100,g=75,b=55], which I don’t think is accceptable in the HSBType constructor.

Here’s a quick test and its output (running under OH2 2.0):

		var int percent = 100
		var redValue = percent
		var greenValue = 75
		var blueValue = 55
		var Color color=new Color(redValue,greenValue,blueValue)
09:15:05.035 [WARN ] [clipse.smarthome.model.script.color!] - Color test...
09:15:05.036 [WARN ] [clipse.smarthome.model.script.color!] - Color: java.awt.Color[r=100,g=75,b=55]

This may also help:

Oh I forgot to post those variables from my post.
They do exist in my rule file
I declared outside the rule "Red DIMMER"
Then I moved it inside the rule, like this:

rule "RED DIMMER"
  when
    Item WIFI_RGB_RED_DIMMER received command
  then
		var int percent = 100
		if(WIFI_RGB_RED_DIMMER.state instanceof DecimalType) percent = (WIFI_RGB_RED_DIMMER.state as DecimalType).intValue 
		if(receivedCommand==INCREASE) percent = percent + 1
		if(receivedCommand==DECREASE) percent = percent - 1
		if(percent<0)   percent = 0
		if(percent>100) percent = 100
		var redValue=percent
		var greenValue = 75
        var blueValue = 55
		var Color color=new Color(redValue,greenValue,blueValue)
		var HSBType hsbValue = new HSBType(color.toString)
		sendCommand(WIFI_RGB,hsbValue)
		//postUpdate(WIFI_RGB_RED_DIMMER, percent);
end

There is still an error in the event log:

21:28:00.596 [ERROR] [.script.engine.ScriptExecutionThread] - Rule 'RED DIMMER': null

What wrong with this?

These should probably include the type:

    var int redValue=percent
    var int greenValue = 75
    var int blueValue = 55

@marcel_erkel
OK, I changed:

rule "RED DIMMER"
  when
    Item WIFI_RGB_RED received command
  then
		var int percent = 0
		if(WIFI_RGB_RED.state instanceof DecimalType) percent = (WIFI_RGB_RED.state as DecimalType).intValue 
		if(receivedCommand==INCREASE) percent = percent + 1
		if(receivedCommand==DECREASE) percent = percent - 1
		if(percent<0)   percent = 0
		if(percent>100) percent = 100
		var int red=percent
        var int green= 75
        var int blue= 55
        var Color color=new Color(red,green,blue)
        var HSBType hsbValue = new HSBType(color.toString)
        sendCommand(WIFI_RGB,hsbValue)
        postUpdate(WIFI_RGB_RED, red);
end

But the error still persist:

21:42:41.406 [WARN ] [b.core.events.EventPublisherDelegate] - given new state is NULL, couldn't post update for 'WIFI_RGB_RED'
21:42:41.411 [ERROR] [.script.engine.ScriptExecutionThread] - Rule 'RED DIMMER': null
21:43:32.515 [INFO ] [marthome.event.ItemStateChangedEvent] - Date changed from 2017-07-09T21:42:32.538+0700 to 2017-07-09T21:43:32.514+0700

As previously stated, this is never going to work as an input to the HSBType constructor:

It needs a string in the form “val1,val2,val3”, where each is a string representation of an acceptable value for H, S and B.

How about this:

Add the following import:

import java.util.List
rule "RED DIMMER"
  when
    Item WIFI_RGB_RED received command
  then
	var int percent = 0
	if(WIFI_RGB_RED.state instanceof DecimalType) percent = (WIFI_RGB_RED.state as DecimalType).intValue 
	if(receivedCommand==INCREASE) percent = percent + 1
	if(receivedCommand==DECREASE) percent = percent - 1
	if(percent<0)   percent = 0
	if(percent>100) percent = 100
	var int red=percent
	var int green= 75
	var int blue= 55

	val List<Float> hsb = Color.RGBtoHSB(red,green,blue,null)
	val String hsbString = hsb.get(0) + "," + hsb.get(1) + "," + hsb.get(2)

	var HSBType hsbValue = new HSBType(hsbString)
        sendCommand(WIFI_RGB,hsbValue)
        postUpdate(WIFI_RGB_RED, red);
end

The Color.RGBtoHSB() method is a static method of the Color class. It returns an array of type float. The problem is that the DSL used by openHAB apparently does not handle arrays. However, it does support to automatically convert them to a List so that’s why this val List<Float> hsb = Color.RGBtoHSB(red,green,blue,null) actually works.
Next a String is created as indicated by @namraccr.
I don’t have any color lights so I can’t test, but when executing the rule and printing out the hsbString it looked ok to me.

For completeness, here’s my test code which includes the conversion from RGB to HSB and from HSB to RGB:

Required imports

import java.awt.Color
import java.util.List
	// from RGB to HSB
	val List<Float> hsb = Color.RGBtoHSB(250,150,50,null)
	val float hue = hsb.get(0)
	val float saturation = hsb.get(1)
	val float brightness = hsb.get(2)
	val String hsbString = hue + "," + saturation + "," + brightness
 
	logInfo("scene.rules", "H: " + hue)
	logInfo("scene.rules", "S: " + saturation)
	logInfo("scene.rules", "B: " + brightness)
	logInfo("scene.rules", "HSB: " + hsbString)

	// from HSB to RGB
	val int rgb = Color.HSBtoRGB(hue, saturation, brightness)
	val color = new Color(rgb)

	logInfo("scene.rules", "R: " + color.getRed())
	logInfo("scene.rules", "G: " + color.getGreen())
	logInfo("scene.rules", "B: " + color.getBlue())

You can use this to convert into HSB:

hsbValue = HSBType.fromRGB(redValue,greenValue,blueValue)
2 Likes