[SOLVED] Subtract / Compare Number:Temperature items?

Hello everyone! Hope I can get some help with a problem…
Running openHABian on a Raspberry Pi 3B

What I’m trying to accomplish…

  • The ability to control multiple HVAC systems with one set of rules.

ITEMS

Group AC
Group Heat
Group HVAC_Control
Group Lockouts

Number:Temperature HVAC_Temp_1 "Living Temp [%.0f °F]" <temperature> (AC,Heat)  { channel="onewiregpio:sensor:living:temperature" }

//-----Proxy items used in rules-----//
Switch AC_Sys_1 (AC, HVAC_Control)
Switch Heat_Sys_1 (Heat, HVAC_Control)
String Fan_Sys_1
Switch SysStatus_AC_1
Switch SysStatus_Heat_1
Switch Lockout_AC_1 (Lockouts)
Switch Lockout_Heat_1 (Lockouts)

//-----Relay Items used to turn on/off air handler-----//
Switch  AC_Relay_1   {gpio="pin:27 activelow:yes initialValue:high"}
Switch  Heat_Relay_1 {gpio="pin:21 activelow:yes initialValue:high"}
Switch  Fan_Relay_1  {gpio="pin:13 activelow:yes initialValue:high"}

//-----Setpoint & Thresholds-----//
Number:Temperature AcSetpoint_Temp_1 (AC)
Number:Temperature AcUpper_Threshold_1
Number:Temperature AcLower_Threshold_1
Number:Temperature HeatSetpoint_Temp_1 (Heat)
Number:Temperature HeatUpper_Threshold_1
Number:Temperature HeatLower_Threshold_1

RULES


// These rules control the HVAC system... the goal is to have a single set of rules that control multiple 
// HVAC systems, without the need to duplicate and modify rules

import org.eclipse.smarthome.model.script.ScriptServiceUtil

        rule "Turn on AC when needed"
when
        Member of AC changed
then
        val system = triggeringItem.name.split("_").get(2).toString
        //logInfo("Trigger", system)

        val ac = ScriptServiceUtil.getItemRegistry.getItem("AC_Sys_"+system) as SwitchItem
        val fan = ScriptServiceUtil.getItemRegistry.getItem("Fan_Sys_"+system) as NumberItem
        val acRelay = ScriptServiceUtil.getItemRegistry.getItem("AC_Relay_"+system) as SwitchItem
        val fanRelay = ScriptServiceUtil.getItemRegistry.getItem("Fan_Relay_"+system) as SwitchItem
        val temp = ScriptServiceUtil.getItemRegistry.getItem("HVAC_Temp_"+system) as NumberItem
        val acSet = ScriptServiceUtil.getItemRegistry.getItem("AcSetpoint_Temp_"+system) as NumberItem
        val acUpThreshold = ScriptServiceUtil.getItemRegistry.getItem("AcUpper_Threshold_"+system) as NumberItem
        val acLowThreshold = ScriptServiceUtil.getItemRegistry.getItem("AcLower_Threshold_"+system) as NumberItem
        val acLockout = ScriptServiceUtil.getItemRegistry.getItem("Lockout_AC_"+system) as SwitchItem

            if(acLockout.state == OFF && ac.state == ON && (temp.state >= (acSet.state + acUpThreshold))){
                if(acRelay.state == OFF && fan.state == 1){
                    logInfo("AC", "Turning ON AC system for system" + system)
                    // sendCommand("Fan_Relay_"+system, ON)
                    // sendCommand("Fan_Sys_"+system, ON)
                    // Thread::sleep(500)
                    // sendCommand("AC_Relay_"+system, ON)
                    // sendCommand("AC_Sys_"+system, ON)
                    // sendCommand("SysStatus_AC_"+system, ON)
                }
            }
            else{
                if(ac.state == ON && (temp.state <= (acSet.state - acLowThreshold.state))){
                    if(acRelay.state == ON && fanRelay.state == ON){
                        logInfo("AC", "Turning OFF AC system for system" + system)
                        // sendCommand("Fan_Relay_"+system, OFF)
                        // sendCommand("Fan_Sys_"+system, OFF)
                        // Thread::sleep(500)
                        // sendCommand("AC_Relay_"+system, OFF)
                        // sendCommand("SysStatus_AC_"+system, OFF)
                        // sendCommand("Lockout_AC_"+system, ON)  
                    }
                }
            }
