📄 balancingzonecontroller.java
字号:
package net.sf.dz.device.model.impl;import java.io.IOException;import java.util.Map;import java.util.HashMap;import java.util.HashSet;import java.util.Iterator;import java.util.Set;import java.util.SortedMap;import java.util.TreeMap;import org.freehold.jukebox.conf.Configurable;import org.freehold.jukebox.conf.Configuration;import org.freehold.jukebox.logger.LogAware;import org.freehold.jukebox.logger.LogChannel;import net.sf.dz.device.actuator.Damper;import net.sf.dz.device.model.Unit;import net.sf.dz.device.model.Thermostat;/** * A balancing A/C zone controller. * * @author Copyright © <a href="mailto:vt@freehold.crocodile.org">Vadim Tkachenko</a> 2001 * @version $Id: BalancingZoneController.java,v 1.8 2004/01/20 02:40:34 vtt Exp $ */public class BalancingZoneController extends AbstractZoneController { public static final LogChannel CH_BZC = new LogChannel("ZCTL/Balancing"); protected synchronized Double controlSignalChanged(Thermostat source, double signal, Double currentDemand) { Map damperMap = new HashMap(); try { // If the signal is within ctl_happy to ctl_unhappy range, nothing // happens. if ( signal >= ctl_unhappy ) { if ( unhappyTs.contains(source) ) { // Don't do anything //complain(LOG_DEBUG, CH_BZC, source.getName() + ": already unhappy"); return null; } if ( !source.isVoting() && !unit.getAC().isRunning() ) { // Don't do anything complain(LOG_INFO, CH_BZC, "Not voting: " + source.getName()); return null; } complain(LOG_INFO, CH_BZC, "Unhappy: " + source.getName()); // Make everybody unhappy for ( Iterator i = unit.iterator(); i.hasNext(); ) { Thermostat ts = (Thermostat)i.next(); unhappyTs.add(ts); // Let balance() do its job? //damperMap.put(ts), new Double(1)); } // Turn on the A/C (this is done implicitly in super.commit()) // The return is not really needed here, I just want to // emphasize that nothing else happens return currentDemand; } else if ( signal <= ctl_happy ) { if ( unhappyTs.isEmpty() ) { // The A/C is already off // Shut the throttle anyway damperMap.put(unit.getDamperController().getDamper(source), new Double(0)); return null; } // OK, *we* are satisfied. unhappyTs.remove(source); //complain(LOG_DEBUG, CH_BZC, source.getName() + ": not unhappy anymore"); // Let's check if all the thermostats are satisfied if ( unhappyTs.isEmpty() ) { // Everybody's happy, turn off the A/C //complain(LOG_DEBUG, CH_BZC, "Everybody's happy now"); currentDemand = new Double(0); // and shut the throttles for ( Iterator i = unit.iterator(); i.hasNext(); ) { Thermostat ts = (Thermostat)i.next(); damperMap.put(unit.getDamperController().getDamper(ts), new Double(0)); } } else { // No, there are some others who are unhappy. Let's just // close our throttle and get out damperMap.put(unit.getDamperController().getDamper(source), new Double(0)); //complain(LOG_DEBUG, CH_BZC, source.getName() + ": shut off the damper"); } } // Again, if the signal is between "unhappy" and "happy", nothing // happens return currentDemand; } finally { balance(damperMap); for ( Iterator i = damperMap.keySet().iterator(); i.hasNext(); ) { Damper d = (Damper)i.next(); try { d.set(((Double)damperMap.get(d)).doubleValue()); } catch ( IOException ioex ) { complain(LOG_WARNING, CH_BZC, "Can't set throttle, cause:", ioex); } } } } /** * This decides how do we want to adjust the throttle positions to keep * the temperature uniform. */ protected void balance(Map damperMap) { // Calculate the mapping between the controller signal and the // throttle position // Readjust the throttles: // // - Room with the most demand gets 1.0 // - Room with the least demand gets 0.0 // - All the rest line up accordingly // // Demand less than HAPPY is set to HAPPY to take the rooms with // "OFF" status don't get their throttles open. SortedMap signal2ts = new TreeMap(); for ( Iterator i = unhappyTs.iterator(); i.hasNext(); ) { Thermostat ts = (Thermostat)i.next(); Double signalObject = (Double)tsSignalMap.get(ts); //complain(LOG_DEBUG, CH_BZC, ts.getName() + ": about to balance"); if ( signalObject != null ) { double signal = signalObject.doubleValue(); if ( signal < ctl_happy ) { signal = ctl_happy; } Set tsSet = (Set)signal2ts.get(signalObject); if ( tsSet == null ) { tsSet = new HashSet(); // Let's introduce offset beforehand, so the least value // is always 0 signal -= ctl_happy; // Also, let's introduce a bias, so the rooms that needs // the most, get the most signal *= signal * signal; signal2ts.put(new Double(signal), tsSet); } tsSet.add(ts); } } if ( signal2ts.isEmpty() ) { //complain(LOG_DEBUG, CH_BZC, "balance(): no signals, doing nothing"); return; } double most = ((Double)signal2ts.lastKey()).doubleValue(); StringBuffer sb = new StringBuffer("Signal:"); for ( Iterator i = signal2ts.keySet().iterator(); i.hasNext(); ) { sb.append(" ").append(i.next()); } if ( most == 0 ) { complain(LOG_INFO, CH_BZC, "Happy"); unhappyTs.clear(); // FIXME: make sure that the current demand is really 0, // otherwise it's going to blow up //unit.getAC().demand(0); for ( Iterator i = unit.iterator(); i.hasNext(); ) { Thermostat ts = (Thermostat)i.next(); damperMap.put(unit.getDamperController().getDamper(ts), new Double(0)); } return; } // Normalize double scale = 1 / most; sb.append(" =").append(Double.toString(scale)); //complain(LOG_INFO, CH_BZC, sb.toString()); // Now, (signal + offset) * scale should be a value for the // throttle position. // Shuffle the throttles for ( Iterator i = signal2ts.keySet().iterator(); i.hasNext(); ) { Double key = (Double)i.next(); Set tSet = (Set)signal2ts.get(key); double value = key.doubleValue() * scale; //complain(LOG_INFO, CH_BZC, "Damper: " + value); for ( Iterator si = tSet.iterator(); si.hasNext(); ) { Thermostat ts = (Thermostat)si.next(); damperMap.put(unit.getDamperController().getDamper(ts), new Double(value)); } } } /** * Compute the total demand for A/C. */ protected double computeDemand() { int mode = unit.getAC().getMode(); double demand = 0; for ( Iterator i = tsSignalMap.keySet().iterator(); i.hasNext(); ) { Thermostat ts = (Thermostat)i.next(); if ( !ts.isOn() ) { // The signal from this thermostat is irrelevant continue; } double signal = ((Double)tsSignalMap.get(ts)).doubleValue() * ((mode == 0) ? 0 : 1); if ( signal > ctl_happy ) { // Since ctl_happy is negative, offset has to be added so // signal equal to ctl_unhappy becomes 0 demand += (signal - ctl_happy); } } //complain(LOG_NOTICE, CH_AZC, "Total demand: " + demand); return demand; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -