Lucid script step by step ... (Jython scripting tutorial using lucid,jsr223 Jython helper library)

Thanks a lot, that did the trick, after adding the item it works as expected.

Sorry, somehow I must have overlocked that part of the installation instructions!

No you didn’t. I added it afterwards to the installation instructions. I’m happy that it works now! :rofl:

Hello! Did you make it?

Your script may look similar to this now:

from lucid.rules import rule, addRule # Needed for defining and adding a rule
from lucid.triggers import ItemStateChangeTrigger, CronTrigger # Import the different type of triggers that you will be using
from lucid.utils import getItemValue

@rule
class StepByStep(object): # Giving the class a unique name
    def getEventTriggers(self):
        return [
            ItemStateChangeTrigger('My_TestSwitch_1'), # Triggering when the switch changes its state.
            ItemStateChangeTrigger('My_TestSwitch_2', ON), # Only trigger when switch turns on
            CronTrigger('0 0/2 * 1/1 * ? *'), # Runs every other minute
        ]

    def execute(self, modules, inputs):
        self.log.setLevel(DEBUG)

        if self.event.isItem:
            self.log.debug('One of the test switches has changed its state')
            self.log.debug('Triggering item name: \'' + unicode(self.event.itemName) + '\', state: ' + str(self.event.state))

            # Only set Test_String_1 to "CAT" when both switches are ON and only when an item trigger has occurred. (Not at cron events)
            bothSwitchesAreOn = ((getItemValue("My_TestSwitch_1", OFF) == ON) and (getItemValue("My_TestSwitch_2", OFF) == ON))
            if bothSwitchesAreOn:
                events.postUpdate("Test_String_1", "CAT")
                self.log.debug('CAT!!!')

        elif event.isCron:
            self.log.debug('A cron event occurred')
            events.postUpdate("Test_String_1", "DOG")

addRule(StepByStep()) # Needed to add the rule, use the same name as defined for the class

We add a second function to our script that triggers upon the update and give it a unique rule name. We use a predefined “constant” for the cron expression and we import yet another trigger type from lucid.triggers named ItemStateUpdateTrigger. As you know, an item update is not the same as an item change. In case you need a recap.

Update your scripts to this:

from lucid.rules import rule, addRule # Needed for defining and adding a rule
from lucid.triggers import ItemStateChangeTrigger, ItemStateUpdateTrigger, CronTrigger # Import the different type of triggers that you will be using
from lucid.utils import getItemValue

@rule
class StepByStep(object): # Giving the class a unique name
    def getEventTriggers(self):
        return [
            ItemStateChangeTrigger('My_TestSwitch_1'), # Triggering when the switch changes its state.
            ItemStateChangeTrigger('My_TestSwitch_2', ON), # Only trigger when switch turns on
            CronTrigger(EVERY_30_SECONDS), # Using a cron expression constant
        ]

    def execute(self, modules, inputs):
        self.log.setLevel(DEBUG)

        if self.event.isItem:
            self.log.debug('One of the test switches has changed its state')
            self.log.debug('Triggering item name: \'' + unicode(self.event.itemName) + '\', state: ' + str(self.event.state))

            # Only set Test_String_1 to "CAT" when both switches are ON and only when an item trigger has occurred. (Not at cron events)
            bothSwitchesAreOn = ((getItemValue("My_TestSwitch_1", OFF) == ON) and (getItemValue("My_TestSwitch_2", OFF) == ON))
            if bothSwitchesAreOn:
                events.postUpdate("Test_String_1", "CAT")
                self.log.debug('CAT!!!')

        elif event.isCron:
            self.log.debug('A cron event occurred')
            events.postUpdate("Test_String_1", "DOG")

addRule(StepByStep()) # Needed to add the rule, use the same name as defined for the class

@rule
class WatchMyString(object): # Giving the class a unique name
    def getEventTriggers(self):
        return [ItemStateUpdateTrigger('Test_String_1')] # Triggering when the Test_String_1 items updates
    def execute(self, modules, inputs):
        self.log.setLevel(DEBUG)
        self.log.debug('Item: \'' + unicode(self.event.itemName) + '\', was updated')

addRule(WatchMyString()) # Needed to add the rule, use the same name as defined for the class

After you’ve saved the new script, you’ll notice in the log that Test_String_1 gets an update every 30 seconds!

We don’t want that to happen.

When we send an update to the Test_String_1 in the first rule, we’d like to check first if the new value differs from the value stored so that the second rule only triggers whenever there is an actual change.

It can be done by inspecting the old value together with an if statement. However we will use another handy function in lucid.utils named postUpdateCheckFirst.

# Checks if the current state of the item is different than the desired new state.
# If the target state is the same, no update is posted.

Use it like this: postUpdateCheckFirst('Item', 'New Value')

Your job is to modify the script to do that.

Is there the equivalent for sendCommand? I’ve often wished the Rules DSL had this.

Sure there is.

sendCommandCheckFirst(itemName, newValue):

:grin:

Hello! How is your lucid jython scripting going?

By now, you’ve added postUpdateCheckFirst to the lucid.utils import line.
Then you replaced the line events.postUpdate("Test_String_1", "CAT") with postUpdateCheckFirst('Test_String_1', 'CAT')

Your script should look like this now:

from lucid.rules import rule, addRule # Needed for defining and adding a rule
from lucid.triggers import ItemStateChangeTrigger, ItemStateUpdateTrigger, CronTrigger # Import the different type of triggers that you will be using
from lucid.utils import getEvent, getItemValue, postUpdateCheckFirst

@rule
class StepByStep(object): # Giving the class a unique name
    def getEventTriggers(self):
        return [
            ItemStateChangeTrigger('My_TestSwitch_1'), # Triggering when the switch changes its state.
            ItemStateChangeTrigger('My_TestSwitch_2', ON), # Only trigger when switch turns ON
            CronTrigger(EVERY_30_SECONDS), # Using a cron expression constant
        ]

    def execute(self, modules, inputs):
        self.log.setLevel(DEBUG)
        event = self.event # Now you can use event instead of self.event below

        if event.isItem:
            self.log.debug('One of the test switches has changed its state')
            self.log.debug('Triggering item name: \'' + unicode(event.itemName) + '\', state: ' + str(event.state))

            # Only set Test_String_1 to "CAT" when both switches are "ON" and only when an item trigger has occurred. (Not at cron events)
            bothSwitchesAreOn = ((getItemValue("My_TestSwitch_1", OFF) == ON) and (getItemValue("My_TestSwitch_2", OFF) == ON))
            if bothSwitchesAreOn:
                postUpdateCheckFirst('Test_String_1', 'CAT')
                self.log.debug('CAT!!!')

        elif event.isCron:
            self.log.debug('A cron event occurred')
            postUpdateCheckFirst('Test_String_1', 'DOG')

addRule(StepByStep()) # Needed to add the rule, use the same name as defined for the class

@rule
class WatchMyString(object): # Giving the class a unique name
    def getEventTriggers(self):
        return [ItemStateUpdateTrigger('Test_String_1')] # Triggering when the Test_String_1 items updates
    def execute(self, modules, inputs):
        self.log.setLevel(DEBUG)
        self.log.debug('Item: \'' + unicode(self.event.itemName) + '\', was updated')

addRule(WatchMyString()) # Needed to add the rule, use the same name as defined for the class

By watching the log output, you’ll find that the Test_String_1 doesn’t get “touched” by an update unless the new value is different from the old one.

Unless you have any questions, I think I’ll end here for this time.
I will continue with adding some more examples for lucid. Studying them and maybe modify them is aslo a great way to learn

Thanks for joining this tutorial.

Cheers!

EDIT: Scripts in the tutorial is modified to work with lucid v1.0.0