end


    rule "Turn OFF AC/Heat when control proxy switch changes from ON to OFF"
when
    Member of HVAC_Control changed from ON to OFF
then
    val mode = triggeringItem.name.split("_").get(1).toString
    val system = triggeringItem.name.split("_").get(2).toString
    logInfo("AC", "Turning OFF AC system for system" + system)
            if(mode == "AC"){
                logInfo("AC_OFF", "AC Control switch changed to OFF... turning AC OFF for System " + system) 
                // sendCommand("Fan_Relay_"+system, OFF)
                // sendCommand("Fan_Sys_"+system, OFF)
                // sendCommand("AC_Relay_"+system, OFF)
                // sendCommand("SysStatus_AC_"+system, OFF)
                // sendCommand("Lockout_AC_"+system, ON)      
            }
        else{
            if(mode == "Heat"){
            logInfo("Heat_OFF", "Heat Control switch changed to OFF... turning Heat OFF for System " + system)
            // sendCommand("Fan_Relay_"+system, OFF)
            // sendCommand("Fan_Sys_"+system, OFF)
            // sendCommand("Heat_Relay_"+system, OFF)
            // sendCommand("SysStatus_Heat_"+system, OFF)
            // sendCommand("Lockout_Heat_"+system, ON)
            }
        }
end

    rule "Turn OFF "Lockout_" + mode + system after 5 mins"
when
    Member of Lockouts changed from OFF to ON
then
    val mode = triggeringItem.name.split("_").get(1).toString
    val system = triggeringItem.name.split("_").get(2).toString

            if(mode == "AC"){
                logInfo("AC_Lock", "Turning OFF AC Lockout in 5 mins for System " + system)
                // createTimer(now.plusMinutes(5), [ |
                // sendCommand("Lockout_AC_"+system, OFF)
                // ])
            }
        else{
            if(mode == "Heat"){
                logInfo("Heat_Lock", "Turning OFF Heat Lockout in 5 mins for System " + system)
                // createTimer(now.plusMinutes(5), [ |
                // sendCommand("Lockout_Heat_"+system, OFF)
                // ])
            }
        }
end 

LOG

Unknown variable or command '-'; line 38, column 54, length 34

When I log out the states ie: temp.state and acSet.state I get… 76 °F and 75 °F.

I would think that if I did (76 °F - 75 °F) I’d get 1 °F back?

What am I doing wrong?

Thanks! :slight_smile:

Which is line 38?

I think your problem is going to be that you are trying to do arithmetic with item.state, and unlike numbers, state objects don’t have arithmetic methods. (item.state can have values “banana”, OFF, etc. not just numeric)

You’ll need to cast as numeric types.

1 Like

Thanks for the info. I tried adding .state as QuantityType.intValue to the end of the ScriptUtil vals… getting a “Could not cast 72.500 °F to void”

I think I’m going to remove the UOM and go from there.

Bad syntax there, it would be
(myItem.state as QuantityType<Temperature>).intValue

Joy!

Changed the vals to…

val temp = (ScriptServiceUtil.getItemRegistry.getItem("HVAC_Temp_"+system).state as QuantityType<Temperature>).intValue
val acSet = (ScriptServiceUtil.getItemRegistry.getItem("AcSetpoint_Temp_"+system).state as QuantityType<Temperature>).intValue
val acUpThreshold = (ScriptServiceUtil.getItemRegistry.getItem("AcUpper_Threshold_"+system).state as QuantityType<Temperature>).intValue
val acLowThreshold = (ScriptServiceUtil.getItemRegistry.getItem("AcLower_Threshold_"+system).state as QuantityType<Temperature>).intValue

Test rule…

logInfo("Vals", "Living temp --> {} , AC Setpoint --> {} , AC UpThreshold --> {} , AC LowThreshold --> {}", temp, acSet, acUpThreshold, acLowThreshold)

val sum = temp + acSet
logInfo("Sum", "Sum of temp and acSet is  --> {}", sum)

if(sum > 100)logInfo("Sum Compare", "True " + sum + " is > 100") else logInfo("Sum Compare", "False " + sum + " is < 100")

Log…

Living temp --> 72 , AC Setpoint --> 73 , AC UpThreshold --> 2 , AC LowThreshold --> 1
Sum of temp and acSet is  --> 145
True 145 is > 100

Thanks @rossko57!