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

Added rule rest endpoint and backend operation for rule execution simulation #2125

Merged
merged 18 commits into from
Apr 11, 2021
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
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 @@ -17,10 +17,12 @@
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.ZonedDateTime;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import javax.annotation.security.RolesAllowed;
Expand All @@ -47,6 +49,7 @@
import org.openhab.core.automation.ManagedRuleProvider;
import org.openhab.core.automation.Module;
import org.openhab.core.automation.Rule;
import org.openhab.core.automation.RuleExecution;
import org.openhab.core.automation.RuleManager;
import org.openhab.core.automation.RuleRegistry;
import org.openhab.core.automation.Trigger;
Expand All @@ -70,6 +73,7 @@
import org.openhab.core.io.rest.RESTConstants;
import org.openhab.core.io.rest.RESTResource;
import org.openhab.core.io.rest.Stream2JSONInputStream;
import org.openhab.core.library.types.DateTimeType;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
Expand Down Expand Up @@ -339,6 +343,22 @@ public Response getTriggers(@PathParam("ruleUID") @Parameter(description = "rule
}
}

@GET
@Path("/simulation")
@Produces(MediaType.APPLICATION_JSON)
@Operation(operationId = "getRuleSimulation", summary = "Simulates the executions for the rules within the schedule.", responses = {
cweitkamp marked this conversation as resolved.
Show resolved Hide resolved
@ApiResponse(responseCode = "200", description = "OK", content = @Content(array = @ArraySchema(schema = @Schema(implementation = RuleExecution.class)))) })
public Response simulateRules(@QueryParam("from") String from, @QueryParam("until") String until) {
final Stream<RuleExecution> ruleExecutions = ruleManager.simulateRuleExecutions(parseTime(from),
parseTime(until));
return Response.ok(ruleExecutions.collect(Collectors.toList())).build();
}

private static ZonedDateTime parseTime(String sTime) {
final DateTimeType dateTime = new DateTimeType(sTime);
return dateTime.getZonedDateTime();
}

@GET
@Path("/{ruleUID}/conditions")
@Produces(MediaType.APPLICATION_JSON)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/**
* Copyright (c) 2010-2021 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.core.automation;

import java.util.Date;

import org.eclipse.jdt.annotation.NonNullByDefault;

/**
* Expected execution of an {@link Rule}.
*
* @author Sönke Küper - Initial contribution
*/
@NonNullByDefault
public final class RuleExecution implements Comparable<RuleExecution> {

private final Date date;
private final Rule rule;

/**
* Creates an new {@link RuleExecution}.
*
* @param date The time when the rule will be executed.
* @param rule The rule that will be executed.
*/
public RuleExecution(Date date, Rule rule) {
this.date = date;
this.rule = rule;
}

/**
* Returns the time when the rule will be executed.
*/
public Date getDate() {
return date;
}

/**
* Returns the rule that will be executed.
*/
public Rule getRule() {
return rule;
}

@Override
public int compareTo(RuleExecution o) {
return this.date.compareTo(o.getDate());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@
*/
package org.openhab.core.automation;

import java.time.ZonedDateTime;
import java.util.Date;
import java.util.Map;
import java.util.stream.Stream;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
Expand Down Expand Up @@ -92,4 +95,13 @@ public interface RuleManager {
* @param context the context that is passed to the conditions and the actions of the rule.
*/
void runNow(String uid, boolean considerConditions, @Nullable Map<String, Object> context);

/**
* Simulates the execution of all rules with tag 'Schedule' for the given time interval.
* The result is sorted ascending by execution time.
*
* @param untilDate {@link Date} until the executions should be simulated.
cweitkamp marked this conversation as resolved.
Show resolved Hide resolved
* @return A {@link Stream} with all expected {@link RuleExecution}.
*/
Stream<RuleExecution> simulateRuleExecutions(ZonedDateTime from, ZonedDateTime until);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/**
* Copyright (c) 2010-2021 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.core.automation.handler;

import java.time.ZonedDateTime;

import org.eclipse.jdt.annotation.NonNullByDefault;

/**
* {@link ConditionHandler} that evaluates, if the current time satisfies an specified condition.
*
* @author Sönke Küper - Initial contribution
*/
@NonNullByDefault
public interface TimeBasedConditionHandler extends ConditionHandler {

/**
* Checks if this condition is satisfied for the given time.
*
* @param time The time to check.
* @return <code>true</code> if and only if the given time satisfies this condition.
*/
public abstract boolean isSatisfiedAt(ZonedDateTime time);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* Copyright (c) 2010-2021 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.core.automation.handler;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.scheduler.SchedulerTemporalAdjuster;

/**
* Marker Interface for an {@link TriggerHandler} that contains an time based execution.
*
* @author Sönke Küper - Initial contribution
*/
@NonNullByDefault
public interface TimeBasedTriggerHandler extends TriggerHandler {

/**
* Returns the {@link SchedulerTemporalAdjuster} which can be used to determine the next execution times.
*/
@Nullable
public abstract SchedulerTemporalAdjuster getTemporalAdjuster();
cweitkamp marked this conversation as resolved.
Show resolved Hide resolved
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
*/
package org.openhab.core.automation.internal;

import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
Expand All @@ -28,6 +29,7 @@
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
Expand All @@ -36,6 +38,7 @@
import org.openhab.core.automation.Module;
import org.openhab.core.automation.ModuleHandlerCallback;
import org.openhab.core.automation.Rule;
import org.openhab.core.automation.RuleExecution;
import org.openhab.core.automation.RuleManager;
import org.openhab.core.automation.RuleRegistry;
import org.openhab.core.automation.RuleStatus;
Expand Down Expand Up @@ -694,7 +697,8 @@ private void unregister(WrappedRule r) {
* @return handler that processing this module. Could be {@code null} if the {@link ModuleHandlerFactory} is not
* available.
*/
private @Nullable ModuleHandler getModuleHandler(Module m, String ruleUID) {
@Nullable
ModuleHandler getModuleHandler(Module m, String ruleUID) {
String moduleTypeId = m.getTypeUID();
ModuleHandlerFactory mhf = getModuleHandlerFactory(moduleTypeId);
if (mhf == null || mtRegistry.get(moduleTypeId) == null) {
Expand Down Expand Up @@ -1471,4 +1475,9 @@ private boolean mustTrigger(Rule r) {
public boolean isStarted() {
return started;
}

@Override
public Stream<RuleExecution> simulateRuleExecutions(ZonedDateTime from, ZonedDateTime until) {
return new RuleExecutionSimulator(this.ruleRegistry, this).simulateRuleExecutions(from, until);
}
}
Loading