2 * Copyright (c) 2010-2023 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.digitalstrom.internal.lib.sensorjobexecutor;
15 import java.util.Comparator;
16 import java.util.Iterator;
17 import java.util.PriorityQueue;
19 import org.openhab.binding.digitalstrom.internal.lib.config.Config;
20 import org.openhab.binding.digitalstrom.internal.lib.sensorjobexecutor.sensorjob.SensorJob;
21 import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.impl.DSID;
22 import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory;
26 * This {@link CircuitScheduler} represents a circuit in the digitalSTROM-System and manages the priorities and
27 * execution times for the {@link SensorJob}s on this circuit.
29 * @author Michael Ochel - Initial contribution
30 * @author Matthias Siegele - Initial contribution
32 public class CircuitScheduler {
34 private final Logger logger = LoggerFactory.getLogger(CircuitScheduler.class);
36 private class SensorJobComparator implements Comparator<SensorJob> {
39 public int compare(SensorJob job1, SensorJob job2) {
40 return ((Long) job1.getInitalisationTime()).compareTo(job2.getInitalisationTime());
44 private final DSID meterDSID;
45 private long nextExecutionTime = System.currentTimeMillis();
46 private final PriorityQueue<SensorJob> sensorJobQueue = new PriorityQueue<>(10, new SensorJobComparator());
47 private final Config config;
50 * Creates a new {@link CircuitScheduler}.
52 * @param meterDSID must not be null
53 * @param config must not be null
54 * @throws IllegalArgumentException if the meterDSID is null
56 public CircuitScheduler(DSID meterDSID, Config config) {
57 if (meterDSID == null) {
58 throw new IllegalArgumentException("The meterDSID must not be null!");
60 this.meterDSID = meterDSID;
65 * Creates a new {@link CircuitScheduler} and add the first {@link SensorJob} to this {@link CircuitScheduler}.
67 * @param sensorJob to add, must not be null
68 * @param config must not be null
70 public CircuitScheduler(SensorJob sensorJob, Config config) {
71 this.meterDSID = sensorJob.getMeterDSID();
72 this.sensorJobQueue.add(sensorJob);
74 logger.debug("create circuitScheduler: {} and add sensorJob: {}", this.getMeterDSID(),
75 sensorJob.getDSID().toString());
79 * Returns the meterDSID of the dS-Meter in which the {@link SensorJob}s will be executed.
83 public DSID getMeterDSID() {
84 return this.meterDSID;
88 * Adds a new SensorJob to this {@link CircuitScheduler}, if no {@link SensorJob} with a higher priority exists.
90 * @param sensorJob to add
92 public void addSensorJob(SensorJob sensorJob) {
93 synchronized (sensorJobQueue) {
94 if (!this.sensorJobQueue.contains(sensorJob)) {
95 sensorJobQueue.add(sensorJob);
96 logger.debug("Add sensorJob: {} to circuitScheduler: {}", sensorJob.toString(), this.getMeterDSID());
97 } else if (checkSensorJobPrio(sensorJob)) {
98 logger.debug("add sensorJob: {} with higher priority to circuitScheduler: {}", sensorJob.toString(),
101 logger.debug("sensorJob: {} allready exist with a higher priority", sensorJob.getDSID());
106 private boolean checkSensorJobPrio(SensorJob sensorJob) {
107 synchronized (sensorJobQueue) {
108 for (Iterator<SensorJob> iter = sensorJobQueue.iterator(); iter.hasNext();) {
109 SensorJob existSensorJob = iter.next();
110 if (existSensorJob.equals(sensorJob)) {
111 if (sensorJob.getInitalisationTime() < existSensorJob.getInitalisationTime()) {
113 sensorJobQueue.add(sensorJob);
123 * Returns the next {@link SensorJob} which can be executed or null, if there are no more {@link SensorJob} to
124 * execute or the wait time between the {@link SensorJob}s executions has not expired yet.
126 * @return next SensorJob or null
128 public SensorJob getNextSensorJob() {
129 synchronized (sensorJobQueue) {
130 if (sensorJobQueue.peek() != null && this.nextExecutionTime <= System.currentTimeMillis()) {
131 nextExecutionTime = System.currentTimeMillis() + config.getSensorReadingWaitTime();
132 return sensorJobQueue.poll();
140 * Returns the time when the next {@link SensorJob} can be executed.
142 * @return next SesnorJob execution time
144 public Long getNextExecutionTime() {
145 return this.nextExecutionTime;
149 * Returns the delay when the next {@link SensorJob} can be executed.
151 * @return next SesnorJob execution delay
153 public Long getNextExecutionDelay() {
154 long delay = this.nextExecutionTime - System.currentTimeMillis();
155 return delay > 0 ? delay : 0;
159 * Removes all {@link SensorJob} of a specific {@link Device} with the given {@link DSID}.
161 * @param dSID of the device
163 public void removeSensorJob(DSID dSID) {
164 synchronized (sensorJobQueue) {
165 for (Iterator<SensorJob> iter = sensorJobQueue.iterator(); iter.hasNext();) {
166 SensorJob job = iter.next();
167 if (job.getDSID().equals(dSID)) {
169 logger.debug("Remove SensorJob with ID {}.", job.getID());
176 * Removes the {@link SensorJob} with the given ID .
178 * @param id of the {@link SensorJob}
180 public void removeSensorJob(String id) {
181 synchronized (sensorJobQueue) {
182 for (Iterator<SensorJob> iter = sensorJobQueue.iterator(); iter.hasNext();) {
183 SensorJob job = iter.next();
184 if (job.getID().equals(id)) {
186 logger.debug("Remove SensorJob with ID {}.", id);
190 logger.debug("No SensorJob with ID {} found, cannot remove a not existing SensorJob.", id);
195 * Returns true, if there are no more {@link SensorJob}s to execute, otherwise false.
197 * @return no more SensorJobs? (true | false)
199 public boolean noMoreJobs() {
200 synchronized (sensorJobQueue) {
201 return this.sensorJobQueue.isEmpty();