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