📄 abstractprocesscontroller.java
字号:
package net.sf.dz.controller;import java.util.HashSet;import java.util.Iterator;import java.util.Set;import org.freehold.jukebox.logger.LogAware;import org.freehold.jukebox.logger.LogChannel;/** * An abstract process controller. * * <p> * * Implements the functionality common for the process controllers and * configurable objects. * * @author Copyright © <a href="mailto:vt@freehold.crocodile.org"> Vadim Tkachenko</a> 2001-2002 * @version $Id: AbstractProcessController.java,v 1.6 2004/06/28 20:35:46 vtt Exp $ */public abstract class AbstractProcessController extends LogAware implements ProcessController { /** * Log channel to use. */ public static final LogChannel CH_APC = new LogChannel("AbstractPC"); /** * The process setpoint. */ private double setpoint; /** * When was the process variable last modified. */ private long lastModified; /** * The current process variable value. */ private double pv; /** * Set of process controller listeners. */ private Set listenerSet = new HashSet(); /** * Last known signal. * * This is used to support the listener notification. */ private Double lastKnownSignal = null; /** * Read the setpoint value from the configuration. * * @exception Throwable if there's a problem with configuration. */ protected final void configure() throws Throwable { // VT: NOTE: Due to the fact that the configuration used may not // contain a setpoint (that would be illogical in some contexts), // we'll just agree to have the default setpoint set to 24. In the // context of this project this means 24C, or about 75F - a little // bit too low for cooling, a little bit high for heating, but // nonetheless acceptable for lack of better default. // VT: FIXME: Sure, 24 is a rather funny value for an *abstract* // process controller... Have to move this into the caller's // configuration. setpoint = getConfiguration().getDouble(getConfigurationRoot() + ".setpoint", 24.0); complain(LOG_DEBUG, CH_APC, "Setpoint: " + getSetpoint()); configure2(); } /** * Configurate the subclass. * * @exception Throwable if there's a problem with configuration. */ protected abstract void configure2() throws Throwable; /** * Get last modified time. * * @return Time when the data was last modified. */ protected final long getLastModified() { return lastModified; } /** * Get last known signal value. * * @return Last known signal value, or <code>null</code> if it is not * yet available. */ protected final Double getLastKnownSignal() { return lastKnownSignal; } /** * {@inheritDoc} */ public final void setSetpoint(final double setpoint) { this.setpoint = setpoint; setpointChanged(setpoint); wrapCompute(); } /** * {@inheritDoc} */ public final double getSetpoint() { return setpoint; } /** * {@inheritDoc} */ public final double getProcessVariable() { return pv; } /** * {@inheritDoc} */ public final synchronized double getError() { return (pv - setpoint); } /** * Compute the controller output given the current value of the process * variable at a given time. * * @param time When this measurement was taken. * * @param pv Process variable. * * @return A computed controller output (corrective action). */ public final synchronized double compute(final long time, final double pv) { // Just check if we're configured getConfiguration(); this.lastModified = time; this.pv = pv; return wrapCompute(); } /** * Wrap the {@link #compute compute()} method to support the listeners * without incurring complexity on the subclasses. * * @return Result of {@link #compute compute()}. */ private double wrapCompute() { double result = compute(); lastKnownSignal = new Double(result); try { processControllerStatusChanged(); } catch (Throwable t) { complain(LOG_WARNING, CH_APC, "wrapCompute:", t); } return result; } /** * Compute the controller output based on the known state. * * @return controller output. */ protected abstract double compute(); /** * {@inheritDoc} */ public final void addListener(final ProcessControllerListener l) { listenerSet.add(l); } /** * {@inheritDoc} */ public final void removeListener(final ProcessControllerListener l) { listenerSet.remove(l); } /** * {@inheritDoc} */ private void processControllerStatusChanged() { ProcessControllerStatus status = getStatus(); for (Iterator i = listenerSet.iterator(); i.hasNext();) { ((ProcessControllerListener) i.next()).processControllerStatusChanged(this, status); } } /** * {@inheritDoc} */ private void setpointChanged(final double value) { for (Iterator i = listenerSet.iterator(); i.hasNext();) { ((ProcessControllerListener) i.next()).setpointChanged(this, value); } } /** * Get the extended process controller status. * * This implementation is provided for lazy programmers and returns only * the information that is available for all the subclasses - the last * known output signal, if it is available, or string "NaN", if not. * * @return Status object. */ public ProcessControllerStatus getStatus() { return new ProcessControllerStatus(getError(), (lastKnownSignal == null) ? Double.NaN : lastKnownSignal.doubleValue()); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -