If-Statement causes an error when using it with "triggeringItem"

Aaaah :hugs: now I understand (der Groschen ist gefallen or the penny dropped). But a little drop of bitterness still stays. When the Channel-based rule is fired and gives the information to the “Switch-Rule” I get the information from the “manual rule” too that it is triggered. Maybe it is possible to use one Rule-File for both rules and a gobal variable which is set in the channel-based one and queried in the other one.
I will try, thx.

The specific problem is that when the Rule is triggered by the Channel events there is no triggeringItem so there is no way to have triggeringItem.state == ON. When there is no triggeringItem, you will always get an error if you try to call triggeringItem.state.

You might be able to test that it’s not null first triggeringItem != null && triggeringItem.state == ON.

=== should only be used when comparing with null.

That’s the same problem but from the other direction. When you trigger that Rule by the Item there is no receivedEvent so you will get an error when you try to call receivedEvent.class.

As with the above, you might be able to determine whether the Rule was triggered by the Item or the Channels using something like:

    if(triggeringItem !== null){
        // do Item stuff
    }
    else if(receivedEvent !== null){
        // do channel stuff
    }

This too might generate an error in which case the suggestions of splitting it into two Rules will be the only viable option.

1 Like

Hi Guys,
thx to all of you for your help finding a solution for my problem, especially to @mstormi for his attempt splitting it into two Rules and his extra Explanations for me.

I will use his idea in one of my next tests. I’m just looking for suitable example.

After a while of testing the possibilities, the way I’m looking for came from @rlkoshak , as I only want to determine wether the rule is triggered by an event or by a channel and then log this in the viewer

So now my rule looks like:

import org.eclipse.smarthome.model.script.ScriptServiceUtil
val sonoff_device_ids = newArrayList("sonoffs")
val rulename = "sonoff_firmware_info"
var Timer tSonoffFirmware = null

rule "Sonoff_firmware_info"
when
        Item Sonoff_Release_Refresh changed to ON
     or Item Dummy4 changed to ON 
     or Channel 'astro:sun:local:noon#event' triggered START 
     or Channel 'astro:sun:local:astroDusk#event' triggered START 
     or Channel 'astro:sun:local:night#event' triggered START 
     or Channel 'astro:sun:stowing1:noon#event' triggered START 

then
    var firmware = transform("REGEX", ".*([0-9].[0-9].[0-9])", Sonoff_Current_FW_Available.state.toString)
    logInfo(rulename, "Tasmota Refresh Items Firmware-Release-State in BasicUI : " + firmware + "(sonoff)")

        // is it an event based Trigger ?
    if (triggeringItem !== null) {
        // now you can do stuff like logInfo
        logInfo(rulename, "Rule fired manually by  : " + triggeringItem.name + " State: " + triggeringItem.state + " previousState: " + previousState)
        // or something other like: generic item from triggeringItem.name  "it's Just fun"
        //++++ Pointer-adresses for the dynamically generated items to get corresponding/generic item       ***thx to @5iver and @rlkoshak for help***
       var GenericItem tempTriggerItem = ScriptServiceUtil.getItemRegistry.getItem(triggeringItem.name) as  GenericItem  // 
       logInfo (rulename, "Itemname is: " + tempTriggerItem.name)
       // or this :
       if (tSonoffFirmware !== null) {
          logInfo("rulename","Timer wird gecancelled: " + tSonoffFirmware)
          tSonoffFirmware.cancel
       }
        logInfo("rulename","Timer wird initialisiert")
        tSonoffFirmware = createTimer(now.plusSeconds(3), [|
           if (triggeringItem.state == ON) {               // this is the state of the triggering Item (could also be generic Item's State)
               tempTriggerItem.postUpdate(OFF)             // update(switch Off) the triggering item via generic item (as it's the same in this case)
               logInfo("rulename","GenericItem ist" + tempTriggerItem)
               // or whatever stuff you want ;)
           }
        ])
    }
             // is it a channel based Trigger ? 
    else if (receivedEvent !== null) {
        // now you can do stuff like logInfo
        logInfo(rulename, "Rule fired by Channel: " + receivedEvent.toString )
        // and of course a lot of other stuff if you/I want ;)
   }
    for (String device_id : sonoff_device_ids) {
          publish("peter", "cmnd/" + device_id + "/status", "2")
          logInfo(rulename, "Sonoff Maintenance: " + device_id)
    }
    logInfo(rulename, "Tasmota Refresh Items Firmware-Release-State : end")
end 

even it has a bit of the idea of Markus inside the lambda (the switch back to OFF for the the triggered event, (as said just a bit :wink::wink:), as a starting point for more).
And the result in the logger shows:

2019-08-02 22:44:15.345 [INFO ] [me.model.script.sonoff_firmware_info] - Tasmota Refresh Items Firmware-Release-State in BasicUI : 6.6.0(sonoff)
2019-08-02 22:44:15.356 [INFO ] [me.model.script.sonoff_firmware_info] - Rule fired manually by  : Dummy4 State: ON previousState: OFF
2019-08-02 22:44:15.363 [INFO ] [me.model.script.sonoff_firmware_info] - Itemname is: Dummy4
2019-08-02 22:44:15.389 [INFO ] [me.model.script.sonoff_firmware_info] - Sonoff Maintenance: sonoffs
2019-08-02 22:44:15.392 [INFO ] [me.model.script.sonoff_firmware_info] - Tasmota Refresh Items Firmware-Release-State : end
//
2019-08-02 23:27:02.862 [INFO ] [me.model.script.sonoff_firmware_info] - Tasmota Refresh Items Firmware-Release-State in BasicUI : 6.6.0(sonoff)
2019-08-02 23:27:02.873 [INFO ] [me.model.script.sonoff_firmware_info] - Rule fired by Channel: astro:sun:local:night#event triggered START
2019-08-02 23:27:02.889 [INFO ] [me.model.script.sonoff_firmware_info] - Sonoff Maintenance: sonoffs
2019-08-02 23:27:02.894 [INFO ] [me.model.script.sonoff_firmware_info] - Tasmota Refresh Items Firmware-Release-State : end

BTW: My second Rule was not a very good example, as I inserted the virtuel Switch just for testing the rule if it triggeres. I changed it now to

//import org.eclipse.smarthome.core.thing.events.ChannelTriggeredEvent   // When using this import, you can see the answer next line
//                                                                          The import 'org.eclipse.smarthome.core.thing.events.ChannelTriggeredEvent' is never used.
  
rule "sunset check"
when
         Channel 'astro:sun:local:set#event' triggered
    or   Channel 'astro:sun:local:civilDusk#event' triggered
    or   Channel 'astro:sun:local:nauticDusk#event' triggered
    or   Channel 'astro:sun:local:astroDusk#event' triggered 
    or   Channel 'astro:sun:local:daylight#event' triggered
    or   Channel 'astro:sun:local:noon#event' triggered
    or   Channel 'astro:sun:stowing1:noon#event' triggered START 
    or   Channel 'astro:sun:stowing2:noon#event' triggered
    or   Channel 'astro:sun:stowing3:noon#event' triggered
    or   Channel 'astro:sun:local:rise#event' triggered 
    or   Channel 'astro:sun:local:morningNight#event' triggered 
    or   Channel 'astro:sun:local:astroDawn#event' triggered 
    or   Channel 'astro:sun:local:nauticDawn#event' triggered 
    or   Channel 'astro:sun:local:night#event' triggered 
    or   Item Sonoff_Release_Refresh changed to ON 
then
    if (triggeringItem !== null) {
    logInfo("sunset Check", "INFO: Rule was manually triggered  by =  '{}' but that's not good in this Rule, so we break off", triggeringItem.name )
    return;   // only for checking if the Rule is triggered manually by an event(item)
    }
    //    val String ruleTitle="event::getCanonicalName()"
    logInfo( "sunset Check", "INFO: receivedEvent.class.getCanonicalName() --> [{}], Event = '{}'", receivedEvent.class.getCanonicalName(), receivedEvent.getEvent() )
    logInfo( "sunset Check", "INFO: receivedEvent.channel.toString()       --> [{}], Event = '{}'", receivedEvent.channel.toString(), receivedEvent.getEvent() )
    val channelevent = receivedEvent.getEvent()
    logInfo( "sunset Check", "INFO: Channel Event = '{}'", channelevent )
    val channelname = receivedEvent.channel.toString()
    logInfo( "sunset Check", "INFO: Channel Name =  '{}'", channelname )
    val channelthingUID = receivedEvent.channel.thingUID.toString()
    logInfo( "sunset Check", "INFO: Channel UID =  '{}'", channelthingUID )
    val channelID = receivedEvent.channel.id.toString()
    logInfo( "sunset Check", "INFO: Channel ID =  '{}'", channelID )

    logInfo( "sunset Check", "INFO: receivedEvent.channel.toString() Line 35      --> [{}], receivedEvent = '{}'", receivedEvent.channel.toString(), receivedEvent)
//    logInfo( "sunset Check", "INFO: receivedEvent.channel.toString() Line 36       --> [{}], Event = '{}'", receivedEvent.class.getCanonicalName.toString().split(".").get(5), receivedEvent.getEvent() )  // geht so nicht - doesn't work either 
//    val channelState = receivedEvent.getStatusInfo  // geht so nicht - doesn't work either 
//    logInfo( "sunset Check", "INFO: Channel Status Line 38 =  '{}'", channelState )  // geht so nicht - doesn't work either 
    val triggerEvent_split = receivedEvent.toString
    logInfo( "sunset Check", "INFO: Trigger =  '{}'", triggerEvent_split )
    val triggerEvent_split_3 = triggerEvent_split.split(":").get(3)
    logInfo( "sunset Check", "INFO: Split_3 ID =  '{}'", triggerEvent_split_3 )

end

Again, thx to you all for help.

Cheers,
Peter