📄 pnphvacdriver.java
字号:
package net.sf.dz.device.actuator.impl.tcp;//import java.io.BufferedReader;import java.io.IOException;//import java.io.InputStreamReader;//import java.io.PrintWriter;//import java.net.Socket;//import java.net.SocketException;//import java.util.Iterator;//import java.util.NoSuchElementException;//import java.util.Set;//import java.util.StringTokenizer;//import java.util.TreeSet;import org.freehold.jukebox.conf.Configuration;import org.freehold.jukebox.logger.LogChannel;import org.freehold.jukebox.service.PassiveService;import org.freehold.jukebox.service.ServiceUnavailableException;import net.sf.dz.device.actuator.ACDriver;import net.sf.dz.pnp.MulticastClient;import net.sf.dz.pnp.custom.SimpleBroadcastClient;import net.sf.dz.daemon.tcp.client.ConnectorFactory;import net.sf.dz.daemon.tcp.client.DeviceConnector;import net.sf.dz.daemon.tcp.client.DeviceListener;/** * Plug-and-play TCP HVAC driver. * * <p> * * VT: FIXME: Initially, this was just a clone of {@link * net.sf.dz.device.actuator.impl.onewire.OneWireACDriver OneWireACDriver}, * but they will diverge significantly in the end. * * <p> * * <strong>NOTE:</strong> 1-Wire device address will look slightly different * from the one for the sensor. Since the switches are usually * multi-channeled (2 to 8), in order to make the request/response path more * uniform, the device address is to be specified as * <code><<i>1-wire-address</i>><u>:</u><<i>channel</i>></code>. * * @author Copyright © <a href="mailto:vt@freehold.crocodile.org"> Vadim Tkachenko</a> 2004 * @version $Id: PnpHvacDriver.java,v 1.3 2004/07/15 06:43:07 vtt Exp $ */public class PnpHvacDriver extends PassiveService implements ACDriver, DeviceListener { public static final LogChannel CH_OWAC = new LogChannel("HVAC/PnP"); // VT: FIXME: These must be moved into TcpConnector public static final long INITIAL_RETRY_TIMEOUT = 1000; public static final long MAX_RETRY_TIMEOUT = INITIAL_RETRY_TIMEOUT * 64; /** * This switch controls the cool/heat. * */ protected String modeSwitchAddress; /** * This switch controls the fan on/off. */ protected String fanSwitchAddress; /** * This switch controls the compressor. */ protected String stageSwitchAddress; /** * Initial retry timeout. * * Configurable, defaults to {@link #INITIAL_RETRY_TIMEOUT INITIAL_RETRY_TIMEOUT}. */ protected long initialRetryTimeout = INITIAL_RETRY_TIMEOUT; /** * Maximum retry timeout. * * Configurable, defaults to {@link #MAX_RETRY_TIMEOUT MAX_RETRY_TIMEOUT}. */ protected long maxRetryTimeout = MAX_RETRY_TIMEOUT; protected static MulticastClient multicastClient; protected static ConnectorFactory connectorFactory; private DeviceConnector modeConnector; private DeviceConnector fanConnector; private DeviceConnector stageConnector; private Integer mode = null; private Integer stage = null; private Double speed = null; protected void configure() throws Throwable { Configuration conf = getConfiguration(); String cfroot = getConfigurationRoot(); // Let's make it clear where we configure from so it will be easier // to change the configuration to non-default complain(LOG_INFO, CH_OWAC, "Configuration root: " + cfroot); modeSwitchAddress = conf.getString(cfroot + ".switch.mode.address"); fanSwitchAddress = conf.getString(cfroot + ".switch.fan.address"); stageSwitchAddress = conf.getString(cfroot + ".switch.stage.address"); initialRetryTimeout = conf.getInteger(cfroot + ".retry.timeout.initial", 1000); maxRetryTimeout = conf.getInteger(cfroot + ".retry.timeout.max", 1000*64); } public final String getServiceSignature() { return "DZ DAC Switches"; } protected void startup() throws Throwable { // VT: FIXME: Make this configurable synchronized ( getClass() ) { if ( multicastClient == null ) { multicastClient = new SimpleBroadcastClient(5003); multicastClient.setLogger(getLogger()); if ( !multicastClient.start().waitFor() ) { throw new ServiceUnavailableException("Could not start multicast client, messages should have been provided"); } connectorFactory = new ConnectorFactory(getLogger()); connectorFactory.setLogger(getLogger()); connectorFactory.addMulticastClient(multicastClient); } } modeConnector = connectorFactory.getConnector(getServiceSignature(), modeSwitchAddress); fanConnector = connectorFactory.getConnector(getServiceSignature(), fanSwitchAddress); stageConnector = connectorFactory.getConnector(getServiceSignature(), stageSwitchAddress); // Add ourself as a listener so we would know when a status change // or a failure occurs modeConnector.addListener(this); fanConnector.addListener(this); stageConnector.addListener(this); } protected synchronized void shutdown(Throwable cause) throws Throwable { complain(LOG_INFO, CH_OWAC, "Shutting down the A/C...", new Exception("Call stack trace")); // Shut down the A/C setStage(0); setFanSpeed(0); setMode(0); complain(LOG_INFO, CH_OWAC, "A/C shut down"); } /** * Set the unit mode. * * @param mode Operating mode. -1 is cooling, 0 is off, 1 is heating. * Actually, the switch is only between cooling and heating, but * different units may have different rules (the contact is energized * only for cooling, or only for heating). * * @exception IOException if there was a problem talking to the hardware. * * @exception IllegalArgumentException if the stage is neither -1, 0 nor * 1. */ public void setMode(int mode) throws IOException { // This is required for translation int value = 0; switch ( mode ) { case -1: case 0: // Need to de-energize for cooling value = 0; break; case 1: // Need to energize for heating value = 1; break; default: throw new IllegalArgumentException("Invalid mode: " + mode); } this.mode = new Integer(mode); String response = modeConnector.sendExclusive("write " + value); if ( !"OK".equals(response) ) { throw new IOException("Device response: " + response); } } /** * Set the unit stage. * * This method will work with single stage unit only. * * @param stage A/C stage. For single stage units, 0 is off, 1 is on. * For multistage units, it is 0, 1, 2 and so on. * * @exception IOException if there was a problem talking to the hardware. * * @exception IllegalArgumentException if the stage is neither 0 nor 1. */ public void setStage(int stage) throws IOException { switch ( stage ) { case 0: case 1: break; default: throw new IllegalArgumentException("Invalid stage: " + stage); } this.stage = new Integer(stage); String response = stageConnector.sendExclusive("write " + stage); if ( !"OK".equals(response) ) { throw new IOException("Device response: " + response); } } /** * Set the fan speed. * * This method will work with single speed fan only. * * @param speed Fan speed. For single speed fan, 0 is off, 1 is on. For * variable speed or multispeed fans, 0 is off, 1 is full, anything in * between defines the actual speed. Since both variable speed and * multispeed fans have some preset values, it is up to the * implementation to define the rounding rules. * * @exception IOException if there was a problem talking to the hardware. * * @exception IllegalArgumentException if the speed is neither 0 nor 1. */ public void setFanSpeed(double speed) throws IOException { if ( speed != 0 && speed != 1 ) { throw new IllegalArgumentException("Unsupported speed: " + speed + " (only 0 and 1 are valid)"); } this.speed = new Double(speed); String response = fanConnector.sendExclusive("write " + (int)speed); if ( !"OK".equals(response) ) { throw new IOException("Device response: " + response); } } public void deviceEvent(DeviceConnector connector, String data) { // VT: FIXME: This is a good place to send the alert to the user complain(LOG_WARNING, CH_OWAC, "Don't know what to do with '" + data + "' from " + connector.getDeviceAddress()); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -