Item Name as Variable in Rules

Hello,

I’m trying to use a variable name for an item. I sometimes re-assign my switches and would like to change it in one place (variable name) so I don’t miss it in multiple places.

My items file is something like this:

// HS103P2 Mini Smart Plugs
Switch switchTplinkHs103p2_1 "Cable Modem [%s]" <poweroutlet> ( groupHome, groupOffline )  { channel="tplinksmarthome:hs105:TplinkHs103p2_1:switch" }

In the rule file, here is what I’d like to do in theory:

var String CableModemSwitch = "switchTplinkHs103p2_1"

rule "CableModemOnStartup"
    when
        System started
    then
        if ( CableModemSwitch.state != ON ) {
            postUpdate( CableModemSwitch, ON )
       }
    end

This is a very simple example of what I’m trying to do. I know this is syntactically incorrect. Admittedly, I’m not a Java or OOP person. I’m thinking this is very doable but I just haven’t been able to find any examples in the OpenHAB Community or online. Any help is appreciated!

1 Like

Maybe you could put all the possible switches in a group (or use one of your existing groups), then loop through them in the “then” part of the rule until you find the one that matches your string value. Some examples of searching through the group are found here.

YOu can use this technique to get items from strings:

1 Like

@jswim788 This worked for me. The size of my rule file has almost doubled though so I’m weighing the pros and cons.

@lipp_markus This partially worked for me. I have 3 rules in a rule file. I only saw this work for one of the rules while the other two rules got errors mentioning NULL settings for the SwitchItem variable when referenced. I declared the variable at the top of the file so I would think the scope is good. This is my first exposure to Java though so it’s possible there’s some details I’m missing.

Thank you very much to both of you for the suggestions!

Maybe posting the file will allow us to take a look

As an option, you can have multiple rules files, if that would simplify things for you.

I’m not opposed to multiple rule files but my preference is having one so I don’t have to look in too many places when a change is needed.

First let me explain the thinking behind these rules. We are cord cutters and we stream our video/TV content. I haven’t taken the time to capture packets or do a full blown analysis but I feel my ISP is throttling at times. I can tell this because the video bitrate drops to some poor video quality or there is constant re-buffering while viewing streams that are otherwise fine. I have a 1GB down connection so it should have nothing to do with bandwidth. It seems that a reset of the cable modem mitigates this issue for a while. So these rules were added for me to easily reset the connection while I’m away from home or any time through the OpenHAB phone app. My family is not too technical and this is a great substitute. I have a switch in my sitemap switchCableModemReset that I toggle to ON to trigger the reset sequence and it works well.

I said earlier that I sometimes move switches around, in this case switchTplinkHs103p2_1. This happened last holiday season as we like to put up a lot of lights, decorative houses, and general holiday items that consume electricity. I’ll move around switches to accommodate, especially since a cable modem power supply having a 10A capable switch is overkill and I will make do in a pinch until I can replenish switches by ordering more. I recently noticed that I missed replacing the string in one place and I could not reset the cable modem properly while I was away and it had to wait until I got home, which is why I am very interested in having a way to map a string to an item, which allows me to change one single entry CableModemSwitchAlias and the rules pick up the change.

When I tried the suggestion made by @lipp_markus, I only observed the first rule CableModemOnStartup working and the other two rules errored out with NULL references to the SwitchItem.

Here is my rules file cableModem.rules.

var String CableModemSwitchAlias = "switchTplinkHs103p2_1"
var String RuleFile = "cableModem.rules"

///////////////////////////////////////////////////////////////////////////////
rule "CableModemOnStartup"
    when
        System started
    then
        var String RuleName = "{CableModemOnStartup}"

        logInfo( RuleFile, RuleName + " Rule triggered" )

        if( switchTplinkHs103p2_1.state == ON ) {
            logInfo( RuleFile, RuleName + " Cable Modem Switch " + CableModemSwitchAlias + " is already ON - Nothing to do" )
        } else {
            logInfo( RuleFile, RuleName + " Cable Modem Switch " + CableModemSwitchAlias + " is not ON - Turn ON now" )
            switchTplinkHs103p2_1.sendCommand( ON )
        }

        logInfo( RuleFile, RuleName + " Rule completed" )
end

///////////////////////////////////////////////////////////////////////////////
rule "CableModemReset"
    when
        Item switchCableModemReset changed to ON
        // Time cron "0 * * * * ? *"
    then
        var String RuleName = "{CableModemReset}"

        logInfo( RuleFile, RuleName + " Rule triggered - Cycle Cable Modem power using " + CableModemSwitchAlias )

        if( switchTplinkHs103p2_1.state == OFF ) {
            logInfo( RuleFile, RuleName + " Cable Modem Switch " + CableModemSwitchAlias + " is OFF - Turn ON now" )
            switchTplinkHs103p2_1.sendCommand( ON )
        } else {
            logInfo( RuleFile, RuleName + " Cable Modem Switch " + CableModemSwitchAlias + " is ON/NULL - Turn OFF now" )
            switchTplinkHs103p2_1.sendCommand( OFF )
        }

        postUpdate(switchCableModemReset, OFF)

        logInfo( RuleFile, RuleName + " Rule complete" )
end

///////////////////////////////////////////////////////////////////////////////
rule "CableModemPowerOn"
    when
        Item switchTplinkHs103p2_1 changed to OFF
    then
        var String RuleName = "{CableModemPowerOn}"

        logInfo( RuleFile, RuleName + " Rule triggered - Cable Modem switch " + CableModemSwitchAlias + " changed to OFF - Sleep 30 seconds and change to ON" )
        Thread::sleep( 30000 )

        logInfo( RuleFile, RuleName + " Turn ON Cable Modem switch " + CableModemSwitchAlias )
        switchTplinkHs103p2_1.sendCommand( ON )

        postUpdate(switchCableModemReset, OFF)

        logInfo( RuleFile, RuleName + " Rule complete" )
end

I’d suggest creating a group item and refer to that in the rule.

Then you need only subscribe one / any / all of your device items to that group. (Using a One on = On method)

That way you don’t need to touch the rule file at all.

Only the .items file or Configuration/Items in PaperUI.

Why not instead use meaningful names for the Items (e.g. CableModem instead of switchTplinkHs103p2_1. Then change the binding config/Channel Link on the Item instead of changing the Item names. Then you can leave your Rules and Sitemap and pretty much everything else alone. Items are supposed to model your home automation. It’s a layer of abstraction between technology specific stuff which belongs in the Thing (e.g. TPLink Switch) and what it is that technology controls (the Cable Modem).

So the true answer to your question is you shouldn’t be doing it this way. You should be using Items in the way they were designed to be used which would make it so you don’t have to do this at all.

The technical answer to your question is documented in the link Lipp provided or the Associated Items Design Pattern.

You are not writing in Java. You are writing in a Domain Specific Language (DSL) loosely based off of Xtend which is a scripting language that runs on the Java Virtual Machine. You have access to some Java stuff from the Rules DSL but Rules really bares little resemblance to actual Java programming.

If you are more familiar with languages like Python or JavaScript, you might be more comfortable using JSR223 and coding Rules in one of those languages instead.

If you use Items in the way I described above, you will only have one place to change anything, the .items files.

Honestly, this is the main reason why I’m always against Item names that reference the technology and such. Rules don’t care that the switch controlling it is TPLink or Zwave or whatever. The Sitemap doesn’t care either. Nor does Persistence. So why not just call it “CableModemPower” and when you have to change physical switches around, change the Link on that Item?

This is actually an extension of my advice above. If you have more than one Item that needs to be treated in the same way, use a Group and write your Rule around the Group. Then when you move things around you only need to change Group membership to have it processed by the right Rules.

That’s actually good feedback about the item naming. I will go with that. It keeps the maintenance low and the code is nice and minimal. I was overthinking that part. :smiley:

Thanks to everyone that contributed suggestions!