Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add startup level trigger #194

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.openhab.automation.jrule.internal.engine.excutioncontext.JRuleItemReceivedCommandExecutionContext;
import org.openhab.automation.jrule.internal.engine.excutioncontext.JRuleItemReceivedUpdateExecutionContext;
import org.openhab.automation.jrule.internal.engine.excutioncontext.JRulePreconditionContext;
import org.openhab.automation.jrule.internal.engine.excutioncontext.JRuleStartupExecutionContext;
import org.openhab.automation.jrule.internal.engine.excutioncontext.JRuleThingExecutionContext;
import org.openhab.automation.jrule.internal.engine.excutioncontext.JRuleTimeTimerExecutionContext;
import org.openhab.automation.jrule.internal.engine.excutioncontext.JRuleTimedCronExecutionContext;
Expand All @@ -54,15 +55,16 @@ public class JRuleBuilder {
private Duration timedLock = null;
private Duration delayed = null;

final private List<PreCondition> preConditions = new ArrayList<>();
private final List<PreCondition> preConditions = new ArrayList<>();

final private List<WhenThingTrigger> whenThingTriggers = new ArrayList<>();
final private List<WhenChannelTrigger> whenChannelTriggers = new ArrayList<>();
final private List<WhenItemReceivedCommand> whenItemReceivedCommandTriggers = new ArrayList<>();
final private List<WhenItemChanged> whenItemChangedTriggers = new ArrayList<>();
final private List<WhenItemReceivedUpdate> whenItemReceivedUpdateTriggers = new ArrayList<>();
final private List<WhenCronTrigger> whenCronTriggers = new ArrayList<>();
final private List<WhenTimeTrigger> whenTimeTriggers = new ArrayList<>();
private final List<WhenStartupTrigger> whenStartupTriggers = new ArrayList<>();
private final List<WhenThingTrigger> whenThingTriggers = new ArrayList<>();
private final List<WhenChannelTrigger> whenChannelTriggers = new ArrayList<>();
private final List<WhenItemReceivedCommand> whenItemReceivedCommandTriggers = new ArrayList<>();
private final List<WhenItemChanged> whenItemChangedTriggers = new ArrayList<>();
private final List<WhenItemReceivedUpdate> whenItemReceivedUpdateTriggers = new ArrayList<>();
private final List<WhenCronTrigger> whenCronTriggers = new ArrayList<>();
private final List<WhenTimeTrigger> whenTimeTriggers = new ArrayList<>();

JRuleBuilder(JRuleEngine jRuleEngine, String ruleName, JRuleInvocationCallback invocationCallback) {
this.jRuleEngine = jRuleEngine;
Expand Down Expand Up @@ -105,6 +107,11 @@ public JRuleBuilder preCondition(String itemName, Condition condition) {
return this;
}

public JRuleBuilder whenStartupTrigger(int level) {
whenStartupTriggers.add(new WhenStartupTrigger(level));
return this;
}

public JRuleBuilder whenThingTrigger(String thingName, @Nullable JRuleThingStatus from,
@Nullable JRuleThingStatus to) {
whenThingTriggers.add(new WhenThingTrigger(thingName, from, to));
Expand Down Expand Up @@ -165,6 +172,15 @@ public boolean build() {
Optional.ofNullable(data.condition.neq)))
.toList();

whenStartupTriggers.forEach(data -> {
JRuleStartupExecutionContext context = new JRuleStartupExecutionContext(uid, logName, loggingTags,
invocationCallback, preconditionContexts, timedLock, delayed, data.level);
jRuleEngine.addToContext(context, enableRule);
jRuleEngine.ruleLoadingStatistics.addStartupTrigger();
ruleModuleEntry.addJRuleWhenStartupTrigger(context);
addedToContext.set(true);
});

whenThingTriggers.forEach(data -> {
JRuleThingExecutionContext context = new JRuleThingExecutionContext(uid, logName, loggingTags,
invocationCallback, Optional.ofNullable(data.thingName), Optional.ofNullable(data.from),
Expand Down Expand Up @@ -261,6 +277,9 @@ private JRuleItemExecutionContext.JRuleConditionContext toJRuleConditionContext(
private record PreCondition(String itemName, Condition condition) {
}

private record WhenStartupTrigger(int level) {
}

private record WhenThingTrigger(String thingName, JRuleThingStatus from, JRuleThingStatus to) {
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import org.openhab.automation.jrule.internal.engine.excutioncontext.JRuleChannelExecutionContext;
import org.openhab.automation.jrule.internal.engine.excutioncontext.JRuleExecutionContext;
import org.openhab.automation.jrule.internal.engine.excutioncontext.JRuleItemExecutionContext;
import org.openhab.automation.jrule.internal.engine.excutioncontext.JRuleStartupExecutionContext;
import org.openhab.automation.jrule.internal.engine.excutioncontext.JRuleThingExecutionContext;
import org.openhab.automation.jrule.internal.engine.excutioncontext.JRuleTimedExecutionContext;
import org.openhab.automation.jrule.internal.engine.timer.JRuleTimerExecutor;
Expand All @@ -63,6 +64,7 @@
import org.openhab.automation.jrule.rules.JRuleWhenItemChange;
import org.openhab.automation.jrule.rules.JRuleWhenItemReceivedCommand;
import org.openhab.automation.jrule.rules.JRuleWhenItemReceivedUpdate;
import org.openhab.automation.jrule.rules.JRuleWhenStartup;
import org.openhab.automation.jrule.rules.JRuleWhenThingTrigger;
import org.openhab.automation.jrule.rules.JRuleWhenTimeTrigger;
import org.openhab.automation.jrule.rules.event.JRuleEvent;
Expand All @@ -82,6 +84,7 @@

/**
* The {@link JRuleEngine}
* O *
*
* @author Joseph (Seaside) Hagberg - Initial Contribution
* @author Robert Delbrück - Refactoring
Expand Down Expand Up @@ -151,7 +154,7 @@ private void add(Method method, JRule jRule, boolean enableRule) {
logWarn("Skipping non-public method {} on class {}", method.getName(), jRule.getClass().getName());
return;
}
// Check if method is has none or a single parameter
// Check if method has none or a single parameter
if (method.getParameterCount() > 1) {
logWarn("Skipping method {} on class {}. Rule methods should have none or a single parameter",
method.getName(), jRule.getClass().getName());
Expand Down Expand Up @@ -223,6 +226,8 @@ private void add(Method method, JRule jRule, boolean enableRule) {
.orElse(null),
Optional.of(jRuleWhen.from()).filter(s -> s != JRuleThingStatus.THING_UNKNOWN).orElse(null),
Optional.of(jRuleWhen.to()).filter(s -> s != JRuleThingStatus.THING_UNKNOWN).orElse(null)));
Arrays.stream(method.getAnnotationsByType(JRuleWhenStartup.class))
.forEach(jRuleWhen -> jRuleBuilder.whenStartupTrigger(jRuleWhen.level()));

// Check if rule was actually activated, i.e. if triggers are present
if (!jRuleBuilder.build()) {
Expand Down Expand Up @@ -324,7 +329,8 @@ public boolean matchPrecondition(JRuleExecutionContext jRuleExecutionContext) {
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals(JRuleEventSubscriber.PROPERTY_ITEM_EVENT)
|| evt.getPropertyName().equals(JRuleEventSubscriber.PROPERTY_CHANNEL_EVENT)
|| evt.getPropertyName().equals(JRuleEventSubscriber.PROPERTY_THING_STATUS_EVENT)) {
|| evt.getPropertyName().equals(JRuleEventSubscriber.PROPERTY_THING_STATUS_EVENT)
|| evt.getPropertyName().equals(JRuleEventSubscriber.PROPERTY_STARTUP_EVENT)) {
fire((AbstractEvent) evt.getNewValue());
}
}
Expand Down Expand Up @@ -365,6 +371,14 @@ public boolean watchingForItem(String itemName) {
return b;
}

public boolean watchingForStartlevel(Integer startlevel) {
boolean b = this.contextList.stream().filter(context -> context instanceof JRuleStartupExecutionContext)
.map(context -> ((JRuleStartupExecutionContext) context))
.anyMatch(context -> context.getStartupLevel() == startlevel);
logDebug("watching for startup: '{}'? -> {}", startlevel, b);
return b;
}

public boolean watchingForChannel(String channel) {
boolean b = this.contextList.stream().filter(context -> context instanceof JRuleChannelExecutionContext)
.map(context -> ((JRuleChannelExecutionContext) context))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
* @author Arne Seime - Initial contribution
*/
public class JRuleLoadingStatistics {
private int numStartupTriggers;
private int numChannelTriggers;
private int numItemStateTriggers;
private int numTimedTriggers;
Expand Down Expand Up @@ -45,6 +46,10 @@ public void addItemStateTrigger() {
numItemStateTriggers++;
}

public void addStartupTrigger() {
numStartupTriggers++;
}

public void addTimedTrigger() {
numTimedTriggers++;
}
Expand Down Expand Up @@ -94,6 +99,11 @@ public String toString() {
b.append(String.format("Loaded %d thing triggers, change %d", numThingTriggers,
previous == null ? 0 : numThingTriggers - previous.numThingTriggers));

b.append("\n");
b.append("******** ");
b.append(String.format("Loaded %d startup triggers, change %d", numStartupTriggers,
previous == null ? 0 : numStartupTriggers - previous.numStartupTriggers));

int numDisabledRules = numRuleMethods - numEnabledRules;

if (numDisabledRules > 0) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/**
* Copyright (c) 2010-2023 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.automation.jrule.internal.engine.excutioncontext;

import java.time.Duration;
import java.util.List;

import org.openhab.automation.jrule.internal.engine.JRuleInvocationCallback;
import org.openhab.automation.jrule.rules.event.JRuleEvent;
import org.openhab.automation.jrule.rules.event.JRuleStartupEvent;
import org.openhab.core.events.AbstractEvent;
import org.openhab.core.events.system.StartlevelEvent;

/**
* The {@link JRuleStartupExecutionContext} - execution context for startup triggers
*
* @author Robert Delbrück
*/
public class JRuleStartupExecutionContext extends JRuleExecutionContext {

private final int startupLevel;

public JRuleStartupExecutionContext(String uid, String logName, String[] loggingTags,
JRuleInvocationCallback invocationCallback, List<JRulePreconditionContext> preconditionContextList,
Duration timedLock, Duration delayed, int startupLevel) {
super(uid, logName, loggingTags, invocationCallback, preconditionContextList, timedLock, delayed);
this.startupLevel = startupLevel;
}

@Override
public boolean match(AbstractEvent event, JRuleAdditionalCheckData checkData) {
if (!(event instanceof StartlevelEvent evt)) {
return false;
}
return startupLevel == evt.getStartlevel();
}

@Override
public JRuleEvent createJRuleEvent(AbstractEvent event) {
StartlevelEvent startlevelEvent = (StartlevelEvent) event;

return new JRuleStartupEvent((startlevelEvent).getStartlevel());
}

public int getStartupLevel() {
return startupLevel;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import org.openhab.core.events.Event;
import org.openhab.core.events.EventFilter;
import org.openhab.core.events.EventSubscriber;
import org.openhab.core.events.system.StartlevelEvent;
import org.openhab.core.items.events.GroupItemStateChangedEvent;
import org.openhab.core.items.events.ItemAddedEvent;
import org.openhab.core.items.events.ItemCommandEvent;
Expand Down Expand Up @@ -63,6 +64,7 @@ public class JRuleEventSubscriber implements EventSubscriber {
public static final String PROPERTY_THING_STATUS_EVENT = "THING_STATUS_EVENT";

private static final String LOG_NAME_SUBSCRIBER = "JRuleSubscriber";
public static final String PROPERTY_STARTUP_EVENT = "STARTUP_EVENT";
// status changes

private final Logger logger = LoggerFactory.getLogger(JRuleEventSubscriber.class);
Expand Down Expand Up @@ -92,6 +94,7 @@ public JRuleEventSubscriber() {
// subscribedEventTypes.add(ThingUpdatedEvent.TYPE);
subscribedEventTypes.add(ThingRemovedEvent.TYPE);
subscribedEventTypes.add(ThingStatusInfoChangedEvent.TYPE);
subscribedEventTypes.add(StartlevelEvent.TYPE);
}

@Override
Expand Down Expand Up @@ -188,6 +191,13 @@ private void processEvent(Event event) {
PROPERTY_THING_STATUS_EVENT, event.getTopic(), event.getPayload());
propertyChangeSupport.firePropertyChange(PROPERTY_THING_STATUS_EVENT, null, event);
}
} else if (event.getType().equals(StartlevelEvent.TYPE)) {
StartlevelEvent startlevelEvent = (StartlevelEvent) event;
if (jRuleEngine.watchingForStartlevel(startlevelEvent.getStartlevel())) {
JRuleLog.debug(logger, LOG_NAME_SUBSCRIBER, "Event processed as {}: topic {} payload: {}",
PROPERTY_STARTUP_EVENT, event.getTopic(), event.getPayload());
propertyChangeSupport.firePropertyChange(PROPERTY_STARTUP_EVENT, null, event);
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,15 @@
*/
package org.openhab.automation.jrule.internal.handler;

import java.util.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

import org.eclipse.jdt.annotation.NonNull;
Expand All @@ -24,12 +32,47 @@
import org.openhab.automation.jrule.items.JRuleItem;
import org.openhab.automation.jrule.items.JRuleItemRegistry;
import org.openhab.automation.jrule.rules.JRule;
import org.openhab.automation.jrule.rules.value.*;
import org.openhab.automation.jrule.rules.value.JRuleDateTimeValue;
import org.openhab.automation.jrule.rules.value.JRuleDecimalValue;
import org.openhab.automation.jrule.rules.value.JRuleHsbValue;
import org.openhab.automation.jrule.rules.value.JRuleNextPreviousValue;
import org.openhab.automation.jrule.rules.value.JRuleOnOffValue;
import org.openhab.automation.jrule.rules.value.JRuleOpenClosedValue;
import org.openhab.automation.jrule.rules.value.JRulePercentValue;
import org.openhab.automation.jrule.rules.value.JRulePlayPauseValue;
import org.openhab.automation.jrule.rules.value.JRulePointValue;
import org.openhab.automation.jrule.rules.value.JRuleQuantityValue;
import org.openhab.automation.jrule.rules.value.JRuleRawValue;
import org.openhab.automation.jrule.rules.value.JRuleRewindFastforwardValue;
import org.openhab.automation.jrule.rules.value.JRuleStopMoveValue;
import org.openhab.automation.jrule.rules.value.JRuleStringListValue;
import org.openhab.automation.jrule.rules.value.JRuleStringValue;
import org.openhab.automation.jrule.rules.value.JRuleUpDownValue;
import org.openhab.automation.jrule.rules.value.JRuleValue;
import org.openhab.core.events.EventPublisher;
import org.openhab.core.items.*;
import org.openhab.core.items.GenericItem;
import org.openhab.core.items.GroupItem;
import org.openhab.core.items.Item;
import org.openhab.core.items.ItemNotFoundException;
import org.openhab.core.items.ItemRegistry;
import org.openhab.core.items.events.ItemEvent;
import org.openhab.core.items.events.ItemEventFactory;
import org.openhab.core.library.types.*;
import org.openhab.core.library.types.DateTimeType;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.HSBType;
import org.openhab.core.library.types.NextPreviousType;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.OpenClosedType;
import org.openhab.core.library.types.PercentType;
import org.openhab.core.library.types.PlayPauseType;
import org.openhab.core.library.types.PointType;
import org.openhab.core.library.types.QuantityType;
import org.openhab.core.library.types.RawType;
import org.openhab.core.library.types.RewindFastforwardType;
import org.openhab.core.library.types.StopMoveType;
import org.openhab.core.library.types.StringListType;
import org.openhab.core.library.types.StringType;
import org.openhab.core.library.types.UpDownType;
import org.openhab.core.types.Command;
import org.openhab.core.types.State;
import org.openhab.core.types.UnDefType;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,14 @@

import org.openhab.automation.jrule.internal.engine.JRuleEngine;
import org.openhab.automation.jrule.internal.engine.excutioncontext.JRuleExecutionContext;
import org.openhab.automation.jrule.internal.engine.excutioncontext.JRuleStartupExecutionContext;
import org.openhab.automation.jrule.rules.JRule;
import org.openhab.automation.jrule.rules.JRuleWhenChannelTrigger;
import org.openhab.automation.jrule.rules.JRuleWhenCronTrigger;
import org.openhab.automation.jrule.rules.JRuleWhenItemChange;
import org.openhab.automation.jrule.rules.JRuleWhenItemReceivedCommand;
import org.openhab.automation.jrule.rules.JRuleWhenItemReceivedUpdate;
import org.openhab.automation.jrule.rules.JRuleWhenStartup;
import org.openhab.automation.jrule.rules.JRuleWhenThingTrigger;
import org.openhab.automation.jrule.rules.JRuleWhenTimeTrigger;
import org.openhab.core.automation.Action;
Expand Down Expand Up @@ -160,6 +162,14 @@ public void addJRuleWhenThingTrigger(JRuleExecutionContext context) {
ruleTriggers.add(triggerBuilder.build());
}

public void addJRuleWhenStartupTrigger(JRuleStartupExecutionContext context) {
executionContextList.add(context);
TriggerBuilder triggerBuilder = TriggerBuilder.create().withId("" + (triggerCounter++))
.withTypeUID(JRuleModuleUtil.toTriggerModuleUID(JRuleWhenStartup.class));

ruleTriggers.add(triggerBuilder.build());
}

public void addTags(String[] loggingTags) {
tags.addAll(Arrays.stream(loggingTags).collect(Collectors.toSet()));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.openhab.automation.jrule.rules.JRuleWhenItemChange;
import org.openhab.automation.jrule.rules.JRuleWhenItemReceivedCommand;
import org.openhab.automation.jrule.rules.JRuleWhenItemReceivedUpdate;
import org.openhab.automation.jrule.rules.JRuleWhenStartup;
import org.openhab.automation.jrule.rules.JRuleWhenThingTrigger;
import org.openhab.automation.jrule.rules.JRuleWhenTimeTrigger;
import org.openhab.core.automation.Module;
Expand All @@ -47,7 +48,8 @@ public class JRuleModuleHandlerFactory extends BaseModuleHandlerFactory {
JRuleModuleUtil.toTriggerModuleUID(JRuleWhenChannelTrigger.class),
JRuleModuleUtil.toTriggerModuleUID(JRuleWhenCronTrigger.class),
JRuleModuleUtil.toTriggerModuleUID(JRuleWhenTimeTrigger.class),
JRuleModuleUtil.toTriggerModuleUID(JRuleWhenThingTrigger.class));
JRuleModuleUtil.toTriggerModuleUID(JRuleWhenThingTrigger.class),
JRuleModuleUtil.toTriggerModuleUID(JRuleWhenStartup.class));
private JRuleRuleProvider jRuleRuleProvider;

@Activate
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.openhab.automation.jrule.rules.JRuleWhenItemChange;
import org.openhab.automation.jrule.rules.JRuleWhenItemReceivedCommand;
import org.openhab.automation.jrule.rules.JRuleWhenItemReceivedUpdate;
import org.openhab.automation.jrule.rules.JRuleWhenStartup;
import org.openhab.automation.jrule.rules.JRuleWhenThingTrigger;
import org.openhab.automation.jrule.rules.JRuleWhenTimeTrigger;
import org.openhab.core.automation.type.ModuleType;
Expand Down Expand Up @@ -52,7 +53,8 @@ public class JRuleModuleTypeProvider implements ModuleTypeProvider {
JRuleModuleUtil.toTriggerModuleUID(JRuleWhenTimeTrigger.class),
new JRuleTriggerType(JRuleWhenTimeTrigger.class),
JRuleModuleUtil.toTriggerModuleUID(JRuleWhenThingTrigger.class),
new JRuleTriggerType(JRuleWhenThingTrigger.class));
new JRuleTriggerType(JRuleWhenThingTrigger.class),
JRuleModuleUtil.toTriggerModuleUID(JRuleWhenStartup.class), new JRuleTriggerType(JRuleWhenStartup.class));

@SuppressWarnings("unchecked")
@Override
Expand Down
Loading
Loading