/**
* 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.Dictionary;
import java.util.Timer;
import org.apache.commons.lang.StringUtils;
import org.openhab.binding.dmx.DmxConnection;
import org.openhab.binding.dmx.DmxService;
import org.openhab.binding.dmx.DmxStatusUpdateListener;
import org.openhab.binding.dmx.internal.action.FadeAction;
import org.openhab.binding.dmx.internal.action.MirrorAction;
import org.openhab.core.library.types.PercentType;
import org.osgi.service.cm.ConfigurationException;
import org.osgi.service.cm.ManagedService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Default DMX Service implementation
*
* @author Davy Vanherbergen
* @author Jan N. Klug
* @since 1.2.0
*/
public class DmxController implements DmxService, ManagedService {
private static Logger logger = LoggerFactory.getLogger(DmxController.class);
private static int TRANSMIT_FREQUENCY_MS = 35;
private DmxTransmitter.DmxRepeatMode repeatMode = DmxTransmitter.DmxRepeatMode.ALWAYS; // default is send every
// update
/** Thread in which the DMX transmitter is running **/
private Timer transmitterTimer;
private DmxTransmitter transmitter;
private DmxConnection connection;
private String connectionString = "localhost:9010";
/**
* {@inheritDoc}
*/
@Override
public void start() throws Exception {
logger.trace("Starting Dmx transmitter ...");
transmitter = new DmxTransmitter(this);
transmitterTimer = new Timer(true);
transmitterTimer.schedule(transmitter, 0, TRANSMIT_FREQUENCY_MS);
logger.trace("Dmx transmitter started.");
}
/**
* {@inheritDoc}
*/
@Override
public void stop() {
if (transmitterTimer != null) {
transmitterTimer.cancel();
}
transmitterTimer = null;
}
/**
* {@inheritDoc}
*/
@Override
public void setChannelValue(int channel, int value) {
logger.trace("Setting channel {} to {}", channel, value);
transmitter.getChannel(channel).setValue(value);
}
/**
* {@inheritDoc}
*/
@Override
public int getChannelValue(int channel) {
int value = transmitter.getChannel(channel).getValue();
logger.trace("Getting channel {} value: {}", channel, value);
return value;
}
/**
* {@inheritDoc}
*/
@Override
public void disableChannel(int channel) {
logger.trace("Disabling channel {}", channel);
transmitter.getChannel(channel).switchOff();
}
/**
* {@inheritDoc}
*/
@Override
public void enableChannel(int channel) {
logger.trace("Enabling channel {}", channel);
transmitter.getChannel(channel).switchOn();
}
/**
* {@inheritDoc}
*/
@Override
public void registerStatusListener(DmxStatusUpdateListener listener) {
logger.trace("Registering listener for channel {}", listener.getChannel());
transmitter.getUniverse().addStatusListener(listener);
}
/**
* {@inheritDoc}
*/
@Override
public void unregisterStatusListener(DmxStatusUpdateListener listener) {
logger.trace("Unregistering listener for channel {}", listener.getChannel());
transmitter.getUniverse().removeStatusListener(listener);
}
/**
* {@inheritDoc}
*/
@Override
public void fadeChannel(int channel, int fadeTime, int targetValue, int holdTime, boolean immediate) {
FadeAction fade = new FadeAction(fadeTime, targetValue, holdTime);
if (immediate) {
logger.trace("Fading channel {} to {}", channel, targetValue);
transmitter.getChannel(channel).setChannelAction(fade);
} else {
logger.trace("Adding channel fade on channel {} to {}", channel, targetValue);
transmitter.getChannel(channel).addChannelAction(fade);
}
}
/**
* {@inheritDoc}
*/
@Override
public void fadeChannels(int startChannel, int fadeTime, int[] targetValues, int holdTime, boolean immediate) {
logger.trace("Fading channels {} to {}", startChannel, targetValues);
int channelId = startChannel;
for (int v : targetValues) {
FadeAction fade = new FadeAction(fadeTime, v, holdTime);
if (immediate) {
transmitter.getChannel(channelId++).setChannelAction(fade);
} else {
transmitter.getChannel(channelId++).addChannelAction(fade);
}
}
}
/**
* {@inheritDoc}
*/
@Override
public void switchToNextAction(int channel) {
logger.trace("Switching fade for channel {}", channel);
transmitter.getChannel(channel).switchToNextAction();
}
/**
* {@inheritDoc}
*/
@Override
public void switchToNextAction(int startChannel, int numberOfChannels) {
logger.trace("Switching fades for channel {} x{}", startChannel, numberOfChannels);
for (int i = 0; i < numberOfChannels; i++) {
transmitter.getChannel(startChannel + i).switchToNextAction();
}
}
/**
* {@inheritDoc}
*/
@Override
public void mirrorChannel(int sourceChannel, int mirrorChannel, int duration) {
logger.trace("Mirroring channel {} onto {}", sourceChannel, mirrorChannel);
transmitter.getChannel(mirrorChannel)
.setChannelAction(new MirrorAction(transmitter.getChannel(sourceChannel), duration));
}
/**
* {@inheritDoc}
*/
@Override
public void increaseChannel(int channelId, int increment) {
logger.trace("Increasing channel {}", channelId);
transmitter.getChannel(channelId).increaseChannel(increment);
}
/**
* {@inheritDoc}
*/
@Override
public void decreaseChannel(int channelId, int decrement) {
logger.trace("Decreasing channel {}", channelId);
transmitter.getChannel(channelId).decreaseChannel(decrement);
}
/**
* {@inheritDoc}
*/
@Override
public void suspend(boolean suspend) {
if (suspend) {
transmitter.setSuspend(true);
while (transmitter.isRunning()) {
try {
Thread.sleep(10);
} catch (Exception e) {
e.printStackTrace();
}
}
} else {
transmitter.setSuspend(false);
}
}
/**
* {@inheritDoc}
*/
@Override
public void setChannelValue(int channelId, PercentType outputlevel) {
transmitter.getChannel(channelId).setValue(outputlevel);
}
/**
* {@inheritDoc}
*/
@Override
public boolean hasChannelActions(int channelId) {
return transmitter.getChannel(channelId).hasRunningActions();
}
/**
* {@inheritDoc}
*/
@Override
public DmxConnection getConnection() {
if (connection == null) {
logger.error("No DMX connection available. Please provide a bundle which implements the connection.");
return null;
}
if (connection.isClosed()) {
try {
connection.open(connectionString);
} catch (Throwable t) {
logger.error("Error opening DMX connection.", t);
return null;
}
}
return connection;
}
/**
* {@inheritDoc}
*/
@Override
public void setConnection(DmxConnection conn) {
if (connection != null) {
connection.close();
}
connection = conn;
}
/**
* {@inheritDoc}
*/
@Override
public void unsetConnection(DmxConnection conn) {
if (conn != null) {
conn.close();
}
connection = null;
}
/**
* {@inheritDoc}
*/
@Override
public void updated(Dictionary<String, ?> config) throws ConfigurationException {
if (config != null) {
// connection
String configuredConnection = (String) config.get("connection");
if (StringUtils.isNotBlank(configuredConnection)) {
connectionString = configuredConnection;
logger.debug("Setting connection from config: {}", connectionString);
}
// refresh timeout (i.e. interval between transmits if nothing changed)
String configuredRepeatMode = ((String) config.get("repeatMode"));
if (StringUtils.isNotBlank(configuredRepeatMode)) {
repeatMode = DmxTransmitter.DmxRepeatMode.fromString(configuredRepeatMode);
if (repeatMode == null) {
repeatMode = DmxTransmitter.DmxRepeatMode.ALWAYS;
logger.error("repeatMode {} not recognized, set to {}", configuredRepeatMode, repeatMode);
} else {
logger.debug("repeatMode set to {}", repeatMode.toString());
}
if (transmitter != null) {
transmitter.setRepeatMode(repeatMode);
}
}
}
// close connection so that the new connection string will take effekt on next getConnection
if (connection != null) {
if (!connection.isClosed()) {
connection.close();
}
}
}
/**
* {@inheritDoc}
*/
@Override
public void suspendChannel(int channel) {
transmitter.getChannel(channel).suspend();
}
/**
* {@inheritDoc}
*/
@Override
public void addChannelResume(int channel) {
transmitter.getChannel(channel).addResumeAction();
}
}