Writing a simple rule with temperature Item

Hello,
I am new to this community and this is my first question. I managed to configure a couple of Xiaomi/Aqara temeprature and humidity sensors and a Sonoff 4CH so that I can see them in Control page of Paper UI. I can also successfully set the status of Sonoff outputs by sending MQTT commands. Now I would like to write a simple rule to drive the outputs of Sonoff based on temperature readings.
I am stuck in the beginning, since there is something wrong in my simple rule. The rule should be self explaining. What happens is that the “if” statement always evaluates to true, even when “tempAqara1” is higher than “threshold”.

2020-09-01 22:03:28.216 [INFO ] [script.Aqara Temp-Humidity Sensor #1] - Temperature update received: 23.57 °C > 28.5°C

2020-09-01 22:08:09.718 [INFO ] [script.Aqara Temp-Humidity Sensor #1] - Temperature update received: 23.63 °C > 20.0°C

Can you help me find out what’s wrong?

My rule code as defined in file “ch1_sensor1.rules”:

var
threshold = 28.5 as Number

rule "ch1_sensor1"
when
	Item Aqara1_Temperature received update
then
	var
		tempAqara1 = Aqara1_Temperature.state as Number

	if (tempAqara1 < threshold)
	{
		logInfo("Aqara Temp-Humidity Sensor #1", "Temperature update received: " + Aqara1_Temperature.state.toString + " < " + threshold.toString + "°C")	
	}
	else
	{
		logInfo("Aqara Temp-Humidity Sensor #1", "Temperature update received: " + Aqara1_Temperature.state.toString + " > " + threshold.toString + "°C")
	}
end

Platform information:
Hardware: Raspberry Pi 4 4GB RAM
OS: Openhabian
openHAB version: 2.5.7-1

Welcome,

Try changing the loginfo to display the variables used in the “if” statement, e.g.

logInfo("Aqara Temp-Humidity Sensor #1", "Temperature update received: " + tempAqara1.toString + " < " + threshold.toString)

It looks like your Aqara1_Temperature item includes a unit of measurement. Have a look at this very recently revived thread on using IF with those types of items:

In short, I think you want to do something like:

if ( Aqara1_Temperature.state < 28.5 | "°C" )

or

if ((Aqara1_Temperature.state as Number).floatValue < 28.5 )

(I would recommend getting your rule to work with base components, before moving to using var and val…)

Thank you JimH for quick reply. I followed your suggestion with no improvement:

2020-09-01 22:47:33.763 [INFO ] [script.Aqara Temp-Humidity Sensor #1] - Temperature update received: 23.59 °C > 28.0°C

Edit: my first post was wrong. “if” statement always evaluates to “false”.

Thank you @hafniumzinc, it worked!

Now it evaluates to “true”:
2020-09-01 22:50:24.842 [INFO ] [script.Aqara Temp-Humidity Sensor #1] - Temperature update received: 23.97 °C < 28.0°C

This is my code now (meanwhile I added the MQTT commands to drive the output relays):

var
	threshold = 28.0 as Number

rule "ch1_sensor1"
when
	Item Aqara1_Temperature received update
then
	var tempAqara1 = Aqara1_Temperature.state as Number
	val mqttActions = getActions("mqtt", "mqtt:broker:e89fd387")
	
	if (tempAqara1.floatValue < threshold)
	{
		logInfo("Aqara Temp-Humidity Sensor #1", "Temperature update received: " + tempAqara1.toString + " < " + threshold.toString + "°C")	
		//publish("mqtt:broker:e89fd387", "house/cmnd/sonoffCH1to4/POWER1","ON")
  		mqttActions.publishMQTT("house/cmnd/sonoffCH1to4/POWER1","ON")
		logInfo("sonoffCH1to4", "Switch ON command sent to house/cmnd/sonoffCH1to4/POWER1")
	}
	else
	{
		logInfo("Aqara Temp-Humidity Sensor #1", "Temperature update received: " + tempAqara1.toString + " > " + threshold.toString + "°C")
		//publish("mqtt:broker:e89fd387", "house/cmnd/sonoffCH1to4/POWER1","OFF")
		mqttActions.publishMQTT("house/cmnd/sonoffCH1to4/POWER1","OFF")
		logInfo("sonoffCH1to4", "Switch OFF command sent to house/cmnd/sonoffCH1to4/POWER1")
	}
end

What happens if you try

var threshold = 28.5
//Or 28,5

rule "ch1_sensor1"
when
	Item Aqara1_Temperature received update
then
	if (Aqara1_Temperature.state < threshold)
	{
		logInfo("Aqara Temp-Humidity Sensor #1", "Temperature update received: " + Aqara1_Temperature.state.toString + " < " + threshold.toString + "°C")	
	}
	else
	{
		logInfo("Aqara Temp-Humidity Sensor #1", "Temperature update received: " + Aqara1_Temperature.state.toString + " > " + threshold.toString + "°C")
	}
end

This is how I do number comparison
For example:

rule "Ist es draußen wärmer?"
when
    Item AlexaGereate_IstEsDraussenWaermer received command
then
    logInfo("Rule started", "\"AlexaGeraete_Diverses.rules: Ist es draußen wärmer?\"")
    var DeltaT = Math::abs((Heizung_DeltaT.state as Number).floatValue) //Zahl zum String machen
    var DeltaT_String = DeltaT.toString().substring(0,3).replace('.',',') //String zuschneiden und formatieren
    var Innentemperatur = Heizung_AktuelleTemperatur.state.toString.substring(0,4).replace('.',',')
    if ( DeltaT < 0.3 ) //Gleich warm
    {
	AmazonEcho_Maze_TextToSpeech.sendCommand("Es hat drinnen " + Innentemperatur + " Grad und ist damit gleich warm wie draußen")
    }
    else if ( Heizung_DeltaT.state > 0 ) //Drinnen kälter
    {
        AmazonEcho_Maze_TextToSpeech.sendCommand("Es ist draußen um " + DeltaT_String + " Grad wärmer als die Innentemperatur, welche " + Innentemperatur + " Grad beträgt")
    }
    else //Drinnen wärmer
    {
        AmazonEcho_Maze_TextToSpeech.sendCommand("Es hat drinnen " + Innentemperatur + " Grad und ist damit um " + DeltaT_String + " Grad wärmer als draußen")
    }
end

Great!

Any reason not to attach your MQTT channels to Items, and then control those Items (ON/OFF) instead?

It would mean you could get rid of a bit of your code, down to something like:

var threshold = 28.0 as Number

rule "ch1_sensor1"
when
	Item Aqara1_Temperature received update
then
	var tempAqara1 = Aqara1_Temperature.state as Number
	
	if (tempAqara1.floatValue < threshold)
	{
		logInfo("Aqara Temp-Humidity Sensor #1", "Temperature update received: " + tempAqara1.toString + " < " + threshold.toString + "°C")
        sendCommand("sRelay1", "ON")
	}
	else
	{
		logInfo("Aqara Temp-Humidity Sensor #1", "Temperature update received: " + tempAqara1.toString + " > " + threshold.toString + "°C")
        sendCommand("sRelay1", "OFF")
	}
end

This assumes attaching the appropriate channels to an Item called sRelay1. Not too long ago I (tried to) help someone else setup their 4 channel Sonoff:

Thank you for all suggestions. “.floatValue” was the key to success. I will anyway read each pieace of your rules, since I can find tips for improving mine.

@Felix_Schneider I assigned solution to @hafniumzinc, since it was first successfull suggestion.
@hafniumzinc: I accept your suggestion to define an Item to clean up the code. I will work on it.

You can just compare apples to apples

var threshold = 28.5  | °C   // this creates a QuantityType

...
if (tempAqara1.state < threshold) {   // this now compares similar types
...
1 Like

Perhaps you needed to refresh the log file? The log timestamp in you second post is before the log timestamp in the first post.