]> git.basschouten.com Git - openhab-addons.git/blob
32cc4388492c94cf4a1516a0073190126d9a4eb6
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
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
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.digitalstrom.internal.lib.sensorjobexecutor;
14
15 import java.util.Comparator;
16 import java.util.Iterator;
17 import java.util.PriorityQueue;
18
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;
24
25 /**
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.
28  *
29  * @author Michael Ochel - Initial contribution
30  * @author Matthias Siegele - Initial contribution
31  */
32 public class CircuitScheduler {
33
34     private final Logger logger = LoggerFactory.getLogger(CircuitScheduler.class);
35
36     private class SensorJobComparator implements Comparator<SensorJob> {
37
38         @Override
39         public int compare(SensorJob job1, SensorJob job2) {
40             return ((Long) job1.getInitalisationTime()).compareTo(job2.getInitalisationTime());
41         }
42     }
43
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;
48
49     /**
50      * Creates a new {@link CircuitScheduler}.
51      *
52      * @param meterDSID must not be null
53      * @param config must not be null
54      * @throws IllegalArgumentException if the meterDSID is null
55      */
56     public CircuitScheduler(DSID meterDSID, Config config) {
57         if (meterDSID == null) {
58             throw new IllegalArgumentException("The meterDSID must not be null!");
59         }
60         this.meterDSID = meterDSID;
61         this.config = config;
62     }
63
64     /**
65      * Creates a new {@link CircuitScheduler} and add the first {@link SensorJob} to this {@link CircuitScheduler}.
66      *
67      * @param sensorJob to add, must not be null
68      * @param config must not be null
69      */
70     public CircuitScheduler(SensorJob sensorJob, Config config) {
71         this.meterDSID = sensorJob.getMeterDSID();
72         this.sensorJobQueue.add(sensorJob);
73         this.config = config;
74         logger.debug("create circuitScheduler: {} and add sensorJob: {}", this.getMeterDSID(),
75                 sensorJob.getDSID().toString());
76     }
77
78     /**
79      * Returns the meterDSID of the dS-Meter in which the {@link SensorJob}s will be executed.
80      *
81      * @return meterDSID
82      */
83     public DSID getMeterDSID() {
84         return this.meterDSID;
85     }
86
87     /**
88      * Adds a new SensorJob to this {@link CircuitScheduler}, if no {@link SensorJob} with a higher priority exists.
89      *
90      * @param sensorJob to add
91      */
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(),
99                         this.getMeterDSID());
100             } else {
101                 logger.debug("sensorJob: {} allready exist with a higher priority", sensorJob.getDSID());
102             }
103         }
104     }
105
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()) {
112                         iter.remove();
113                         sensorJobQueue.add(sensorJob);
114                         return true;
115                     }
116                 }
117             }
118         }
119         return false;
120     }
121
122     /**
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.
125      *
126      * @return next SensorJob or null
127      */
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();
133             } else {
134                 return null;
135             }
136         }
137     }
138
139     /**
140      * Returns the time when the next {@link SensorJob} can be executed.
141      *
142      * @return next SesnorJob execution time
143      */
144     public Long getNextExecutionTime() {
145         return this.nextExecutionTime;
146     }
147
148     /**
149      * Returns the delay when the next {@link SensorJob} can be executed.
150      *
151      * @return next SesnorJob execution delay
152      */
153     public Long getNextExecutionDelay() {
154         long delay = this.nextExecutionTime - System.currentTimeMillis();
155         return delay > 0 ? delay : 0;
156     }
157
158     /**
159      * Removes all {@link SensorJob} of a specific {@link Device} with the given {@link DSID}.
160      *
161      * @param dSID of the device
162      */
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)) {
168                     iter.remove();
169                     logger.debug("Remove SensorJob with ID {}.", job.getID());
170                 }
171             }
172         }
173     }
174
175     /**
176      * Removes the {@link SensorJob} with the given ID .
177      *
178      * @param id of the {@link SensorJob}
179      */
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)) {
185                     iter.remove();
186                     logger.debug("Remove SensorJob with ID {}.", id);
187                     return;
188                 }
189             }
190             logger.debug("No SensorJob with ID {} found, cannot remove a not existing SensorJob.", id);
191         }
192     }
193
194     /**
195      * Returns true, if there are no more {@link SensorJob}s to execute, otherwise false.
196      *
197      * @return no more SensorJobs? (true | false)
198      */
199     public boolean noMoreJobs() {
200         synchronized (sensorJobQueue) {
201             return this.sensorJobQueue.isEmpty();
202         }
203     }
204 }