diff --git a/bundles/binding/org.openhab.binding.dmx/src/main/java/org/openhab/binding/dmx/internal/core/DmxController.java b/bundles/binding/org.openhab.binding.dmx/src/main/java/org/openhab/binding/dmx/internal/core/DmxController.java index e9f7f21384f..c4e83e7d7c7 100644 --- a/bundles/binding/org.openhab.binding.dmx/src/main/java/org/openhab/binding/dmx/internal/core/DmxController.java +++ b/bundles/binding/org.openhab.binding.dmx/src/main/java/org/openhab/binding/dmx/internal/core/DmxController.java @@ -27,6 +27,7 @@ * Default DMX Service implementation * * @author Davy Vanherbergen + * @author Jan N. Klug * @since 1.2.0 */ public class DmxController implements DmxService, ManagedService { @@ -34,6 +35,8 @@ 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; @@ -49,7 +52,6 @@ public class DmxController implements DmxService, ManagedService { */ @Override public void start() throws Exception { - logger.trace("Starting Dmx transmitter ..."); transmitter = new DmxTransmitter(this); transmitterTimer = new Timer(true); @@ -84,7 +86,6 @@ public void setChannelValue(int channel, int value) { */ @Override public int getChannelValue(int channel) { - int value = transmitter.getChannel(channel).getValue(); logger.trace("Getting channel {} value: {}", channel, value); return value; @@ -292,11 +293,33 @@ public void unsetConnection(DmxConnection conn) { @Override public void updated(Dictionary 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(); + } } } diff --git a/bundles/binding/org.openhab.binding.dmx/src/main/java/org/openhab/binding/dmx/internal/core/DmxTransmitter.java b/bundles/binding/org.openhab.binding.dmx/src/main/java/org/openhab/binding/dmx/internal/core/DmxTransmitter.java index 95da85adf44..c79f59a4e3d 100644 --- a/bundles/binding/org.openhab.binding.dmx/src/main/java/org/openhab/binding/dmx/internal/core/DmxTransmitter.java +++ b/bundles/binding/org.openhab.binding.dmx/src/main/java/org/openhab/binding/dmx/internal/core/DmxTransmitter.java @@ -27,6 +27,38 @@ */ public final class DmxTransmitter extends TimerTask { + /* REPEAT_INTERVAL is 750 ms (results in 800-1000ms) repetition time */ + private static final int REPEAT_INTERVAL = 750; + private static final int REPEAT_COUNT = 3; + + public enum DmxRepeatMode { + ALWAYS("always"), + NEVER("never"), + REDUCED("reduced"); + + private String repeatMode; + + DmxRepeatMode(String repeatMode) { + this.repeatMode = repeatMode; + } + + @Override + public String toString() { + return this.repeatMode; + } + + public static DmxRepeatMode fromString(String repeatMode) { + if (repeatMode != null) { + for (DmxRepeatMode mode : DmxRepeatMode.values()) { + if (repeatMode.equalsIgnoreCase(mode.repeatMode)) { + return mode; + } + } + } + return null; + } + } + private static Logger logger = LoggerFactory.getLogger(DmxTransmitter.class); private DmxUniverse universe = new DmxUniverse(); @@ -34,9 +66,13 @@ public final class DmxTransmitter extends TimerTask { private DmxService service; private boolean running; + private DmxRepeatMode repeatMode = DmxRepeatMode.ALWAYS; private boolean suspended; + private long lastTransmit = 0; + private int packetRepeatCount = 0; + /** * Default constructor. */ @@ -56,12 +92,30 @@ public void run() { running = true; try { + long now = System.currentTimeMillis(); byte[] b = universe.calculateBuffer(); - if (universe.getBufferChanged()) { - DmxConnection conn = service.getConnection(); - if (conn != null) { + DmxConnection conn = service.getConnection(); + if (conn != null) { + if (universe.getBufferChanged()) { + logger.trace("DMX Buffer changed, also sending status updates"); conn.sendDmx(b); universe.notifyStatusListeners(); + lastTransmit = now; + packetRepeatCount = 0; + } else if (repeatMode == DmxRepeatMode.ALWAYS) { + logger.trace("repeat mode always, sending DMX only"); + conn.sendDmx(b); + lastTransmit = now; + } else if ((repeatMode == DmxRepeatMode.REDUCED) + && ((packetRepeatCount < REPEAT_COUNT) || ((now - lastTransmit) > REPEAT_INTERVAL))) { + logger.trace("output needs refresh, sending DMX only"); + conn.sendDmx(b); + if (packetRepeatCount < REPEAT_COUNT) { + packetRepeatCount++; + } + lastTransmit = now; + } else { + logger.trace("DMX output suppressed"); } } } catch (Exception e) { @@ -79,8 +133,8 @@ public boolean isRunning() { } /** - * Suspend/resume transmittting. - * + * Suspend/resume transmitting. + * * @param suspend * true to suspend */ @@ -88,9 +142,19 @@ public void setSuspend(boolean suspend) { this.suspended = suspend; } + /** + * change transmitter refresh cycle + * + * @param refreshInterval + * interval in ms (if output did not change) + */ + public void setRepeatMode(DmxRepeatMode repeatMode) { + this.repeatMode = repeatMode; + } + /** * Get the DMX channel in the current universe. - * + * * @param channel * number * @return DMX channel diff --git a/distribution/openhabhome/configurations/openhab_default.cfg b/distribution/openhabhome/configurations/openhab_default.cfg index 02e342ec488..2435eaafb0b 100644 --- a/distribution/openhabhome/configurations/openhab_default.cfg +++ b/distribution/openhabhome/configurations/openhab_default.cfg @@ -1,4 +1,4 @@ -# This is the default configuration file, which comes with every openHAB distribution. +# This is the default configuration file, which comes with every openHAB distribution. # You should do a copy of it with the name 'openhab.cfg' and configure your personal # settings in there. This way you can be sure that they are not overwritten, if you # update openHAB one day. @@ -1053,6 +1053,13 @@ ntp:hostname=ptbtime1.ptb.de # 'localhost:9010' or 'localhost:9020' depending on the choosen connection type) #dmx:connection= +# Standard DMX-512A (E1.11) uses continous transmission (option "always", default value). +# Some DMX protocols (sACN/E1.31, ArtNET) allow suppressing packet transmission for +# a short period of time (800-1000ms) to reduce network load (option "reduced"). +# Previous versions of the DMX binding did not repeat unchanged packets at all. While +# this is not in compliance with any standard the option "never" is included for +# backward compatibilty. +#dmx:repeatMode=always ############################### Philips Hue Binding ################################### # # IP address of Hue Bridge (optional, default is auto-discovery)