/** * Copyright (c) 2010-2016 by the respective copyright holders. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html */ package org.openhab.binding.dmx.internal.core; import java.util.ArrayList; import java.util.List; import org.openhab.binding.dmx.internal.action.BaseAction; import org.openhab.binding.dmx.internal.action.ResumeAction; import org.openhab.core.library.types.PercentType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * DmxChannel. Represents a single dimmable channel in DMX universe. * * When the channel is switched on, it will switch on to the last know state. * * @author Davy Vanherbergen * @since 1.2.0 */ public class DmxChannel implements Comparable<DmxChannel> { protected static final Logger logger = LoggerFactory.getLogger(DmxChannel.class); private int channelId; /** Current channel value in the range from 0-255 **/ private int value; /** Channel is alive or not.. **/ private boolean switchedOn = false; private List<BaseAction> actions = new ArrayList<BaseAction>(); private List<BaseAction> suspendedActions = new ArrayList<BaseAction>(); private int suspendedValue; /** Maximum DMX output value **/ public static int DMX_MAX_VALUE = 255; /** Minimum output value **/ public static int DMX_MIN_VALUE = 0; /** * Create new DMX channel. * * @param channelId * DMX channel id. */ public DmxChannel(int channelId) { this.channelId = channelId; } /** * Set the channel output to a fixed value. This will stop any active * actions on the channel. * * @param value * output value */ public synchronized void setValue(int value) { switchedOn = true; // stop active/looping fades.. actions.clear(); // set value this.value = DmxUtil.capDmxValue(value); } /** * Set the channel output to a fixed value of output level * 255, if no * actions are available. If actions are available, they are faded to the * output level. * * @param value * output value */ public synchronized void setValue(PercentType outputlevel) { if (outputlevel.intValue() == 0) { switchOff(); return; } else { switchOn(); } if (hasRunningActions()) { for (BaseAction a : actions) { a.setOutputLevel(outputlevel.intValue()); } } else { value = DmxUtil.getOutputValue(value, outputlevel.intValue()); } } /** * Get the value of the channel. * * @return value 0 - 255. */ public synchronized int getValue() { if (!switchedOn) { return DMX_MIN_VALUE; } return value; } /** * Switch on this channel. If no actions are active, this will also put the * channel value back to the last known state or to DMX Max value if no * state is known. */ public synchronized void switchOn() { switchedOn = true; } /** * Switch off this channel. The current state of the channel (but not * actions) will be kept for later use. */ public synchronized void switchOff() { switchedOn = false; actions.clear(); } /** * Get the new value for this channel as determined by active actions or the * current value. * * @param calculationTime * * @return value 0-255 */ public synchronized Integer getNextValue(long calculationTime) { if (!switchedOn) { return DMX_MIN_VALUE; } if (hasRunningActions()) { BaseAction action = actions.get(0); value = action.getNewValue(this, calculationTime); if (action.isCompleted()) { switchToNextAction(); } } return value; } /** * Move to the next action in the action chain. This method is used by * automatic chains and to manually move to the next action if actions are * set as indefinite (e.g. endless hold). This allows the user to toggle * through a fixed set of values. */ public synchronized void switchToNextAction() { logger.trace("Switching to next action on channel {}", getChannelId()); // push action to the back of the action list BaseAction action = actions.get(0); actions.remove(0); action.reset(); actions.add(action); } /** * Replace the current list of channel actions with the provided one. * * @param channelAction * action for this channel. */ public synchronized void setChannelAction(BaseAction channelAction) { if (!switchedOn) { value = 0; } switchedOn = true; actions.clear(); actions.add(channelAction); } /** * Add a channel action to the current list of channel actions. * * @param channelAction * action for this channel. */ public synchronized void addChannelAction(BaseAction channelAction) { actions.add(channelAction); } /** * @return dmx channel id. */ public int getChannelId() { return channelId; } /** * @{inheritDoc */ @Override public int compareTo(DmxChannel arg0) { if (arg0 == null) { return -1; } return new Integer(getChannelId()).compareTo(new Integer(arg0.getChannelId())); } /** * Increase channel value. * * @param increment * % to increase */ public synchronized void increaseChannel(int increment) { if (increment < 0) { return; } switchedOn = true; if (!hasRunningActions()) { // increase channel value value = DmxUtil.capDmxValue(value + DmxUtil.getByteFromPercentType(new PercentType(increment))); } else { // increase channel actions output for (BaseAction a : actions) { a.increase(increment); } } } /** * Decrease channel value level. * * @param decrement * % to decrease. */ public synchronized void decreaseChannel(int decrement) { if (decrement < 0) { return; } if (!hasRunningActions()) { // increase channel value value = DmxUtil.capDmxValue(value - DmxUtil.getByteFromPercentType(new PercentType(decrement))); } else { // decrease channel actions output for (BaseAction a : actions) { a.decrease(decrement); } } } /** * @return true if there are running actions */ public boolean hasRunningActions() { return !actions.isEmpty(); } /** * Suspend the current actions and value. This will store the values for * later resume. */ public void suspend() { suspendedValue = value; suspendedActions.clear(); suspendedActions.addAll(actions); } /** * Resume previously suspended actions. If no actions were suspended, the * suspended value will be restored. */ public void resume() { actions.clear(); if (!suspendedActions.isEmpty()) { actions.addAll(suspendedActions); suspendedActions.clear(); } else { setValue(suspendedValue); } } /** * Add a resume action to the end of the action list to trigger a resume of previously * suspended actions. */ public void addResumeAction() { actions.add(new ResumeAction()); } }