⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ac_controller.java

📁 这是一个以JAVA编写的程序,本人还没有试过,是一个简单的温度控制系统
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
package net.sf.dz.device.actuator.impl;import java.util.Iterator;import java.util.HashSet;import java.util.Set;import org.freehold.jukebox.conf.Configuration;import org.freehold.jukebox.service.ActiveService;import org.freehold.jukebox.service.PassiveService;import org.freehold.jukebox.service.RunnableService;import org.freehold.jukebox.logger.LogAware;import org.freehold.jukebox.logger.LogChannel;import org.freehold.jukebox.util.SimpleQueue;import net.sf.dz.device.actuator.AC;import net.sf.dz.device.actuator.ACDriver;import net.sf.dz.event.ACListener;import net.sf.dz.util.ObjectFactory;/** * The A/C controller implementation. * * Ideally, the only thing missing from this implementation should be the * actual hardware switch drivers. However, the multistage AC may require a * different logic. Let's try to generalize implementation so this one's * enough. * * <h2>Controlling multistage units</h2> * * The single stage system will switch on as soon as the demand rises above * 0, and shut off as soon as it reaches 0 again. The demand is always * positive, and the logic in the zone controller <strong>must</strong> take * the {@link #getMode current operating mode} into account. * * <p> * * For the multistage system, the first stage will do the same, and the * second stage will be controlled by the first entries in {@link * #stageHeating stageHeating} and {@link #stageCooling stageCooling}, and * so on. *  * <p> * * One more complication is necessary because the hardware usually doesn't * like the rapid sequence of commands like changing the mode from heat to * cool and back, and changing the stage. In order to eliminate the * possibility of the hardware damage, the state machine introducing the * delays between the control actions is used. * * <p> * * The rules are: * * <ul> * * <li> The command to change the mode will cause the fan and the *      compressor to stop and wait for a preset delay if they are not *      stopped, then the mode change will be performed. * * <li> The command to change the stage will be executed no sooner than *      the preset delay after the last stage change or mode change *      operation was carried out. * * <li> The compressor will not switch on before the fan. * * <li> The fan will not switch off before the compressor. * * </ul> * * The actual commands relayed to hardware will have nothing to do with the * abstraction state. If there's a problem with the logic and the * abstraction is oscillating, the hardware will perform the commands, but * with the specified delays, and the size of the queue will grow. * * @author Copyright &copy; <a href="mailto:vt@freehold.crocodile.org"> Vadim Tkachenko</a> 2001 * @version $Id: AC_Controller.java,v 1.8 2004/06/28 20:35:48 vtt Exp $ */public class AC_Controller extends ActiveService implements AC {    public static final LogChannel CH_AC = new LogChannel("AC/Controller");        /**     * The hardware driver.     */    private ACDriver driver;        /**     * Set of limits to switch to the next heating stage.     *     * The size of this set determines how many stages does this device     * support when heating. Single stage system will have no entries,     * two-stage will have one entryand so on.     *     * @see #stageCooling     */    private double stageHeating[] = new double[0];        /**     * @see #stageHeating     */    private double stageCooling[] = new double[0];        /**     * The A/C abstraction status.     *     * This status is updated immediately.     */    private ACState abstraction = new ACState();        /**     * The A/C hardware status.     *     * This status is updated as the commands are carried out.     */    private ACState hardware = new ACState();        /**     * Delay parameters.     */    private Time delay = new Time();        /**     * Timestamps.     */    private Time timestamp = new Time();        /**     * The command queue.     */    private TransparentQueue theQueue = new TransparentQueue();         private Set listenerSet = new HashSet();        public int getMode() {            return abstraction.mode;    }        public void setMode(int mode) {            if ( abstraction.mode == mode ) {                    return;        }            abstraction.mode = mode;        enqueue(new ChangeMode(mode));                modeChanged(mode);        //complain(LOG_INFO, CH_AC, "Mode set: " + mode);    }        private synchronized void enqueue(Command command) {            // VT: FIXME 2: Turns out that if we go through the iterator,        // ConcurrentModificationException may be thrown - I'd guess that is        // a result of theQueue.waitObject() in execute() working. Since the        // commands are not flushed from the queue anyway, let's make this        // code inactive for the moment, and figure out both what to flush        // and how to handle the concurrent modification later.                if ( false ) {                    // VT: FIXME 1: See if there are other commands of this kind in            // the queue and flush them. Afterthought: this is not so simple            // because there may be secondary commands in the queue that            // were caused by the primary command. If the primary command is            // removed, but secondary commands are not, the result is a            // havoc.                        int offset = 0;                        for ( Iterator i = theQueue.iterator(); i.hasNext(); ) {                            Command queuedCommand = (Command)i.next();                                complain(LOG_DEBUG, CH_AC, "Queue: @" + (offset++) + ": " + queuedCommand);                                if ( false )                if ( queuedCommand.getClass().equals(command.getClass()) ) {                                    complain(LOG_INFO, CH_AC, "Queued command flushed: " + queuedCommand);                    i.remove();                }            }                        complain(LOG_NOTICE, CH_AC, "Queue: @" + offset + ": " + command);        } else {                    complain(LOG_NOTICE, CH_AC, "Queued: " + command);        }                theQueue.put(command);    }        protected void configure() throws Throwable {        delay.mode = getConfiguration().getLong(getConfigurationRoot() + ".delay.mode", 1000);        delay.stage = getConfiguration().getLong(getConfigurationRoot() + ".delay.stage", 1000);        delay.fan = getConfiguration().getLong(getConfigurationRoot() + ".delay.fan", 1000);                // VT: FIXME: I can understand the settings relevant for the        // internal operation of the HVAC unit belonging here, but how        // justified is the mode? Shouldn't it be in Unit instead? This will        // be a painful change, though...        String sMode = getConfiguration().getString(getConfigurationRoot() + ".mode", "cool");                // VT: This is required so the initial mode is properly impressed        // upon the hardware (for example, in case when the last instance of        // the controller has crashed for some reason and the switches are        // still in the running position).        //        // Now, since we can't talk to the hardware at this point (we have        // not been started yet, and the driver is not available), we have        // to assign the proper value to the abstraction.mode and remember        // to properly set the mode when it is possible (in startup()).                if ( "heat".equalsIgnoreCase(sMode) ) {                    abstraction.mode = 1;        } else if ( "cool".equalsIgnoreCase(sMode) ) {                    abstraction.mode = -1;        } else if ( "off".equalsIgnoreCase(sMode) ) {                    abstraction.mode = 0;                    } else {                    complain(LOG_WARNING, CH_AC, "Invalid mode (" + sMode + "), left default (cool)");            abstraction.mode = -1;        }                // Take care of the driver                String driverClassName = getConfiguration().getString(getConfigurationRoot() + ".driver.class");                driver = (ACDriver)ObjectFactory.instantiate(driverClassName, ACDriver.class);        if ( driver instanceof LogAware ) {                    ((LogAware)driver).setLogger(getLogger());        }                driver.configure(getConfigurationRoot() + ".driver", getConfiguration());                if ( driver instanceof RunnableService ) {                    if ( !((RunnableService)driver).start().waitFor() ) {                            throw new IllegalStateException("Unable to start the driver, check the logs");            }        }    }        public boolean isRunning() {            return (abstraction.stage != 0);    }        /**     * Receive a notification about a change in demand.     *     * The demand change determines the behavior of the unit - the cooler     * switches on if the demand raises above 0, the heater switches on as     * the demand drops below 0. It depends on the current mode (cooling or     * heating) and not necessarily linear.     *     * @param factor Demand factor. Positive values determine need for     * cooling, negative - for heating.     */    public synchronized void demand(double factor) {            int stage = abstraction.stage;        double speed = abstraction.speed;                // VT: FIXME: The following describes a single stage system                if ( factor > 0 && !isRunning() ) {                    complain(LOG_NOTICE, CH_AC, "Switching ON " + getModeString());            abstraction.stage = 1;            abstraction.speed = 1;        } else if ( factor <= 0 && isRunning() ) {                    complain(LOG_NOTICE, CH_AC, "Switching OFF " + getModeString());            abstraction.stage = 0;            abstraction.speed = 0;        }                demandChanged(factor);                // Decide what to do first - compressor or the fan.                if ( abstraction.stage == 0 ) {                    // Need to process the stage first - we're shutting off            if ( abstraction.stage != stage ) {                            enqueue(new ChangeStage(abstraction.stage));                                stageChanged(abstraction.stage);            }            if ( abstraction.speed != speed ) {                            enqueue(new ChangeFanSpeed(abstraction.speed));                                fanSpeedChanged(abstraction.speed);            }        } else {                    // Need to process the fan first - we're starting up            if ( abstraction.speed != speed ) {                            enqueue(new ChangeFanSpeed(abstraction.speed));                                fanSpeedChanged(abstraction.speed);            }            if ( abstraction.stage != stage ) {                            enqueue(new ChangeStage(abstraction.stage));                                stageChanged(abstraction.stage);            }        }    }        private String getModeString() {            StringBuffer sb = new StringBuffer("(mode: ");                switch ( abstraction.mode ) {                    case -1:                            sb.append("cooling");                break;                            case 0:                            sb.append("off");                break;                            case 1:                            sb.append("heating");                break;                            default:                            throw new IllegalStateException("Invalid abstraction mode: " + abstraction.mode);        }                sb.append(")");                return sb.toString();        }        /**     * Add the listener.     *     * @param listener The object to be notified about the state changes.     */    public final void addListener(ACListener listener) {            listenerSet.add(listener);    }        /**     * Remove the listener.     */    public final void removeListener(ACListener listener) {            listenerSet.remove(listener);    }        /**     * Broadcast the notification about the change in demand.     *     * @param value New demand value.     */    private final void demandChanged(double value) {            for ( Iterator i = listenerSet.iterator(); i.hasNext(); ) {                    ((ACListener)i.next()).demandChanged(this, value);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -