artnet optimiert, fehlerkorrigiert
senden von Werten nur, wenn was geändert wurde.
This commit is contained in:
parent
d8817c2e46
commit
ddea2d1e69
|
@ -0,0 +1,5 @@
|
||||||
|
XDOCLETBUILDERACTIVE=true
|
||||||
|
XDOCLETHOME=
|
||||||
|
XDOCLETUSEGLOBAL=true
|
||||||
|
XDOCLETVERSION=1.2.1
|
||||||
|
eclipse.preferences.version=1
|
|
@ -0,0 +1,2 @@
|
||||||
|
eclipse.preferences.version=1
|
||||||
|
org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false
|
|
@ -0,0 +1,2 @@
|
||||||
|
eclipse.preferences.version=1
|
||||||
|
org.eclipse.wst.ws.service.policy.projectEnabled=false
|
|
@ -1,146 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of artnet4j.
|
|
||||||
*
|
|
||||||
* Copyright 2009 Karsten Schmidt (PostSpectacular Ltd.)
|
|
||||||
*
|
|
||||||
* artnet4j is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* artnet4j is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with artnet4j. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package artnet4j;
|
|
||||||
|
|
||||||
import java.net.InetAddress;
|
|
||||||
import java.net.SocketException;
|
|
||||||
import java.net.UnknownHostException;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
import artnet4j.packets.ArtNetPacket;
|
|
||||||
|
|
||||||
public class ArtNet {
|
|
||||||
|
|
||||||
public static final Logger logger = Logger.getLogger(ArtNet.class.getClass().getName());
|
|
||||||
|
|
||||||
protected static final long ARTPOLL_REPLY_TIMEOUT = 3000;
|
|
||||||
|
|
||||||
protected static final String VERSION = "0001-20091119";
|
|
||||||
|
|
||||||
protected ArtNetServer server;
|
|
||||||
// protected ArtNetNodeDiscovery discovery;
|
|
||||||
|
|
||||||
// public ArtNet() {
|
|
||||||
// logger.info("Art-Net v" + VERSION);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public void addServerListener(ArtNetServerListener l) {
|
|
||||||
// server.addListener(l);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// public void broadcastPacket(ArtNetPacket packet) {
|
|
||||||
// server.broadcastPacket(packet);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public ArtNetNodeDiscovery getNodeDiscovery() {
|
|
||||||
// if (discovery == null) {
|
|
||||||
// discovery = new ArtNetNodeDiscovery(this);
|
|
||||||
// }
|
|
||||||
// return discovery;
|
|
||||||
// }
|
|
||||||
|
|
||||||
public void init() {
|
|
||||||
server = new ArtNetServer();
|
|
||||||
// server.addListener(new ArtNetServerEventAdapter() {
|
|
||||||
// @Override
|
|
||||||
// public void artNetPacketReceived(ArtNetPacket packet) {
|
|
||||||
// logger.fine("packet received: " + packet.getType());
|
|
||||||
// if (discovery != null && packet.getType() == PacketType.ART_POLL_REPLY) {
|
|
||||||
// discovery.discoverNode((ArtPollReplyPacket) packet);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public void artNetServerStarted(ArtNetServer artNetServer) {
|
|
||||||
// logger.fine("server started callback");
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public void artNetServerStopped(ArtNetServer artNetServer) {
|
|
||||||
// logger.info("server stopped");
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
}
|
|
||||||
|
|
||||||
// public void removeServerListener(ArtNetServerListener l) {
|
|
||||||
// server.removeListener(l);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// public void setBroadCastAddress(String ip) {
|
|
||||||
// server.setBroadcastAddress(ip);
|
|
||||||
// }
|
|
||||||
|
|
||||||
public void start() throws SocketException, ArtNetException {
|
|
||||||
if (server == null) {
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
server.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
// public void startNodeDiscovery() throws ArtNetException {
|
|
||||||
// getNodeDiscovery().start();
|
|
||||||
// }
|
|
||||||
|
|
||||||
public void stop() {
|
|
||||||
// if (discovery != null) {
|
|
||||||
// discovery.stop();
|
|
||||||
// }
|
|
||||||
if (server != null) {
|
|
||||||
server.stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// /**
|
|
||||||
// * Sends the given packet to the specified Art-Net node.
|
|
||||||
// *
|
|
||||||
// * @param packet
|
|
||||||
// * @param node
|
|
||||||
// */
|
|
||||||
// public void unicastPacket(ArtNetPacket packet, ArtNetNode node) {
|
|
||||||
// server.unicastPacket(packet, node.getIPAddress());
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Sends the given packet to the specified IP address.
|
|
||||||
// *
|
|
||||||
// * @param packet
|
|
||||||
// * @param adr
|
|
||||||
// */
|
|
||||||
// public void unicastPacket(ArtNetPacket packet, InetAddress adr) {
|
|
||||||
// server.unicastPacket(packet, adr);
|
|
||||||
// }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sends the given packet to the specified IP address.
|
|
||||||
*
|
|
||||||
* @param packet
|
|
||||||
* @param adr
|
|
||||||
*/
|
|
||||||
public void unicastPacket(ArtNetPacket packet, String adr) {
|
|
||||||
InetAddress targetAdress;
|
|
||||||
try {
|
|
||||||
targetAdress = InetAddress.getByName(adr);
|
|
||||||
server.unicastPacket(packet, targetAdress);
|
|
||||||
} catch (UnknownHostException e) {
|
|
||||||
logger.log(Level.WARNING, e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,33 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of artnet4j.
|
|
||||||
*
|
|
||||||
* Copyright 2009 Karsten Schmidt (PostSpectacular Ltd.)
|
|
||||||
*
|
|
||||||
* artnet4j is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* artnet4j is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with artnet4j. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package artnet4j;
|
|
||||||
|
|
||||||
public class ArtNetException extends Exception {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
public ArtNetException(String message) {
|
|
||||||
super(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ArtNetException(String message, Throwable cause) {
|
|
||||||
super(message, cause);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,170 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of artnet4j.
|
|
||||||
*
|
|
||||||
* Copyright 2009 Karsten Schmidt (PostSpectacular Ltd.)
|
|
||||||
*
|
|
||||||
* artnet4j is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* artnet4j is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with artnet4j. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package artnet4j;
|
|
||||||
|
|
||||||
import java.net.InetAddress;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
import artnet4j.packets.ArtPollReplyPacket;
|
|
||||||
import artnet4j.packets.ByteUtils;
|
|
||||||
|
|
||||||
public class ArtNetNode {
|
|
||||||
|
|
||||||
protected static final Logger logger = Logger.getLogger(ArtNetNode.class
|
|
||||||
.getClass().getName());
|
|
||||||
|
|
||||||
protected final NodeStyle nodeStyle;
|
|
||||||
|
|
||||||
private InetAddress ip;
|
|
||||||
|
|
||||||
private int subSwitch;
|
|
||||||
|
|
||||||
private int oemCode;
|
|
||||||
|
|
||||||
private int nodeStatus;
|
|
||||||
private NodeReportCode reportCode;
|
|
||||||
|
|
||||||
private String shortName;
|
|
||||||
private String longName;
|
|
||||||
|
|
||||||
private int numPorts;
|
|
||||||
private PortDescriptor[] ports;
|
|
||||||
private byte[] dmxIns;
|
|
||||||
private byte[] dmxOuts;
|
|
||||||
|
|
||||||
public ArtNetNode() {
|
|
||||||
this(NodeStyle.ST_NODE);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ArtNetNode(NodeStyle style) {
|
|
||||||
nodeStyle = style;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void extractConfig(ArtPollReplyPacket source) {
|
|
||||||
setIPAddress(source.getIPAddress());
|
|
||||||
subSwitch = source.getSubSwitch();
|
|
||||||
oemCode = source.getOEMCode();
|
|
||||||
nodeStatus = source.getNodeStatus();
|
|
||||||
shortName = source.getShortName();
|
|
||||||
longName = source.getLongName();
|
|
||||||
ports = source.getPorts();
|
|
||||||
numPorts = ports.length;
|
|
||||||
reportCode = source.getReportCode();
|
|
||||||
dmxIns = source.getDmxIns();
|
|
||||||
dmxOuts = source.getDmxOuts();
|
|
||||||
logger.info("updated node config");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the dmxIns
|
|
||||||
*/
|
|
||||||
public byte[] getDmxIns() {
|
|
||||||
return dmxIns;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the dmxOuts
|
|
||||||
*/
|
|
||||||
public byte[] getDmxOuts() {
|
|
||||||
return dmxOuts;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the ip
|
|
||||||
*/
|
|
||||||
public InetAddress getIPAddress() {
|
|
||||||
return ip;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the longName
|
|
||||||
*/
|
|
||||||
public String getLongName() {
|
|
||||||
return longName;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the nodeStatus
|
|
||||||
*/
|
|
||||||
public int getNodeStatus() {
|
|
||||||
return nodeStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the nodeStyle
|
|
||||||
*/
|
|
||||||
public NodeStyle getNodeStyle() {
|
|
||||||
return nodeStyle;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the numPorts
|
|
||||||
*/
|
|
||||||
public int getNumPorts() {
|
|
||||||
return numPorts;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the oemCode
|
|
||||||
*/
|
|
||||||
public int getOemCode() {
|
|
||||||
return oemCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the ports
|
|
||||||
*/
|
|
||||||
public PortDescriptor[] getPorts() {
|
|
||||||
return ports;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the reportCode
|
|
||||||
*/
|
|
||||||
public NodeReportCode getReportCode() {
|
|
||||||
return reportCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the shortName
|
|
||||||
*/
|
|
||||||
public String getShortName() {
|
|
||||||
return shortName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getSubNet() {
|
|
||||||
return subSwitch;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSubNetAsHex() {
|
|
||||||
return ByteUtils.hex(subSwitch, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setIPAddress(InetAddress ip) {
|
|
||||||
this.ip = ip;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "node: " + nodeStyle + " " + ip + " " + longName + ", "
|
|
||||||
+ numPorts + " ports, subswitch: "
|
|
||||||
+ ByteUtils.hex(subSwitch, 2);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,132 +0,0 @@
|
||||||
///*
|
|
||||||
// * This file is part of artnet4j.
|
|
||||||
// *
|
|
||||||
// * Copyright 2009 Karsten Schmidt (PostSpectacular Ltd.)
|
|
||||||
// *
|
|
||||||
// * artnet4j is free software: you can redistribute it and/or modify
|
|
||||||
// * it under the terms of the GNU General Public License as published by
|
|
||||||
// * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// * (at your option) any later version.
|
|
||||||
// *
|
|
||||||
// * artnet4j is distributed in the hope that it will be useful,
|
|
||||||
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// * GNU General Public License for more details.
|
|
||||||
// *
|
|
||||||
// * You should have received a copy of the GNU General Public License
|
|
||||||
// * along with artnet4j. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
// */
|
|
||||||
//
|
|
||||||
//package artnet4j;
|
|
||||||
//
|
|
||||||
//import java.net.InetAddress;
|
|
||||||
//import java.util.ArrayList;
|
|
||||||
//import java.util.List;
|
|
||||||
//import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
//import java.util.logging.Logger;
|
|
||||||
//
|
|
||||||
//import artnet4j.events.ArtNetDiscoveryListener;
|
|
||||||
//import artnet4j.packets.ArtPollPacket;
|
|
||||||
//import artnet4j.packets.ArtPollReplyPacket;
|
|
||||||
//
|
|
||||||
//public class ArtNetNodeDiscovery implements Runnable {
|
|
||||||
//
|
|
||||||
// public static final int POLL_INTERVAL = 10000;
|
|
||||||
//
|
|
||||||
// public static final Logger logger = Logger
|
|
||||||
// .getLogger(ArtNetNodeDiscovery.class.getClass().getName());
|
|
||||||
//
|
|
||||||
// protected final ArtNet artNet;
|
|
||||||
// protected ConcurrentHashMap<InetAddress, ArtNetNode> discoveredNodes = new ConcurrentHashMap<InetAddress, ArtNetNode>();
|
|
||||||
// protected List<ArtNetNode> lastDiscovered = new ArrayList<ArtNetNode>();
|
|
||||||
// protected List<ArtNetDiscoveryListener> listeners = new ArrayList<ArtNetDiscoveryListener>();
|
|
||||||
//
|
|
||||||
// protected boolean isActive = true;
|
|
||||||
//
|
|
||||||
// protected long discoveryInterval;
|
|
||||||
//
|
|
||||||
// private Thread discoveryThread;
|
|
||||||
//
|
|
||||||
// public ArtNetNodeDiscovery(ArtNet artNet) {
|
|
||||||
// this.artNet = artNet;
|
|
||||||
// setInterval(POLL_INTERVAL);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// public void addListener(ArtNetDiscoveryListener l) {
|
|
||||||
// synchronized (listeners) {
|
|
||||||
// listeners.add(l);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// public void discoverNode(ArtPollReplyPacket reply) {
|
|
||||||
// InetAddress nodeIP = reply.getIPAddress();
|
|
||||||
// ArtNetNode node = discoveredNodes.get(nodeIP);
|
|
||||||
// if (node == null) {
|
|
||||||
// logger.info("discovered new node: " + nodeIP);
|
|
||||||
// node = reply.getNodeStyle().createNode();
|
|
||||||
// node.extractConfig(reply);
|
|
||||||
// discoveredNodes.put(nodeIP, node);
|
|
||||||
// for (ArtNetDiscoveryListener l : listeners) {
|
|
||||||
// l.discoveredNewNode(node);
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// node.extractConfig(reply);
|
|
||||||
// }
|
|
||||||
// lastDiscovered.add(node);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// public void removeListener(ArtNetDiscoveryListener l) {
|
|
||||||
// synchronized (listeners) {
|
|
||||||
// listeners.remove(l);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public void run() {
|
|
||||||
// try {
|
|
||||||
// while (isActive) {
|
|
||||||
// lastDiscovered.clear();
|
|
||||||
// ArtPollPacket poll = new ArtPollPacket();
|
|
||||||
// artNet.broadcastPacket(poll);
|
|
||||||
// Thread.sleep(ArtNet.ARTPOLL_REPLY_TIMEOUT);
|
|
||||||
// if (isActive) {
|
|
||||||
// synchronized (listeners) {
|
|
||||||
// for (ArtNetNode node : discoveredNodes.values()) {
|
|
||||||
// if (!lastDiscovered.contains(node)) {
|
|
||||||
// discoveredNodes.remove(node.getIPAddress());
|
|
||||||
// for (ArtNetDiscoveryListener l : listeners) {
|
|
||||||
// l.discoveredNodeDisconnected(node);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// for (ArtNetDiscoveryListener l : listeners) {
|
|
||||||
// l.discoveryCompleted(new ArrayList<ArtNetNode>(
|
|
||||||
// discoveredNodes.values()));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// Thread.sleep(discoveryInterval
|
|
||||||
// - ArtNet.ARTPOLL_REPLY_TIMEOUT);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// } catch (InterruptedException e) {
|
|
||||||
// logger.warning("node discovery interrupted");
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// public void setInterval(int interval) {
|
|
||||||
// discoveryInterval = Math.max(interval, ArtNet.ARTPOLL_REPLY_TIMEOUT);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// public void start() throws ArtNetException {
|
|
||||||
// if (discoveryThread == null) {
|
|
||||||
// discoveryThread = new Thread(this);
|
|
||||||
// discoveryThread.start();
|
|
||||||
// } else {
|
|
||||||
// throw new ArtNetException("discovery already started.");
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// public void stop() {
|
|
||||||
// isActive = false;
|
|
||||||
// }
|
|
||||||
//}
|
|
|
@ -1,179 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of artnet4j.
|
|
||||||
*
|
|
||||||
* Copyright 2009 Karsten Schmidt (PostSpectacular Ltd.)
|
|
||||||
*
|
|
||||||
* artnet4j is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* artnet4j is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with artnet4j. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package artnet4j;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.DatagramPacket;
|
|
||||||
import java.net.DatagramSocket;
|
|
||||||
import java.net.InetAddress;
|
|
||||||
import java.net.SocketException;
|
|
||||||
import java.net.UnknownHostException;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
|
|
||||||
import artnet4j.packets.ArtNetPacket;
|
|
||||||
|
|
||||||
public class ArtNetServer extends ArtNetNode { // implements Runnable {
|
|
||||||
|
|
||||||
public static final int DEFAULT_PORT = 0x1936;
|
|
||||||
|
|
||||||
public static final String DEFAULT_BROADCAST_IP = "2.255.255.255";
|
|
||||||
|
|
||||||
protected final int port;
|
|
||||||
protected final int sendPort;
|
|
||||||
|
|
||||||
protected DatagramSocket socket;
|
|
||||||
protected InetAddress broadCastAddress;
|
|
||||||
protected Thread serverThread;
|
|
||||||
|
|
||||||
protected int receiveBufferSize;
|
|
||||||
protected boolean isRunning;
|
|
||||||
|
|
||||||
// protected final List<ArtNetServerListener> listeners;
|
|
||||||
|
|
||||||
public ArtNetServer() {
|
|
||||||
this(DEFAULT_PORT, DEFAULT_PORT);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ArtNetServer(int port, int sendPort) {
|
|
||||||
super(NodeStyle.ST_SERVER);
|
|
||||||
this.port = port;
|
|
||||||
this.sendPort = sendPort;
|
|
||||||
// this.listeners = new ArrayList<ArtNetServerListener>();
|
|
||||||
setBufferSize(2048);
|
|
||||||
}
|
|
||||||
|
|
||||||
// public void addListener(ArtNetServerListener l) {
|
|
||||||
// synchronized (listeners) {
|
|
||||||
// listeners.add(l);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// public void broadcastPacket(ArtNetPacket ap) {
|
|
||||||
// try {
|
|
||||||
// DatagramPacket packet = new DatagramPacket(ap.getData(), ap
|
|
||||||
// .getLength(), broadCastAddress, sendPort);
|
|
||||||
// socket.send(packet);
|
|
||||||
// for (ArtNetServerListener l : listeners) {
|
|
||||||
// l.artNetPacketBroadcasted(ap);
|
|
||||||
// }
|
|
||||||
// } catch (IOException e) {
|
|
||||||
// logger.warning(e.getMessage());
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// public void removeListener(ArtNetServerListener l) {
|
|
||||||
// synchronized (listeners) {
|
|
||||||
// listeners.remove(l);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// @Override
|
|
||||||
// public void run() {
|
|
||||||
// byte[] receiveBuffer = new byte[receiveBufferSize];
|
|
||||||
// DatagramPacket receivedPacket = new DatagramPacket(receiveBuffer, receiveBuffer.length);
|
|
||||||
//
|
|
||||||
// try {
|
|
||||||
// while (isRunning) {
|
|
||||||
// socket.receive(receivedPacket);
|
|
||||||
// logger.finer("received new packet");
|
|
||||||
// ArtNetPacket packet = ArtNetPacketParser.parse(receivedPacket);
|
|
||||||
// if (packet != null) {
|
|
||||||
// if (packet.getType() == PacketType.ART_POLL) {
|
|
||||||
// sendArtPollReply(receivedPacket.getAddress(), (ArtPollPacket) packet);
|
|
||||||
// }
|
|
||||||
// for (ArtNetServerListener l : listeners) {
|
|
||||||
// l.artNetPacketReceived(packet);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// socket.close();
|
|
||||||
// logger.info("server thread terminated.");
|
|
||||||
// for (ArtNetServerListener l : listeners) {
|
|
||||||
// l.artNetServerStopped(this);
|
|
||||||
// }
|
|
||||||
// } catch (IOException e) {
|
|
||||||
// e.printStackTrace();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// private void sendArtPollReply(InetAddress inetAddress, ArtPollPacket packet) {
|
|
||||||
// // TODO send reply with self description
|
|
||||||
// }
|
|
||||||
|
|
||||||
public void setBroadcastAddress(String address) {
|
|
||||||
try {
|
|
||||||
broadCastAddress = InetAddress.getByName(address);
|
|
||||||
logger.fine("broadcast IP set to: " + broadCastAddress);
|
|
||||||
} catch (UnknownHostException e) {
|
|
||||||
logger.log(Level.WARNING, e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setBufferSize(int size) {
|
|
||||||
if (!isRunning) {
|
|
||||||
receiveBufferSize = size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void start() throws SocketException, ArtNetException {
|
|
||||||
if (broadCastAddress == null) {
|
|
||||||
setBroadcastAddress(DEFAULT_BROADCAST_IP);
|
|
||||||
}
|
|
||||||
if (socket == null) {
|
|
||||||
// socket = new DatagramSocket(port);
|
|
||||||
socket = new DatagramSocket();
|
|
||||||
// logger.info("Art-Net server started at port: " + port);
|
|
||||||
// for (ArtNetServerListener l : listeners) {
|
|
||||||
// l.artNetServerStarted(this);
|
|
||||||
// }
|
|
||||||
isRunning = true;
|
|
||||||
// serverThread = new Thread(this);
|
|
||||||
// serverThread.start();
|
|
||||||
} else {
|
|
||||||
throw new ArtNetException(
|
|
||||||
"Couldn't create server socket, server already running?");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void stop() {
|
|
||||||
isRunning = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sends the given packet to the specified IP address.
|
|
||||||
*
|
|
||||||
* @param ap
|
|
||||||
* @param targetAdress
|
|
||||||
*/
|
|
||||||
public void unicastPacket(ArtNetPacket ap, InetAddress targetAdress) {
|
|
||||||
try {
|
|
||||||
DatagramPacket packet = new DatagramPacket(ap.getData(), ap.getLength(), targetAdress, sendPort);
|
|
||||||
|
|
||||||
socket.send(packet);
|
|
||||||
logger.finer("sent packet to: " + targetAdress);
|
|
||||||
|
|
||||||
// for (ArtNetServerListener l : listeners) {
|
|
||||||
// l.artNetPacketUnicasted(ap);
|
|
||||||
// }
|
|
||||||
} catch (IOException e) {
|
|
||||||
logger.warning(e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,122 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of artnet4j.
|
|
||||||
*
|
|
||||||
* Copyright 2009 Karsten Schmidt (PostSpectacular Ltd.)
|
|
||||||
*
|
|
||||||
* artnet4j is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* artnet4j is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with artnet4j. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package artnet4j;
|
|
||||||
|
|
||||||
import artnet4j.packets.ArtDmxPacket;
|
|
||||||
|
|
||||||
public class DmxUniverse {
|
|
||||||
|
|
||||||
protected final DmxUniverseConfig config;
|
|
||||||
protected final byte[] frameData;
|
|
||||||
|
|
||||||
protected ArtNetNode node;
|
|
||||||
protected boolean isEnabled = true;
|
|
||||||
protected boolean isActive = true;
|
|
||||||
|
|
||||||
public DmxUniverse(ArtNetNode node, DmxUniverseConfig config) {
|
|
||||||
this.node = node;
|
|
||||||
this.config = config;
|
|
||||||
frameData = new byte[0x200];
|
|
||||||
}
|
|
||||||
|
|
||||||
public DmxUniverseConfig getConfig() {
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getID() {
|
|
||||||
return config.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ArtNetNode getNode() {
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getNumChannels() {
|
|
||||||
return config.numDmxChannels;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ArtDmxPacket getPacket(int sequenceID) {
|
|
||||||
ArtDmxPacket packet = new ArtDmxPacket();
|
|
||||||
packet.setSequenceID(sequenceID);
|
|
||||||
packet.setUniverse(node.getSubNet(), config.universeID);
|
|
||||||
// FIXME Art-Lynx OP has firmware issue with packet lengths < 512
|
|
||||||
// channels
|
|
||||||
// packet.setDMX(frameData, config.numDmxChannels);
|
|
||||||
packet.setDMX(frameData, config.ignoreNumChannels
|
|
||||||
? 0x200
|
|
||||||
: config.numDmxChannels);
|
|
||||||
return packet;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the isActive
|
|
||||||
*/
|
|
||||||
public boolean isActive() {
|
|
||||||
return isActive;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the isEnabled
|
|
||||||
*/
|
|
||||||
public boolean isEnabled() {
|
|
||||||
return isEnabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param isActive
|
|
||||||
* the isActive to sunsetTime
|
|
||||||
*/
|
|
||||||
public void setActive(boolean isActive) {
|
|
||||||
this.isActive = isActive;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setChannel(int offset, int val) {
|
|
||||||
frameData[offset] = (byte) val;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param isEnabled
|
|
||||||
* the isEnabled to sunsetTime
|
|
||||||
*/
|
|
||||||
public void setEnabled(boolean isEnabled) {
|
|
||||||
this.isEnabled = isEnabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param node
|
|
||||||
* the node to sunsetTime
|
|
||||||
*/
|
|
||||||
public void setNode(ArtNetNode node) {
|
|
||||||
this.node = node;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRGBPixel(int offset, int col) {
|
|
||||||
offset *= 3;
|
|
||||||
frameData[offset] = (byte) (col >> 16 & 0xff);
|
|
||||||
frameData[offset + 1] = (byte) (col >> 8 & 0xff);
|
|
||||||
frameData[offset + 2] = (byte) (col & 0xff);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return node.getIPAddress() + "u: " + config.universeID + " st: "
|
|
||||||
+ isEnabled + "/" + isActive + " c: " + config.numDmxChannels;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,53 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of artnet4j.
|
|
||||||
*
|
|
||||||
* Copyright 2009 Karsten Schmidt (PostSpectacular Ltd.)
|
|
||||||
*
|
|
||||||
* artnet4j is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* artnet4j is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with artnet4j. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package artnet4j;
|
|
||||||
|
|
||||||
import java.net.InetAddress;
|
|
||||||
|
|
||||||
import javax.xml.bind.annotation.XmlAttribute;
|
|
||||||
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
|
|
||||||
|
|
||||||
public class DmxUniverseConfig {
|
|
||||||
|
|
||||||
@XmlAttribute
|
|
||||||
public String id;
|
|
||||||
|
|
||||||
@XmlAttribute
|
|
||||||
@XmlJavaTypeAdapter(InetAddressAdapter.class)
|
|
||||||
public InetAddress ip;
|
|
||||||
|
|
||||||
@XmlAttribute(name = "universe")
|
|
||||||
public int universeID;
|
|
||||||
|
|
||||||
@XmlAttribute(name = "numchannels")
|
|
||||||
public int numDmxChannels;
|
|
||||||
|
|
||||||
@XmlAttribute(name = "port")
|
|
||||||
public int serverPort;
|
|
||||||
|
|
||||||
@XmlAttribute
|
|
||||||
public boolean ignoreNumChannels;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "nodeConfig: id=" + id + ", ip=" + ip + ", uid=" + universeID
|
|
||||||
+ ", nc=" + numDmxChannels;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,38 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of artnet4j.
|
|
||||||
*
|
|
||||||
* Copyright 2009 Karsten Schmidt (PostSpectacular Ltd.)
|
|
||||||
*
|
|
||||||
* artnet4j is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* artnet4j is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with artnet4j. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package artnet4j;
|
|
||||||
|
|
||||||
import java.net.InetAddress;
|
|
||||||
|
|
||||||
import javax.xml.bind.annotation.adapters.XmlAdapter;
|
|
||||||
|
|
||||||
public class InetAddressAdapter extends XmlAdapter<String, InetAddress> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String marshal(InetAddress adr) throws Exception {
|
|
||||||
return adr.getHostAddress();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public InetAddress unmarshal(String adr) throws Exception {
|
|
||||||
return InetAddress.getByName(adr);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,78 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of artnet4j.
|
|
||||||
*
|
|
||||||
* Copyright 2009 Karsten Schmidt (PostSpectacular Ltd.)
|
|
||||||
*
|
|
||||||
* artnet4j is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* artnet4j is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with artnet4j. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package artnet4j;
|
|
||||||
|
|
||||||
public enum NodeReportCode {
|
|
||||||
|
|
||||||
RcDebug("#0000", "Booted in debug mode"),
|
|
||||||
RcPowerOk("#0001", "Power On Tests successful"),
|
|
||||||
RcPowerFail("#0002", "Hardware tests failed at Power On"),
|
|
||||||
RcSocketWr1(
|
|
||||||
"#0003",
|
|
||||||
"Last UDP from Node failed due to truncated length. Most likely caused by a collision."),
|
|
||||||
RcParseFail("#0004",
|
|
||||||
"Unable to identify last UDP transmission. Check OpCode and packet length."),
|
|
||||||
RcUdpFail("#0005", "Unable to open Udp Socket in last transmission attempt"),
|
|
||||||
RcShNameOk("#0006",
|
|
||||||
"Confirms that Short Name programming via ArtAddress, was successful."),
|
|
||||||
RcLoNameOk("#0007",
|
|
||||||
"Confirms that Long Name programming via ArtAddress, was successful."),
|
|
||||||
RcDmxError("#0008", "DMX512 receive errors detected."), RcDmxUdpFull(
|
|
||||||
"#0009", "Ran out of internal DMX transmit buffers."), RcDmxRxFull(
|
|
||||||
"#000a", "Ran out of internal DMX Rx buffers."), RcSwitchErr(
|
|
||||||
"#000b", "Rx Universe switches conflict."), RcConfigErr("#000c",
|
|
||||||
"Product configuration does not match firmware."), RcDmxShort(
|
|
||||||
"#000d", "DMX output short detected. See GoodOutput field."),
|
|
||||||
RcFirmwareFail("#000e", "Last attempt to upload new firmware failed."),
|
|
||||||
RcUserFail("#000f",
|
|
||||||
"User changed switch settings when address locked by remote.");
|
|
||||||
|
|
||||||
public static NodeReportCode getForID(String id) {
|
|
||||||
NodeReportCode code = null;
|
|
||||||
for (NodeReportCode c : values()) {
|
|
||||||
if (c.id.equalsIgnoreCase(id)) {
|
|
||||||
code = c;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final String id;
|
|
||||||
private final String description;
|
|
||||||
|
|
||||||
private NodeReportCode(String id, String desc) {
|
|
||||||
this.id = id;
|
|
||||||
this.description = desc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the description
|
|
||||||
*/
|
|
||||||
public String getDescription() {
|
|
||||||
return description;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the id
|
|
||||||
*/
|
|
||||||
public String getID() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,50 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of artnet4j.
|
|
||||||
*
|
|
||||||
* Copyright 2009 Karsten Schmidt (PostSpectacular Ltd.)
|
|
||||||
*
|
|
||||||
* artnet4j is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* artnet4j is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with artnet4j. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package artnet4j;
|
|
||||||
|
|
||||||
public enum NodeStyle {
|
|
||||||
ST_NODE(0, ArtNetNode.class), ST_SERVER(1, ArtNetServer.class), ST_MEDIA(2,
|
|
||||||
ArtNetNode.class), ST_ROUTER(3, ArtNetNode.class), ST_BACKUP(4,
|
|
||||||
ArtNetNode.class), ST_CONFIG(5, ArtNetNode.class);
|
|
||||||
|
|
||||||
private int id;
|
|
||||||
private Class<? extends ArtNetNode> nodeClass;
|
|
||||||
|
|
||||||
private NodeStyle(int id, Class<? extends ArtNetNode> nodeClass) {
|
|
||||||
this.id = id;
|
|
||||||
this.nodeClass = nodeClass;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ArtNetNode createNode() {
|
|
||||||
ArtNetNode node = null;
|
|
||||||
try {
|
|
||||||
node = nodeClass.newInstance();
|
|
||||||
} catch (InstantiationException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getStyleID() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,65 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of artnet4j.
|
|
||||||
*
|
|
||||||
* Copyright 2009 Karsten Schmidt (PostSpectacular Ltd.)
|
|
||||||
*
|
|
||||||
* artnet4j is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* artnet4j is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with artnet4j. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package artnet4j;
|
|
||||||
|
|
||||||
public class PortDescriptor {
|
|
||||||
|
|
||||||
protected boolean canOutput;
|
|
||||||
protected boolean canInput;
|
|
||||||
protected PortType type;
|
|
||||||
|
|
||||||
public PortDescriptor(int id) {
|
|
||||||
canOutput = (id & 0x80) > 0;
|
|
||||||
canInput = (id & 0x40) > 0;
|
|
||||||
id &= 0x3f;
|
|
||||||
for (PortType t : PortType.values()) {
|
|
||||||
if (id == t.getPortID()) {
|
|
||||||
type = t;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the canInput
|
|
||||||
*/
|
|
||||||
public boolean canInput() {
|
|
||||||
return canInput;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the canOutput
|
|
||||||
*/
|
|
||||||
public boolean canOutput() {
|
|
||||||
return canOutput;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the type
|
|
||||||
*/
|
|
||||||
public PortType getType() {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "PortDescriptor: " + type + " out: " + canOutput + " in: "
|
|
||||||
+ canInput;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,33 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of artnet4j.
|
|
||||||
*
|
|
||||||
* Copyright 2009 Karsten Schmidt (PostSpectacular Ltd.)
|
|
||||||
*
|
|
||||||
* artnet4j is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* artnet4j is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with artnet4j. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package artnet4j;
|
|
||||||
|
|
||||||
public enum PortType {
|
|
||||||
DMX512(0), MIDI(1), AVAB(2), COLORTRAN(3), ADB62_5(4), ARTNET(5);
|
|
||||||
|
|
||||||
private int id;
|
|
||||||
|
|
||||||
private PortType(int id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getPortID() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,47 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of artnet4j.
|
|
||||||
*
|
|
||||||
* Copyright 2009 Karsten Schmidt (PostSpectacular Ltd.)
|
|
||||||
*
|
|
||||||
* artnet4j is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* artnet4j is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with artnet4j. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package artnet4j.events;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import artnet4j.ArtNetNode;
|
|
||||||
|
|
||||||
public class ArtNetDiscoveryEventAdapter implements ArtNetDiscoveryListener {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void discoveredNewNode(ArtNetNode node) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void discoveredNodeDisconnected(ArtNetNode node) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void discoveryCompleted(List<ArtNetNode> nodes) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void discoveryFailed(Throwable t) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,35 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of artnet4j.
|
|
||||||
*
|
|
||||||
* Copyright 2009 Karsten Schmidt (PostSpectacular Ltd.)
|
|
||||||
*
|
|
||||||
* artnet4j is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* artnet4j is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with artnet4j. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package artnet4j.events;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import artnet4j.ArtNetNode;
|
|
||||||
|
|
||||||
public interface ArtNetDiscoveryListener {
|
|
||||||
|
|
||||||
void discoveredNewNode(ArtNetNode node);
|
|
||||||
|
|
||||||
void discoveredNodeDisconnected(ArtNetNode node);
|
|
||||||
|
|
||||||
void discoveryCompleted(List<ArtNetNode> nodes);
|
|
||||||
|
|
||||||
void discoveryFailed(Throwable t);
|
|
||||||
}
|
|
|
@ -1,70 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of artnet4j.
|
|
||||||
*
|
|
||||||
* Copyright 2009 Karsten Schmidt (PostSpectacular Ltd.)
|
|
||||||
*
|
|
||||||
* artnet4j is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* artnet4j is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with artnet4j. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package artnet4j.events;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of artnet4j.
|
|
||||||
*
|
|
||||||
* Copyright 2009 Karsten Schmidt (PostSpectacular Ltd.)
|
|
||||||
*
|
|
||||||
* artnet4j is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* artnet4j is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with artnet4j. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import artnet4j.ArtNetServer;
|
|
||||||
import artnet4j.packets.ArtNetPacket;
|
|
||||||
|
|
||||||
public class ArtNetServerEventAdapter implements ArtNetServerListener {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void artNetPacketBroadcasted(ArtNetPacket packet) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void artNetPacketReceived(ArtNetPacket packet) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void artNetPacketUnicasted(ArtNetPacket packet) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void artNetServerStarted(ArtNetServer server) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void artNetServerStopped(ArtNetServer server) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of artnet4j.
|
|
||||||
*
|
|
||||||
* Copyright 2009 Karsten Schmidt (PostSpectacular Ltd.)
|
|
||||||
*
|
|
||||||
* artnet4j is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* artnet4j is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with artnet4j. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package artnet4j.events;
|
|
||||||
|
|
||||||
import artnet4j.ArtNetServer;
|
|
||||||
import artnet4j.packets.ArtNetPacket;
|
|
||||||
|
|
||||||
public interface ArtNetServerListener {
|
|
||||||
|
|
||||||
void artNetPacketBroadcasted(ArtNetPacket packet);
|
|
||||||
|
|
||||||
void artNetPacketReceived(ArtNetPacket packet);
|
|
||||||
|
|
||||||
void artNetPacketUnicasted(ArtNetPacket packet);
|
|
||||||
|
|
||||||
void artNetServerStarted(ArtNetServer server);
|
|
||||||
|
|
||||||
void artNetServerStopped(ArtNetServer server);
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,69 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of artnet4j.
|
|
||||||
*
|
|
||||||
* Copyright 2009 Karsten Schmidt (PostSpectacular Ltd.)
|
|
||||||
*
|
|
||||||
* artnet4j is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* artnet4j is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with artnet4j. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package artnet4j.packets;
|
|
||||||
|
|
||||||
import java.net.DatagramPacket;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
public class ArtNetPacketParser {
|
|
||||||
|
|
||||||
public static final Logger logger =
|
|
||||||
Logger.getLogger(ArtNetPacketParser.class.getClass().getName());
|
|
||||||
|
|
||||||
public static ArtNetPacket createPacketForOpCode(int opCode, byte[] data) {
|
|
||||||
logger.finer("creating packet instance for opcode: 0x"
|
|
||||||
+ ByteUtils.hex(opCode, 4));
|
|
||||||
ArtNetPacket packet = null;
|
|
||||||
for (PacketType type : PacketType.values()) {
|
|
||||||
if (opCode == type.getOpCode()) {
|
|
||||||
packet = type.createPacket();
|
|
||||||
if (packet != null) {
|
|
||||||
packet.parse(data);
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
logger.fine("packet type valid, but not yet supported: "
|
|
||||||
+ type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return packet;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ArtNetPacket parse(byte[] raw, int offset, int length) {
|
|
||||||
ArtNetPacket packet = null;
|
|
||||||
ByteUtils data = new ByteUtils(raw);
|
|
||||||
if (data.length > 10) {
|
|
||||||
if (data.compareBytes(ArtNetPacket.HEADER, 0, 8)) {
|
|
||||||
int opCode = data.getInt16LE(8);
|
|
||||||
packet = createPacketForOpCode(opCode, raw);
|
|
||||||
} else {
|
|
||||||
logger.warning("invalid header");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
logger.warning("invalid packet length: " + data.length);
|
|
||||||
}
|
|
||||||
return packet;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ArtNetPacket parse(DatagramPacket receivedPacket) {
|
|
||||||
return parse(receivedPacket.getData(), receivedPacket.getOffset(),
|
|
||||||
receivedPacket.getLength());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,65 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of artnet4j.
|
|
||||||
*
|
|
||||||
* Copyright 2009 Karsten Schmidt (PostSpectacular Ltd.)
|
|
||||||
*
|
|
||||||
* artnet4j is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* artnet4j is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with artnet4j. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package artnet4j.packets;
|
|
||||||
|
|
||||||
public class ArtPollPacket extends ArtNetPacket {
|
|
||||||
|
|
||||||
private static int ARTPOLL_LENGTH = 14;
|
|
||||||
|
|
||||||
private boolean replyOnce;
|
|
||||||
private boolean replyDirect;
|
|
||||||
|
|
||||||
public ArtPollPacket() {
|
|
||||||
this(true, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ArtPollPacket(boolean replyOnce, boolean replyDirect) {
|
|
||||||
super(PacketType.ART_POLL);
|
|
||||||
setData(new byte[ARTPOLL_LENGTH]);
|
|
||||||
setHeader();
|
|
||||||
setProtocol();
|
|
||||||
setTalkToMe(replyOnce, replyDirect);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getLength() {
|
|
||||||
return data.getLength();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean parse(byte[] raw) {
|
|
||||||
setData(raw, ARTPOLL_LENGTH);
|
|
||||||
int talk = data.getInt8(12);
|
|
||||||
replyOnce = 0 == (talk & 0x02);
|
|
||||||
replyDirect = 1 == (talk & 0x01);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setTalkToMe(boolean replyOnce, boolean replyDirect) {
|
|
||||||
this.replyOnce = replyOnce;
|
|
||||||
this.replyDirect = replyDirect;
|
|
||||||
data.setInt8((replyOnce ? 0 : 2) | (replyDirect ? 1 : 0), 12);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return type + ": reply once:" + replyOnce + " direct: " + replyDirect;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,185 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of artnet4j.
|
|
||||||
*
|
|
||||||
* Copyright 2009 Karsten Schmidt (PostSpectacular Ltd.)
|
|
||||||
*
|
|
||||||
* artnet4j is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* artnet4j is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with artnet4j. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package artnet4j.packets;
|
|
||||||
|
|
||||||
import java.net.InetAddress;
|
|
||||||
import java.net.UnknownHostException;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
|
|
||||||
import artnet4j.NodeReportCode;
|
|
||||||
import artnet4j.NodeStyle;
|
|
||||||
import artnet4j.PortDescriptor;
|
|
||||||
|
|
||||||
public class ArtPollReplyPacket extends ArtNetPacket {
|
|
||||||
|
|
||||||
private InetAddress ip;
|
|
||||||
|
|
||||||
private int subSwitch;
|
|
||||||
private int oemCode;
|
|
||||||
private int nodeStatus;
|
|
||||||
|
|
||||||
private String shortName;
|
|
||||||
private String longName;
|
|
||||||
|
|
||||||
private int numPorts;
|
|
||||||
private PortDescriptor[] ports;
|
|
||||||
|
|
||||||
private NodeStyle nodeStyle;
|
|
||||||
private NodeReportCode reportCode;
|
|
||||||
|
|
||||||
private byte[] dmxIns;
|
|
||||||
private byte[] dmxOuts;
|
|
||||||
|
|
||||||
public ArtPollReplyPacket() {
|
|
||||||
super(PacketType.ART_POLL_REPLY);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ArtPollReplyPacket(byte[] data) {
|
|
||||||
super(PacketType.ART_POLL_REPLY);
|
|
||||||
setData(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the dmxIns
|
|
||||||
*/
|
|
||||||
public byte[] getDmxIns() {
|
|
||||||
return dmxIns;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the dmxOuts
|
|
||||||
*/
|
|
||||||
public byte[] getDmxOuts() {
|
|
||||||
return dmxOuts;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the ip
|
|
||||||
*/
|
|
||||||
public InetAddress getIPAddress() {
|
|
||||||
InetAddress ipClone = null;
|
|
||||||
try {
|
|
||||||
ipClone = InetAddress.getByAddress(ip.getAddress());
|
|
||||||
} catch (UnknownHostException e) {
|
|
||||||
}
|
|
||||||
return ipClone;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getLongName() {
|
|
||||||
return longName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getNodeStatus() {
|
|
||||||
return nodeStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
public NodeStyle getNodeStyle() {
|
|
||||||
return nodeStyle;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getOEMCode() {
|
|
||||||
return oemCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public PortDescriptor[] getPorts() {
|
|
||||||
return ports;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the reportCode
|
|
||||||
*/
|
|
||||||
public NodeReportCode getReportCode() {
|
|
||||||
return reportCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getShortName() {
|
|
||||||
return shortName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getSubSwitch() {
|
|
||||||
return subSwitch;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean parse(byte[] raw) {
|
|
||||||
setData(raw);
|
|
||||||
// System.out.println(data.toHex(256));
|
|
||||||
setIPAddress(data.getByteChunk(null, 10, 4));
|
|
||||||
subSwitch = data.getInt16(18);
|
|
||||||
oemCode = data.getInt16(20);
|
|
||||||
nodeStatus = data.getInt8(23);
|
|
||||||
shortName = new String(data.getByteChunk(null, 26, 17));
|
|
||||||
longName = new String(data.getByteChunk(null, 44, 64));
|
|
||||||
reportCode =
|
|
||||||
NodeReportCode.getForID(new String(data.getByteChunk(null, 108,
|
|
||||||
5)));
|
|
||||||
numPorts = data.getInt16(172);
|
|
||||||
ports = new PortDescriptor[numPorts];
|
|
||||||
for (int i = 0; i < numPorts; i++) {
|
|
||||||
ports[i] = new PortDescriptor(data.getInt8(174 + i));
|
|
||||||
}
|
|
||||||
dmxIns = data.getByteChunk(null, 186, 4);
|
|
||||||
dmxOuts = data.getByteChunk(null, 190, 4);
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
dmxIns[i] &= 0x0f;
|
|
||||||
dmxOuts[i] &= 0x0f;
|
|
||||||
}
|
|
||||||
int styleID = data.getInt8(200);
|
|
||||||
for (NodeStyle s : NodeStyle.values()) {
|
|
||||||
if (styleID == s.getStyleID()) {
|
|
||||||
nodeStyle = s;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param dmxIns
|
|
||||||
* the dmxIns to set
|
|
||||||
*/
|
|
||||||
public void setDmxIns(byte[] dmxIns) {
|
|
||||||
this.dmxIns = dmxIns;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param dmxOuts
|
|
||||||
* the dmxOuts to set
|
|
||||||
*/
|
|
||||||
public void setDmxOuts(byte[] dmxOuts) {
|
|
||||||
this.dmxOuts = dmxOuts;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setIPAddress(byte[] address) {
|
|
||||||
try {
|
|
||||||
ip = InetAddress.getByAddress(address);
|
|
||||||
logger.fine("setting ip address: " + ip);
|
|
||||||
} catch (UnknownHostException e) {
|
|
||||||
logger.log(Level.WARNING, e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param reportCode
|
|
||||||
* the reportCode to set
|
|
||||||
*/
|
|
||||||
public void setReportCode(NodeReportCode reportCode) {
|
|
||||||
this.reportCode = reportCode;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
package de.ctdo.bunti.artnet;
|
||||||
|
|
||||||
|
import de.ctdo.bunti.artnet.packets.ArtNetPacket;
|
||||||
|
|
||||||
|
|
||||||
|
public interface ArtNetSocket {
|
||||||
|
|
||||||
|
public boolean unicastPacket(ArtNetPacket pack, String address);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
package de.ctdo.bunti.artnet;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.DatagramPacket;
|
||||||
|
import java.net.DatagramSocket;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.SocketException;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import de.ctdo.bunti.artnet.packets.ArtNetPacket;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class ArtNetSocketImpl implements ArtNetSocket {
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(getClass());
|
||||||
|
public static final int DEFAULT_PORT = 0x1936;
|
||||||
|
protected DatagramSocket socket;
|
||||||
|
|
||||||
|
public ArtNetSocketImpl() {
|
||||||
|
try {
|
||||||
|
socket = new DatagramSocket();
|
||||||
|
|
||||||
|
|
||||||
|
} catch (SocketException e) {
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
logger.debug(e.getMessage(), e.getStackTrace());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean unicastPacket(ArtNetPacket pack, String address) {
|
||||||
|
InetAddress targetAdress;
|
||||||
|
try {
|
||||||
|
targetAdress = InetAddress.getByName(address);
|
||||||
|
|
||||||
|
DatagramPacket packet = new DatagramPacket(pack.getData(), pack.getLength(), targetAdress, DEFAULT_PORT);
|
||||||
|
|
||||||
|
socket.send(packet);
|
||||||
|
//socket.send(packet, targetAdress);
|
||||||
|
|
||||||
|
} catch (UnknownHostException e) {
|
||||||
|
logger.error(e.getMessage(), e);
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.error(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -17,16 +17,17 @@
|
||||||
* along with artnet4j. If not, see <http://www.gnu.org/licenses/>.
|
* along with artnet4j. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package artnet4j.packets;
|
package de.ctdo.bunti.artnet;
|
||||||
|
|
||||||
public class ByteUtils {
|
public class ByteUtils {
|
||||||
|
protected final byte[] data;
|
||||||
|
public final int length;
|
||||||
|
|
||||||
|
public ByteUtils(byte[] data) {
|
||||||
|
this.data = data;
|
||||||
|
this.length = data.length;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts the byte into an unsigned int.
|
|
||||||
*
|
|
||||||
* @param b
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static final int byteToUint(byte b) {
|
public static final int byteToUint(byte b) {
|
||||||
return (b < 0 ? 256 + b : b);
|
return (b < 0 ? 256 + b : b);
|
||||||
}
|
}
|
||||||
|
@ -43,15 +44,6 @@ public class ByteUtils {
|
||||||
return stuff;
|
return stuff;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final byte[] data;
|
|
||||||
|
|
||||||
public final int length;
|
|
||||||
|
|
||||||
public ByteUtils(byte[] data) {
|
|
||||||
this.data = data;
|
|
||||||
this.length = data.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean compareBytes(byte[] other, int offset, int length) {
|
public boolean compareBytes(byte[] other, int offset, int length) {
|
||||||
boolean isEqual = (offset + length) < data.length;
|
boolean isEqual = (offset + length) < data.length;
|
||||||
for (int i = 0; i < length && isEqual; i++) {
|
for (int i = 0; i < length && isEqual; i++) {
|
|
@ -0,0 +1,9 @@
|
||||||
|
package de.ctdo.bunti.artnet;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public interface SimpleArtNetSender {
|
||||||
|
|
||||||
|
public void sendDMXData(Map<Integer,Integer> dmxdata, String adr);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
package de.ctdo.bunti.artnet;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
|
||||||
|
import de.ctdo.bunti.artnet.packets.ArtDmxPacket;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class SimpleArtNetSenderImpl implements SimpleArtNetSender {
|
||||||
|
|
||||||
|
private ArtNetSocket socket;
|
||||||
|
private int sequence = 0;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public void setSocket(ArtNetSocket socket) {
|
||||||
|
this.socket = socket;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendDMXData(Map<Integer,Integer> dmxdata, String adr) {
|
||||||
|
|
||||||
|
ArtDmxPacket packet = new ArtDmxPacket();
|
||||||
|
int size = dmxdata.size();
|
||||||
|
|
||||||
|
byte[] arr = new byte[size];
|
||||||
|
|
||||||
|
for (int i = 0; i < dmxdata.size(); i++) {
|
||||||
|
arr[i] = (byte)(dmxdata.get(i) & 0xff);
|
||||||
|
}
|
||||||
|
|
||||||
|
packet.setSequenceID(sequence++);
|
||||||
|
packet.setDMX(arr, arr.length);
|
||||||
|
packet.setUniverse(0, 0);
|
||||||
|
|
||||||
|
socket.unicastPacket(packet, adr);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,7 +17,8 @@
|
||||||
* along with artnet4j. If not, see <http://www.gnu.org/licenses/>.
|
* along with artnet4j. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package artnet4j.packets;
|
package de.ctdo.bunti.artnet.packets;
|
||||||
|
|
||||||
|
|
||||||
public class ArtDmxPacket extends ArtNetPacket {
|
public class ArtDmxPacket extends ArtNetPacket {
|
||||||
|
|
||||||
|
@ -79,7 +80,6 @@ public class ArtDmxPacket extends ArtNetPacket {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDMX(byte[] dmxData, int numChannels) {
|
public void setDMX(byte[] dmxData, int numChannels) {
|
||||||
logger.finer("setting DMX data for: " + numChannels + " channels");
|
|
||||||
this.numChannels = numChannels;
|
this.numChannels = numChannels;
|
||||||
data.setByteChunk(dmxData, 18, numChannels);
|
data.setByteChunk(dmxData, 18, numChannels);
|
||||||
data.setInt16((1 == numChannels % 2 ? numChannels + 1 : numChannels),
|
data.setInt16((1 == numChannels % 2 ? numChannels + 1 : numChannels),
|
||||||
|
@ -111,9 +111,6 @@ public class ArtDmxPacket extends ArtNetPacket {
|
||||||
this.subnetID = subnetID & 0x0f;
|
this.subnetID = subnetID & 0x0f;
|
||||||
this.universeID = universeID & 0x0f;
|
this.universeID = universeID & 0x0f;
|
||||||
data.setInt16LE(subnetID << 4 | universeID, 14);
|
data.setInt16LE(subnetID << 4 | universeID, 14);
|
||||||
logger.finer("universe ID set to: subnet: "
|
|
||||||
+ ByteUtils.hex(subnetID, 2) + "/"
|
|
||||||
+ ByteUtils.hex(universeID, 2));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
|
@ -1,35 +1,11 @@
|
||||||
/*
|
package de.ctdo.bunti.artnet.packets;
|
||||||
* This file is part of artnet4j.
|
|
||||||
*
|
|
||||||
* Copyright 2009 Karsten Schmidt (PostSpectacular Ltd.)
|
|
||||||
*
|
|
||||||
* artnet4j is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* artnet4j is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with artnet4j. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package artnet4j.packets;
|
import de.ctdo.bunti.artnet.ByteUtils;
|
||||||
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
public abstract class ArtNetPacket {
|
public abstract class ArtNetPacket {
|
||||||
|
|
||||||
public static final byte[] HEADER = "Art-Net\0".getBytes();
|
public static final byte[] HEADER = "Art-Net\0".getBytes();
|
||||||
|
|
||||||
public static final int PROTOCOL_VERSION = 14;
|
public static final int PROTOCOL_VERSION = 14;
|
||||||
|
|
||||||
public static final Logger logger =
|
|
||||||
Logger.getLogger(ArtNetPacket.class.getClass().getName());
|
|
||||||
|
|
||||||
protected ByteUtils data;
|
protected ByteUtils data;
|
||||||
protected final PacketType type;
|
protected final PacketType type;
|
||||||
|
|
||||||
|
@ -37,27 +13,14 @@ public abstract class ArtNetPacket {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the data
|
|
||||||
*/
|
|
||||||
public byte[] getData() {
|
public byte[] getData() {
|
||||||
return data.getBytes();
|
return data.getBytes();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the actually used length of the data buffer.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public int getLength() {
|
public int getLength() {
|
||||||
return data.length;
|
return data.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the type of this packet.
|
|
||||||
*
|
|
||||||
* @return the type
|
|
||||||
*/
|
|
||||||
public PacketType getType() {
|
public PacketType getType() {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
@ -90,10 +53,6 @@ public abstract class ArtNetPacket {
|
||||||
setData(raw);
|
setData(raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the header bytes of the packet consisting of {@link #HEADER} and the
|
|
||||||
* type's OpCode.
|
|
||||||
*/
|
|
||||||
protected void setHeader() {
|
protected void setHeader() {
|
||||||
data.setByteChunk(HEADER, 0, 8);
|
data.setByteChunk(HEADER, 0, 8);
|
||||||
data.setInt16LE(type.getOpCode(), 8);
|
data.setInt16LE(type.getOpCode(), 8);
|
||||||
|
@ -107,4 +66,5 @@ public abstract class ArtNetPacket {
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return data.toHex(getLength());
|
return data.toHex(getLength());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -17,21 +17,33 @@
|
||||||
* along with artnet4j. If not, see <http://www.gnu.org/licenses/>.
|
* along with artnet4j. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package artnet4j.packets;
|
package de.ctdo.bunti.artnet.packets;
|
||||||
|
|
||||||
public enum PacketType {
|
public enum PacketType {
|
||||||
|
|
||||||
ART_POLL(0x2000, ArtPollPacket.class), ART_POLL_REPLY(0x2100,
|
ART_POLL(0x2000, null),
|
||||||
ArtPollReplyPacket.class), ART_OUTPUT(0x5000, null), ART_ADDRESS(
|
ART_POLL_REPLY(0x2100, null),
|
||||||
0x6000, null), ART_INPUT(0x7000, null), ART_TOD_REQUEST(0x8000,
|
ART_OUTPUT(0x5000, null),
|
||||||
null), ART_TOD_DATA(0x8100, null), ART_TOD_CONTROL(0x8200, null),
|
ART_ADDRESS(0x6000, null),
|
||||||
ART_RDM(0x8300, null), ART_RDMSUB(0x8400, null), ART_MEDIA(0x9000, null),
|
ART_INPUT(0x7000, null),
|
||||||
ART_MEDIA_PATCH(0x9100, null), ART_MEDIA_CONTROL(0x9200, null),
|
ART_TOD_REQUEST(0x8000, null),
|
||||||
ART_MEDIA_CONTROL_REPLY(0x9300, null), ART_VIDEO_SETUP(0xa010, null),
|
ART_TOD_DATA(0x8100, null),
|
||||||
ART_VIDEO_PALETTE(0xa020, null), ART_VIDEO_DATA(0xa040, null),
|
ART_TOD_CONTROL(0x8200, null),
|
||||||
ART_MAC_MASTER(0xf000, null), ART_MAC_SLAVE(0xf100, null),
|
ART_RDM(0x8300, null),
|
||||||
ART_FIRMWARE_MASTER(0xf200, null), ART_FIRMWARE_REPLY(0xf300, null),
|
ART_RDMSUB(0x8400, null),
|
||||||
ART_IP_PROG(0xf800, null), ART_IP_PROG_REPLY(0xf900, null);
|
ART_MEDIA(0x9000, null),
|
||||||
|
ART_MEDIA_PATCH(0x9100, null),
|
||||||
|
ART_MEDIA_CONTROL(0x9200, null),
|
||||||
|
ART_MEDIA_CONTROL_REPLY(0x9300, null),
|
||||||
|
ART_VIDEO_SETUP(0xa010, null),
|
||||||
|
ART_VIDEO_PALETTE(0xa020, null),
|
||||||
|
ART_VIDEO_DATA(0xa040, null),
|
||||||
|
ART_MAC_MASTER(0xf000, null),
|
||||||
|
ART_MAC_SLAVE(0xf100, null),
|
||||||
|
ART_FIRMWARE_MASTER(0xf200, null),
|
||||||
|
ART_FIRMWARE_REPLY(0xf300, null),
|
||||||
|
ART_IP_PROG(0xf800, null),
|
||||||
|
ART_IP_PROG_REPLY(0xf900, null);
|
||||||
|
|
||||||
private final int opCode;
|
private final int opCode;
|
||||||
private final Class<? extends ArtNetPacket> packetClass;
|
private final Class<? extends ArtNetPacket> packetClass;
|
|
@ -1,11 +1,8 @@
|
||||||
package de.ctdo.bunti.devices;
|
package de.ctdo.bunti.devices;
|
||||||
|
|
||||||
|
|
||||||
import org.springframework.context.ApplicationListener;
|
|
||||||
|
|
||||||
import de.ctdo.bunti.DeviceChangedEvent;
|
public interface DeviceMixer {
|
||||||
|
|
||||||
public interface DeviceMixer extends ApplicationListener<DeviceChangedEvent> {
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package de.ctdo.bunti.devices;
|
package de.ctdo.bunti.devices;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.springframework.context.ApplicationListener;
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import de.ctdo.bunti.DeviceChangedEvent;
|
import de.ctdo.bunti.DeviceChangedEvent;
|
||||||
|
@ -9,8 +8,7 @@ import de.ctdo.bunti.model.BuntiSwitchingDevice;
|
||||||
|
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
public class DeviceMixerImpl implements DeviceMixer {
|
public class DeviceMixerImpl implements DeviceMixer, ApplicationListener<DeviceChangedEvent> {
|
||||||
private Logger logger = LoggerFactory.getLogger(getClass());
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onApplicationEvent(DeviceChangedEvent arg0) {
|
public void onApplicationEvent(DeviceChangedEvent arg0) {
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
/DMXMixer.java
|
|
@ -1,10 +1,10 @@
|
||||||
package de.ctdo.bunti.dmx;
|
package de.ctdo.bunti.dmx;
|
||||||
|
|
||||||
public class DMXChannel {
|
public class DMXChannel {
|
||||||
int offset;
|
private int offset;
|
||||||
String name;
|
private String name;
|
||||||
int value;
|
private int value;
|
||||||
long lastChangedTimestamp = 0;
|
private long lastChangedTimestamp = 0;
|
||||||
|
|
||||||
public DMXChannel(int offset, String name) {
|
public DMXChannel(int offset, String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
|
|
@ -6,8 +6,10 @@ import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DMXChannel container
|
* DMXChannel container
|
||||||
*/
|
* @author jCoder
|
||||||
|
*
|
||||||
|
*/
|
||||||
public class DMXChannels {
|
public class DMXChannels {
|
||||||
|
|
||||||
protected Map<Integer,DMXChannel> channelByNumber = new HashMap<Integer, DMXChannel>();
|
protected Map<Integer,DMXChannel> channelByNumber = new HashMap<Integer, DMXChannel>();
|
||||||
|
@ -33,14 +35,14 @@ public class DMXChannels {
|
||||||
return this.channelByName.get(name);
|
return this.channelByName.get(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Returns a channel by offset
|
* Returns a channel by offset
|
||||||
// * @param number number
|
* @param number number
|
||||||
// * @return channel or null if not found
|
* @return channel or null if not found
|
||||||
// */
|
*/
|
||||||
// public DMXChannel getChannelByNumber(int number) {
|
public DMXChannel getChannelByNumber(int number) {
|
||||||
// return this.channelByNumber.get(number);
|
return this.channelByNumber.get(number);
|
||||||
// }
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a channel
|
* Adds a channel
|
||||||
|
@ -53,50 +55,51 @@ public class DMXChannels {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// description cannot be null
|
// description cannot be null
|
||||||
if (channel.name == null) {
|
if (channel.getName() == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// entry must not exist by offset
|
// entry must not exist by offset
|
||||||
if (this.channelByNumber.containsKey(channel.offset) == true) {
|
if (this.channelByNumber.containsKey(channel.getOffset()) == true) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// entry must not exist by name
|
// entry must not exist by name
|
||||||
if (this.channelByName.containsKey(channel.name) == true) {
|
if (this.channelByName.containsKey(channel.getName()) == true) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
this.channelByNumber.put(channel.offset, channel);
|
this.channelByNumber.put(channel.getOffset(), channel);
|
||||||
this.channelByName.put(channel.name, channel);
|
this.channelByName.put(channel.getName(), channel);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Removes a channel by offset
|
* Removes a channel by offset
|
||||||
// * @param offset offset
|
* @param offset offset
|
||||||
// * @return removed channel or null if it does not exist
|
* @return removed channel or null if it does not exist
|
||||||
// */
|
*/
|
||||||
// public DMXChannel removeChannel(int offset) {
|
public DMXChannel removeChannel(int offset) {
|
||||||
// DMXChannel tmpChannel = this.channelByNumber.remove(offset);
|
DMXChannel tmpChannel = this.channelByNumber.remove(offset);
|
||||||
// if (tmpChannel != null) {
|
if (tmpChannel != null) {
|
||||||
// this.channelByName.remove(tmpChannel.name);
|
this.channelByName.remove(tmpChannel.getName());
|
||||||
// }
|
}
|
||||||
// return tmpChannel;
|
return tmpChannel;
|
||||||
// }
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a channel by name
|
||||||
|
* @param name channel name
|
||||||
|
* @return removed channel or null if it does not exist
|
||||||
|
*/
|
||||||
|
public DMXChannel removeChannel(String name) {
|
||||||
|
if (name == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
DMXChannel tmpChannel = this.channelByName.remove(name);
|
||||||
|
if (tmpChannel != null) {
|
||||||
|
this.channelByNumber.remove(tmpChannel.getOffset());
|
||||||
|
}
|
||||||
|
return tmpChannel;
|
||||||
|
}
|
||||||
|
|
||||||
// /**
|
|
||||||
// * Removes a channel by name
|
|
||||||
// * @param name channel name
|
|
||||||
// * @return removed channel or null if it does not exist
|
|
||||||
// */
|
|
||||||
// public DMXChannel removeChannel(String name) {
|
|
||||||
// if (name == null) {
|
|
||||||
// return null;
|
|
||||||
// }
|
|
||||||
// DMXChannel tmpChannel = this.channelByName.remove(name);
|
|
||||||
// if (tmpChannel != null) {
|
|
||||||
// this.channelByOffset.remove(tmpChannel.offset);
|
|
||||||
// }
|
|
||||||
// return tmpChannel;
|
|
||||||
// }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an (unmodifiable) collection of all channels
|
* Returns an (unmodifiable) collection of all channels
|
||||||
|
|
|
@ -1,112 +1,84 @@
|
||||||
package de.ctdo.bunti.dmx;
|
package de.ctdo.bunti.dmx;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.ApplicationListener;
|
||||||
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import de.ctdo.bunti.DeviceChangedEvent;
|
import de.ctdo.bunti.DeviceChangedEvent;
|
||||||
import de.ctdo.bunti.dao.BuntiDevicesDAO;
|
import de.ctdo.bunti.artnet.SimpleArtNetSender;
|
||||||
import de.ctdo.bunti.model.*;
|
import de.ctdo.bunti.model.*;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
public class DMXMixerImpl implements DMXMixer {
|
public class DMXMixerImpl implements DMXMixer, ApplicationListener<DeviceChangedEvent> {
|
||||||
private Logger logger = LoggerFactory.getLogger(getClass());
|
private final Logger logger = LoggerFactory.getLogger(getClass());
|
||||||
private final int TICKS_BETWEEN_DMX_SEND = 20;
|
private final String ARTNET_DEVICE_ADDRESS = "192.168.0.90";
|
||||||
// private final String ARTNET_DEVICE_ADDRESS = "192.168.0.90";
|
|
||||||
|
|
||||||
private int[] dmx512databuffer = new int[DMX.DMX_CHANNELS_MAX+1];
|
private final Map<Integer,Integer> dmxMap = Collections.synchronizedMap(new HashMap<Integer,Integer>());
|
||||||
|
private SimpleArtNetSender artNetSender;
|
||||||
// private int sequenceID = 0;
|
private boolean hasDataChanged = true;
|
||||||
private long ticksLastBufferFlush = 0;
|
|
||||||
private BuntiDevicesDAO devicesDAO;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public void setDevicesDAO(BuntiDevicesDAO devicesDAO) {
|
public void setArtNetSender(SimpleArtNetSender artNetSender) {
|
||||||
this.devicesDAO = devicesDAO;
|
this.artNetSender = artNetSender;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void initDMXData() {
|
||||||
private void sendOutDMXBuffer() {
|
for (int i = 0; i <= DMX.DMX_CHANNELS_MAX; i++) {
|
||||||
|
dmxMap.put(i, 0);
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
sb.append("DMX Data: ");
|
|
||||||
|
|
||||||
byte[] arr = new byte[dmx512databuffer.length];
|
|
||||||
for (int i = 0; i < dmx512databuffer.length; i++) {
|
|
||||||
arr[i] = (byte)dmx512databuffer[i];
|
|
||||||
sb.append(i);
|
|
||||||
sb.append("=");
|
|
||||||
sb.append(dmx512databuffer[i]);
|
|
||||||
sb.append(", ");
|
|
||||||
}
|
|
||||||
|
|
||||||
// sequenceID++;
|
|
||||||
|
|
||||||
logger.debug(sb.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void sendOutDMXBufferIfNeeded() {
|
|
||||||
if(ticksLastBufferFlush + TICKS_BETWEEN_DMX_SEND < System.currentTimeMillis()) {
|
|
||||||
|
|
||||||
// mergeDevicesIntoBuffer();
|
|
||||||
sendOutDMXBuffer();
|
|
||||||
ticksLastBufferFlush = System.currentTimeMillis();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateDevice(BuntiDevice device, Map<String, Object> options) {
|
@Scheduled(fixedDelay=100) //TODO aendern auf 10ms
|
||||||
|
public void sendOutDMXBuffer() {
|
||||||
|
if( dmxMap.size() == 0) initDMXData();
|
||||||
|
|
||||||
|
if( hasDataChanged ) {
|
||||||
|
artNetSender.sendDMXData(dmxMap, ARTNET_DEVICE_ADDRESS);
|
||||||
|
hasDataChanged = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// logger.debug(sb.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateDevice(BuntiDevice device, Map<String, Object> options) {
|
||||||
BuntiDMXDevice dmxDev = (BuntiDMXDevice)device;
|
BuntiDMXDevice dmxDev = (BuntiDMXDevice)device;
|
||||||
boolean retval = dmxDev.setValuesFromOptions(options);
|
|
||||||
|
|
||||||
if( retval ) {
|
if( dmxDev.setValuesFromOptions(options) ) {
|
||||||
dmxDev.mergeDMXData(dmx512databuffer);
|
|
||||||
|
|
||||||
sendOutDMXBufferIfNeeded();
|
dmxMap.putAll(dmxDev.getChannelData());
|
||||||
|
|
||||||
|
|
||||||
|
logger.info("setValuesFromOptions on " + device);
|
||||||
} else {
|
} else {
|
||||||
logger.error("setValuesFromOptions failed");
|
logger.info("setValuesFromOptions on " + device + " failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// private void mergeDevicesIntoBuffer() {
|
@Override
|
||||||
//
|
public void setDMX512Channel(int channel, int value) {
|
||||||
// for (BuntiDMXDevice buntiDMXDevice : devicesDAO.getAllDMXDevices()) {
|
if(!DMX.checkChannelBoundaries(channel)) return;
|
||||||
// long lastchanged = buntiDMXDevice.getLastChanged();
|
value = DMX.sanitizeDMXValue(value);
|
||||||
// long lastSend = buntiDMXDevice.getLastSendOut();
|
|
||||||
//
|
|
||||||
// if (lastchanged >= lastSend) {
|
|
||||||
// buntiDMXDevice.mergeDMXData(dmx512databuffer);
|
|
||||||
// logger.debug("merged " + buntiDMXDevice + " into dmx buffer");
|
|
||||||
// buntiDMXDevice.setSendOutNow();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public void setDMX512Channel(int channel, int value) {
|
dmxMap.put(channel, value);
|
||||||
// if(!DMX.checkChannelBoundaries(channel)) return;
|
hasDataChanged = true;
|
||||||
// value = DMX.sanitizeDMXValue(value);
|
}
|
||||||
//
|
|
||||||
// dmx512databuffer[channel] = value;
|
|
||||||
//
|
|
||||||
// sendOutDMXBufferIfNeeded();
|
|
||||||
// }
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onApplicationEvent(DeviceChangedEvent arg0) {
|
public void onApplicationEvent(DeviceChangedEvent arg0) {
|
||||||
|
|
||||||
if( arg0.getDevice() instanceof BuntiDMXDevice) {
|
if( arg0.getDevice() instanceof BuntiDMXDevice) {
|
||||||
|
|
||||||
updateDevice(arg0.getDevice(), arg0.getOptions());
|
updateDevice(arg0.getDevice(), arg0.getOptions());
|
||||||
|
|
||||||
|
hasDataChanged = true;
|
||||||
|
// TODO: hier kann man z.B. auch noch direkt einmal die DMX Daten zu verschicken veranlassen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package de.ctdo.bunti.model;
|
package de.ctdo.bunti.model;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
|
@ -58,28 +59,66 @@ public abstract class BuntiDMXDevice extends BuntiDevice {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* Merge the DMX values from this device into a global DMX512 Data Array.
|
// * Merge the DMX values from this device into a global DMX512 Data Array.
|
||||||
* @param dmxData DMX512 Data array to merge the local values into.
|
// * @param dmxData DMX512 Data array to merge the local values into.
|
||||||
* @return True on success, false otherwise.
|
// * @return True on success, false otherwise.
|
||||||
*/
|
// */
|
||||||
public boolean mergeDMXData(int[] dmxData) {
|
// public boolean mergeDMXData(int[] dmxData) {
|
||||||
|
//
|
||||||
|
// if(dmxData == null || dmxData.length == 0) {
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// for (DMXChannel channel : dmxChannels.getAllChannels()) {
|
||||||
|
// int index = channel.getOffset() + (startAddress - DMX.DMX_STARTADDRESS_OFFSET);
|
||||||
|
//
|
||||||
|
// if(index >= 0 && index < dmxData.length){
|
||||||
|
// dmxData[index] = channel.getValue();
|
||||||
|
// } else {
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Merge the DMX values from this device into a global DMX512 Data Array.
|
||||||
|
// * @param dmxData DMX512 Data to merge the local values into.
|
||||||
|
// * @return True on success, false otherwise.
|
||||||
|
// */
|
||||||
|
// public boolean mergeDMXData(Map<Integer,Integer> dmxData) {
|
||||||
|
//
|
||||||
|
// if(dmxData == null || dmxData.size() == 0) {
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// for (DMXChannel channel : dmxChannels.getAllChannels()) {
|
||||||
|
// int index = channel.getOffset() + (startAddress - DMX.DMX_STARTADDRESS_OFFSET);
|
||||||
|
//
|
||||||
|
// if(index >= DMX.DMX_CHANNELS_MIN && index <= DMX.DMX_CHANNELS_MAX){
|
||||||
|
// dmxData.put(index, channel.getValue());
|
||||||
|
// } else {
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
|
||||||
if(dmxData == null || dmxData.length == 0) {
|
public Map<Integer,Integer> getChannelData() {
|
||||||
return false;
|
Map<Integer,Integer> map = new HashMap<Integer, Integer>();
|
||||||
}
|
|
||||||
|
|
||||||
for (DMXChannel channel : dmxChannels.getAllChannels()) {
|
for (DMXChannel channel : dmxChannels.getAllChannels()) {
|
||||||
int index = channel.getOffset() + (startAddress - DMX.DMX_STARTADDRESS_OFFSET);
|
int index = channel.getOffset() + (startAddress - DMX.DMX_STARTADDRESS_OFFSET);
|
||||||
|
|
||||||
if(index >= 0 && index < dmxData.length){
|
if(index >= DMX.DMX_CHANNELS_MIN && index <= DMX.DMX_CHANNELS_MAX){
|
||||||
dmxData[index] = channel.getValue();
|
map.put(index, channel.getValue());
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context"
|
xmlns:context="http://www.springframework.org/schema/context"
|
||||||
|
xmlns:task="http://www.springframework.org/schema/task"
|
||||||
xsi:schemaLocation="
|
xsi:schemaLocation="
|
||||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
||||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
|
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
|
||||||
|
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd">
|
||||||
|
|
||||||
<context:component-scan base-package="de.ctdo" />
|
<context:component-scan base-package="de.ctdo" />
|
||||||
|
|
||||||
|
@ -12,4 +14,9 @@
|
||||||
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
|
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
|
||||||
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
|
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
|
||||||
|
|
||||||
|
<task:annotation-driven scheduler="myScheduler"/>
|
||||||
|
<!--<task:annotation-driven executor="myExecutor" scheduler="myScheduler"/>
|
||||||
|
<task:executor id="myExecutor" pool-size="3-10" queue-capacity="50" />-->
|
||||||
|
<task:scheduler id="myScheduler" pool-size="3"/>
|
||||||
|
|
||||||
</beans>
|
</beans>
|
Loading…
Reference in New Issue