[Rules DSL] Send command or update to item only if the command/state is different than current state

Here’s a lambda to send a command or update to an item, but only if the command/state being sent is different than the item’s current state. The lucid JSR223-Jython utils.py module (@RRoe) does some checks to make sure the item is compatible with what is being sent. I added that in too, but in a more robust way that checks all allowed State and Command types, just as is done when using sendCommand and postUpdate. For example, you can’t send a OFF to a DecimalType item. This version works in the Rules DSL and includes both sendCommand and postUpdate.

Usage:
You’ll need to pass an item, a string, and a boolean (true for SendCommand and False for postUpdate). I’ve played with it a little… please let me know if you find any issues!

checkFirst.apply(Virtual_Switch_1, "ON", false)

If you combine it with this, you can use a string name, like…

checkFirst.apply(ScriptServiceUtil.getItemRegistry.getItem("Virtual_Switch_1"), "ON", false)

Lambda
Put all of this at the top of your rules file, under any other imports.

import org.eclipse.xtext.xbase.lib.Functions
import org.eclipse.smarthome.core.types.State
import org.eclipse.smarthome.core.types.Command
import org.eclipse.smarthome.core.types.TypeParser

val Functions$Function3<GenericItem, String, Boolean, Boolean> checkFirst = [
    GenericItem item,
    String newValue,
    Boolean SendCommand |

    if (SendCommand) {
        val Command parsedCommand = TypeParser.parseCommand(item.acceptedCommandTypes,newValue)
        if (parsedCommand !== null) {
            if (item.state.toString != newValue) {
                item.sendCommand(newValue)
                logDebug("Rules", "checkFirst: {}: Sent Command [{}]",item.name,newValue)
            }
            else {
                logDebug("Rules", "checkFirst: {}: Not sending Command [{}] because it matches current state",item.name,newValue)
            }
        }
        else {
            logWarn("Rules", "checkFirst: {}: Cannot convert [{}] to an accepted Command type: [{}]",item.name,newValue,item.acceptedCommandTypes)
        }
    }
    else {
        var State parsedState = TypeParser.parseState(item.acceptedDataTypes,newValue)
        if (parsedState !== null) {
            if (item.state.toString != newValue) {
                item.postUpdate(newValue)
                logDebug("Rules", "checkFirst: {}: Sent Update [{}]",item.name,newValue)
            }
            else {
                logDebug("Rules", "checkFirst: {}: Not sending Update [{}] because it matches current state",item.name,newValue)
            }
        }
        else {
            logWarn("Rules", "checkFirst: {}: Cannot convert [{}] to an accepted State type: [{}]",item.name,newValue,item.acceptedDataTypes)
        }
    }
    true
]