001package jmri.jmrix.powerline; 002 003import jmri.implementation.AbstractVariableLight; 004import org.slf4j.Logger; 005import org.slf4j.LoggerFactory; 006 007/** 008 * Implementation of the Light Object for Powerline devices. 009 * <p> 010 * For X10 devices, uses dimming commands to set intensity unless the value is 011 * 0.0 or 1.0, in which case it uses on/off commands only. 012 * <p> 013 * For Insteon devices, uses direct setting of intensity level unless the value 014 * is 0.0 or 1.0, in which case it uses on/off commands only. 015 * <p> 016 * For DMX devices, use direct setting of the intensity level. But an on/off 017 * will skip any stepping of the change. 018 * <p> 019 * For X10, since the dim/bright step of the hardware is unknown then the Light 020 * object is first created, the first time the intensity (not state) is set to 021 * other than 0.0 or 1.0, the output is run to it's maximum dim or bright step 022 * so that we know the count is right. 023 * <p> 024 * For X10, keeps track of the controller's "dim count", and if not certain 025 * forces it to zero to be sure. 026 * 027 * @author Dave Duchamp Copyright (C) 2004 028 * @author Bob Jacobsen Copyright (C) 2006, 2007, 2008 029 * @author Ken Cameron Copyright (C) 2009, 2010 Converted to multiple connection 030 * @author kcameron Copyright (C) 2011 031 */ 032abstract public class SerialLight extends AbstractVariableLight { 033 034 /** 035 * Create a Light object, with only system name. 036 * <p> 037 * 'systemName' was previously validated in SerialLightManager 038 * @param systemName system name for light 039 * @param tc traffic controller 040 */ 041 public SerialLight(String systemName, SerialTrafficController tc) { 042 super(systemName); 043 this.tc = tc; 044 // Initialize the Light 045 initializeLight(); 046 } 047 048 /** 049 * Create a Light object, with both system and user names. 050 * <p> 051 * 'systemName' was previously validated in SerialLightManager 052 * @param systemName system name for light 053 * @param tc traffic controller 054 * @param userName user name for light 055 */ 056 public SerialLight(String systemName, SerialTrafficController tc, String userName) { 057 super(systemName, userName); 058 this.tc = tc; 059 initializeLight(); 060 } 061 062 SerialTrafficController tc = null; 063 064 /** 065 * Invoked from constructors to set up details. Note: most instance 066 * variables are in AbstractLight and AbstractVariableLight base classes. 067 */ 068 protected void initializeLight() { 069 // Convert to the two-part X10 address 070 housecode = tc.getAdapterMemo().getSerialAddress().x10HouseCodeAsValueFromSystemName(getSystemName()); 071 devicecode = tc.getAdapterMemo().getSerialAddress().x10DeviceCodeAsValueFromSystemName(getSystemName()); 072 // not an X10, try Insteon 073 if (housecode == -1) { 074 idhighbyte = tc.getAdapterMemo().getSerialAddress().insteonIdHighCodeAsValueFromSystemName(getSystemName()); 075 idmiddlebyte = tc.getAdapterMemo().getSerialAddress().insteonIdMiddleCodeAsValueFromSystemName(getSystemName()); 076 idlowbyte = tc.getAdapterMemo().getSerialAddress().insteonIdLowCodeAsValueFromSystemName(getSystemName()); 077 // if not Insteon, try DMX 078 if (idhighbyte == -1) { 079 unitid = tc.getAdapterMemo().getSerialAddress().dmxUnitIdCodeAsValueFromSystemName(getSystemName()); 080 } 081 } 082 } 083 084 /** 085 * Optionally, force control to a known "dim count". 086 * <p> 087 * Invoked the first time intensity is set. 088 * <p> 089 * Default implementation doesn't do anything. 090 * @param intensity float for 0->1.0 091 */ 092 protected void initIntensity(double intensity) { 093 } 094 095 // data members holding the address forms 096 protected int housecode = -1; 097 protected int devicecode = -1; 098 protected int idhighbyte = -1; 099 protected int idmiddlebyte = -1; 100 protected int idlowbyte = -1; 101 protected int unitid = -1; 102 103 /** 104 * Send a On/Off Command to the hardware 105 */ 106 @Override 107 protected void sendOnOffCommand(int newState) { 108 if (log.isDebugEnabled()) { 109 log.debug("sendOnOff({}) Current: {}", newState, mState); 110 } 111 112 // figure out command 113 int function; 114 double newDim; 115 if (newState == ON) { 116 function = X10Sequence.FUNCTION_ON; 117 newDim = 1; 118 } else if (newState == OFF) { 119 function = X10Sequence.FUNCTION_OFF; 120 newDim = 0; 121 } else { 122 log.warn("illegal state requested for Light: {}", getSystemName()); 123 return; 124 } 125 126 if (log.isDebugEnabled()) { 127 log.debug("set state {} house {} device {}", newState, X10Sequence.houseCodeToText(housecode), devicecode); 128 } 129 130 // create output sequence of address, then function 131 X10Sequence out = new X10Sequence(); 132 out.addAddress(housecode, devicecode); 133 out.addFunction(housecode, function, 0); 134 // send 135 tc.sendX10Sequence(out, null); 136 137 if (log.isDebugEnabled()) { 138 log.debug("sendOnOff({}) house {} device {} funct: {}", newDim, X10Sequence.houseValueToText(housecode), devicecode, function); 139 } 140 } 141 142 private final static Logger log = LoggerFactory.getLogger(SerialLight.class); 143} 144 145