Thx, for your hint. No I didn’t, as I thought it’s only for comparing with null. I will give it a try and inform you about the result.
Cheers,
Peter
Thx, for your hint. No I didn’t, as I thought it’s only for comparing with null. I will give it a try and inform you about the result.
Cheers,
Peter
thx, for answering.
But as the switch is just a “Dummy” for manually triggering the rule from time to time no channel is possible or do you have an idea for a Dummy-Channel ?
Cheers,
Peter
extracted from the documentation
When a binding provides such channels, you can find the needed information in the corresponding binding documentation. There is no generic list of possible values for
triggerEvent
, ThetriggerEvent
(s) available depend upon the specific implementation details of the binding. If the Rule needs to know what the received event was, use the implicit variablereceivedEvent
to access the information.
Did you try to use receivedEvent
instead triggeringEvent
?
@mikaelgu
Hi Mikael,
sorry to say but your hint didn’t work. Same error as before.
I tried:
if (triggeringItem.state === ON) {
logInfo("sonoff.rules", "Rule was manually fired: " + triggeringItem + " previousState: " + previousState)
}
and the error:
2019-07-29 10:28:02.309 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Sonoff Tasmota Release Version': cannot invoke method public abstract org.eclipse.smarthome.core.types.State org.eclipse.smarthome.core.items.Item.getState() on null
came up again.
But anyway, thx for help.
Cheers,
Peter
the implicit variable
triggeringItem
is populated with the Item that caused the Rule to trigger.
You are using a combination of an item and channels, that’s why you get the error when the trigger comes from the astro channel
When the rule gets triggered by a channel, there is no implicit triggeringItem. There’s no fix for that, it’s just a logical consequence.
But the Item exists whether or not you trigger any rules by channels or anything else. The Item is always accessible by name within any rule, regardless of how it was triggered.
You can always test the state of the Item by name.
Hi Humberto,
in another rule I just tested the event-driven way. It’s a rule based on this post from @shutterfreak.
But an error came up when I inserted the line
or Item Sonoff_Release_Refresh changed to ON
the rule:
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
// 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() --> [{}], Event = '{}'", receivedEvent.channel.toString(), receivedEvent)
// logInfo( "sunset Check", "INFO: receivedEvent.channel.toString() --> [{}], Event = '{}'", receivedEvent.getCanonicalName(), receivedEvent.getEvent() ) //geht nicht
// logInfo( "sunset Check", "INFO: receivedEvent.channel.toString() --> [{}], Event = '{}'", receivedEvent.class.getCanonicalName().split(".").get(5), receivedEvent.getEvent() ) // geht so nicht
// val channelState = receivedEvent.getStatusInfo()
// logInfo( "sunset Check", "INFO: Channel Status = '{}'", channelState )
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 )
the log:
2019-07-29 10:54:05.955 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'sunset check': cannot invoke method public final native java.lang.Class java.lang.Object.getClass() on null
As I’m not very experienced in programming and that stuff, I just doing “trial and error”. But for me it seems as if those variants do not work together , but thx for hint.
Cheers,
Peter
thx for your tip. This is the way i’m just doing . My proposal was to combine the two ways in a more general manner.
But if it’s not possible - it’s not possible, anyway .
So no need to think about it anymore, as I spent hours and hours to find a solution or workaround.
This is the head of the rule,I posted above:
//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
When using the import I just get the information that the import is never used, so I commetend it out.
Remove channel triggers from your rule and move them to a new rule to have a body to contain Sonoff_Release_Refresh.sendCommand(ON)
@fibu-freak you can also define an Item to store those astro events that you are interested on, like
DateTime Sunrise_Time { channel="astro:sun:home:rise#start" }
By doing that you can use the triggeringEvent
implicit variable on you rule for all the triggers
or you can do what @mstormi suggests
umm, it doesn’t work like that. You cannot store transient events in an Item state.
What your example does is store the expected datetime of sunrise in an Item. The Astro binding will set that when it calculates the day’s events, usually at midnight, and that’s that. The Item stays set to the datetime all day until the next time it is changed. Nothing happens to it when the given time passes.
astro:sun:home:rise#start is a datetime state, a prediction.
astro:sun:local:set#event is an event. It just happens, then it is gone again until next day.
Hi Markus,
thx for your hint, but I do not quite understand what is meant or what you try me to explain (sorry I’m bit stupid)
I don’t want to send a command to my switch. But if you mean to make two rules, one which fire when I use the switch to start and another one which starts channel based, I understand. But this was not my intension.
I just want to know if the rule is triggered by the switch or by a channel. And it works when I used a named switch(Item).
But my consideration was to use the If-Clause more general to make the Rule-Stuff a bit more “lean”.
That’s the difficult part, so my suggestion is to have two rules, rule 1 for the (virtual) switch and rule 2 for the channels. Then rule 2 sends a command to the virtual switch which is not having any physical effect but is there only to call rule 1 and do everything else in there.
Aaaah 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.
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 ), 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