ac_controller.java
来自「这是一个以JAVA编写的程序,本人还没有试过,是一个简单的温度控制系统」· Java 代码 · 共 793 行 · 第 1/2 页
JAVA
793 行
} } /** * Broadcast the notification about the change in the running mode. * * @param stage New running mode. */ private final void modeChanged(int mode) { for ( Iterator i = listenerSet.iterator(); i.hasNext(); ) { ((ACListener)i.next()).modeChanged(this, mode); } } /** * Broadcast the notification about the change in the running stage. * * @param stage New running stage. */ private final void stageChanged(int stage) { for ( Iterator i = listenerSet.iterator(); i.hasNext(); ) { ((ACListener)i.next()).stageChanged(this, stage); } } private final void fanSpeedChanged(double value) { for ( Iterator i = listenerSet.iterator(); i.hasNext(); ) { ((ACListener)i.next()).fanSpeedChanged(this, value); } } protected void startup() throws Throwable { if ( driver instanceof PassiveService ) { PassiveService ps = (PassiveService)driver; if ( false ) if ( !ps.start().waitFor() ) { throw new IllegalStateException("Could not start the AC driver, check the logs"); } // VT: FIXME: Check if it works as a dependant later // addDependant(ps); } // Now we can set the mode int mode = abstraction.mode; // Skew the mode so setMode() will work properly abstraction.mode = 2; setMode(mode); // Let's be nice and tell the possible listeners about our stage and // speed, 'cause otherwise they won't know... stageChanged(hardware.stage); fanSpeedChanged(hardware.speed); } protected void execute() throws Throwable { while ( isEnabled() ) { try { Command c = (Command)theQueue.waitObject(10000); complain(LOG_NOTICE, CH_AC, "Executing: " + c); boolean ok = false; while ( !ok ) { try { c.run(); ok = true; } catch ( Throwable t ) { complain(LOG_ERR, CH_AC, "Failed to execute " + c + ", cause:", t); } if ( !ok ) { // Let's give them some time to come around // VT: FIXME: Rerty count shouldn't be exceeded, // otherwise we'll just be stuck here forever Thread.sleep(1000); } } complain(LOG_INFO, CH_AC, "Completed: " + c); } catch ( InterruptedException iex ) { if ( "heartbeat".equals(iex.getMessage()) ) { // Send the current status to the listeners so they don't // become frustrated modeChanged(hardware.mode); stageChanged(hardware.stage); fanSpeedChanged(hardware.speed); } else { throw iex; } } } } protected void shutdown(Throwable cause) throws Throwable { if ( driver instanceof PassiveService ) { ((PassiveService)driver).stop().waitFor(); } complain(LOG_ERR, CH_AC, "IMPLEMENT THE SHUTDOWN: SWITCH OFF EVERYTHING"); } protected abstract class Command { abstract void run() throws Throwable; } protected class ChangeMode extends Command { int mode; ChangeMode(int mode) { if ( mode < -1 || mode > 1 ) { throw new IllegalArgumentException("Invalid mode: " + mode); } this.mode = mode; } void run() throws Throwable { // Set stage to 0 // Switch off the fan // Wait // Change the mode // Update timestamp // Set stage to 0 complain(LOG_INFO, CH_AC, "Stopping the compressor..."); new ChangeStage(0).run(); complain(LOG_INFO, CH_AC, "Stopping the fan..."); new ChangeFanSpeed(0).run(); // Figure out how long we have to wait long lastOp = System.currentTimeMillis() - timestamp.mode; long wait = (lastOp > delay.mode) ? 0 : (delay.mode - lastOp); complain(LOG_INFO, CH_AC, "wait: " + wait); if ( wait > 0 ) { Thread.sleep(wait); } driver.setMode(mode); hardware.mode = mode; timestamp.mode = System.currentTimeMillis(); // VT: NOTE: We're not setting the stage back if the unit was // working. If so, there will be subsequent commands that will // take care of this, because mode change definitely means stage // change. } public String toString() { return "Mode change to " + mode; } } protected class ChangeStage extends Command { int stage; ChangeStage(int stage) { if ( stage < 0 ) { throw new IllegalArgumentException("Invalid stage: " + stage); } this.stage = stage; } void run() throws Throwable { // Wait // Change the stage // Update timestamp // Figure out how long we have to wait long lastOp = System.currentTimeMillis() - timestamp.stage; long wait = (lastOp > delay.stage) ? 0 : (delay.stage - lastOp); complain(LOG_INFO, CH_AC, "wait: " + wait); if ( wait > 0 ) { Thread.sleep(wait); } // FIXME: If the stage is not 0 and the fan speed is 0, refuse // and complain driver.setStage(stage); hardware.stage = stage; timestamp.stage = System.currentTimeMillis(); } public String toString() { return "Stage change to " + stage; } } protected class ChangeFanSpeed extends Command { double speed; ChangeFanSpeed(double speed) { if ( speed < 0 || speed > 1 ) { throw new IllegalArgumentException("Invalid fan speed: " + speed); } this.speed = speed; } void run() throws Throwable { // Wait // Change the fan speed // Update timestamp // Figure out how long we have to wait long lastOp = System.currentTimeMillis() - timestamp.fan; long wait = (lastOp > delay.fan) ? 0 : (delay.fan - lastOp); complain(LOG_INFO, CH_AC, "wait: " + wait); if ( wait > 0 ) { Thread.sleep(wait); } driver.setFanSpeed(speed); hardware.speed = speed; timestamp.fan = System.currentTimeMillis(); } public String toString() { return "Fan speed change to " + speed; } } protected class ACState { /** * Defines whether we are in a heating or cooling mode. * * <code>1</code> means heating, <code>-1</code> means cooling, * <code>0</code> means off. * * The default value is <code>0</code>, however, it may be overridden * by the configuration (and for Arizona, it better be cooling;). */ int mode; /** * The current compressor stage. * * This has the same value for heating and cooling, however, the * interpretation will be different. * * <p> * * Value of 0 means that the unit is off, value of 1 means first * stage, value of 2 means second stage, and so on. The stage value * is always non-negative. */ int stage; /** * Fan speed. * * <p> * * 0 is off, 1 is full, anything in between should be configured (VT: * FIXME: this is not done yet) according to the real hardware * configuration. */ double speed; } /** * Time constants related to mode, stage and fan speed change. */ private class Time { long mode; long stage; long fan; } /** * A queue that allows inspecting and removing the queue elements out of * order, as well as timed wait. */ protected class TransparentQueue extends SimpleQueue { public Iterator iterator() { return theQueue.iterator(); } /** * Wait for the object from the queue, then remove and return it. * * This method blocks until the object is available, or timeout * expires. * * @return The first object from the queue. * * @exception InterruptedException if the wait was interrupted. * Also, if the timeout expires, the same exception will be thrown, * with the message being a literal string "heartbeat". */ public synchronized Object waitObject(long timeout) throws InterruptedException { if ( timeout <= 0 ) { throw new IllegalArgumentException("Timeout must be positive, value given was " + timeout); } long deadline = System.currentTimeMillis() + timeout; while ( theQueue.isEmpty() ) { wait(timeout); long now = System.currentTimeMillis(); if ( now >= deadline ) { // No need to be specific about what exactly did we miss // and by how much throw new InterruptedException("heartbeat"); } timeout = deadline - now; } return theQueue.removeFirst(); } }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?