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/>.
|
||||
*/
|
||||
|
||||
package artnet4j.packets;
|
||||
package de.ctdo.bunti.artnet;
|
||||
|
||||
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) {
|
||||
return (b < 0 ? 256 + b : b);
|
||||
}
|
||||
|
@ -43,15 +44,6 @@ public class ByteUtils {
|
|||
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) {
|
||||
boolean isEqual = (offset + length) < data.length;
|
||||
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/>.
|
||||
*/
|
||||
|
||||
package artnet4j.packets;
|
||||
package de.ctdo.bunti.artnet.packets;
|
||||
|
||||
|
||||
public class ArtDmxPacket extends ArtNetPacket {
|
||||
|
||||
|
@ -79,7 +80,6 @@ public class ArtDmxPacket extends ArtNetPacket {
|
|||
}
|
||||
|
||||
public void setDMX(byte[] dmxData, int numChannels) {
|
||||
logger.finer("setting DMX data for: " + numChannels + " channels");
|
||||
this.numChannels = numChannels;
|
||||
data.setByteChunk(dmxData, 18, numChannels);
|
||||
data.setInt16((1 == numChannels % 2 ? numChannels + 1 : numChannels),
|
||||
|
@ -111,9 +111,6 @@ public class ArtDmxPacket extends ArtNetPacket {
|
|||
this.subnetID = subnetID & 0x0f;
|
||||
this.universeID = universeID & 0x0f;
|
||||
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 @@
|
|||
/*
|
||||
* 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 de.ctdo.bunti.artnet.packets;
|
||||
|
||||
package artnet4j.packets;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
import de.ctdo.bunti.artnet.ByteUtils;
|
||||
|
||||
public abstract class ArtNetPacket {
|
||||
|
||||
public static final byte[] HEADER = "Art-Net\0".getBytes();
|
||||
|
||||
public static final int PROTOCOL_VERSION = 14;
|
||||
|
||||
public static final Logger logger =
|
||||
Logger.getLogger(ArtNetPacket.class.getClass().getName());
|
||||
|
||||
protected ByteUtils data;
|
||||
protected final PacketType type;
|
||||
|
||||
|
@ -37,27 +13,14 @@ public abstract class ArtNetPacket {
|
|||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the data
|
||||
*/
|
||||
public byte[] getData() {
|
||||
return data.getBytes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the actually used length of the data buffer.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int getLength() {
|
||||
return data.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type of this packet.
|
||||
*
|
||||
* @return the type
|
||||
*/
|
||||
public PacketType getType() {
|
||||
return type;
|
||||
}
|
||||
|
@ -90,10 +53,6 @@ public abstract class ArtNetPacket {
|
|||
setData(raw);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the header bytes of the packet consisting of {@link #HEADER} and the
|
||||
* type's OpCode.
|
||||
*/
|
||||
protected void setHeader() {
|
||||
data.setByteChunk(HEADER, 0, 8);
|
||||
data.setInt16LE(type.getOpCode(), 8);
|
||||
|
@ -107,4 +66,5 @@ public abstract class ArtNetPacket {
|
|||
public String toString() {
|
||||
return data.toHex(getLength());
|
||||
}
|
||||
|
||||
}
|
|
@ -17,21 +17,33 @@
|
|||
* along with artnet4j. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package artnet4j.packets;
|
||||
package de.ctdo.bunti.artnet.packets;
|
||||
|
||||
public enum PacketType {
|
||||
|
||||
ART_POLL(0x2000, ArtPollPacket.class), ART_POLL_REPLY(0x2100,
|
||||
ArtPollReplyPacket.class), ART_OUTPUT(0x5000, null), ART_ADDRESS(
|
||||
0x6000, null), ART_INPUT(0x7000, null), ART_TOD_REQUEST(0x8000,
|
||||
null), ART_TOD_DATA(0x8100, null), ART_TOD_CONTROL(0x8200, null),
|
||||
ART_RDM(0x8300, null), ART_RDMSUB(0x8400, 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);
|
||||
ART_POLL(0x2000, null),
|
||||
ART_POLL_REPLY(0x2100, null),
|
||||
ART_OUTPUT(0x5000, null),
|
||||
ART_ADDRESS(0x6000, null),
|
||||
ART_INPUT(0x7000, null),
|
||||
ART_TOD_REQUEST(0x8000, null),
|
||||
ART_TOD_DATA(0x8100, null),
|
||||
ART_TOD_CONTROL(0x8200, null),
|
||||
ART_RDM(0x8300, null),
|
||||
ART_RDMSUB(0x8400, 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 Class<? extends ArtNetPacket> packetClass;
|
|
@ -1,11 +1,8 @@
|
|||
package de.ctdo.bunti.devices;
|
||||
|
||||
|
||||
import org.springframework.context.ApplicationListener;
|
||||
|
||||
import de.ctdo.bunti.DeviceChangedEvent;
|
||||
|
||||
public interface DeviceMixer extends ApplicationListener<DeviceChangedEvent> {
|
||||
public interface DeviceMixer {
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package de.ctdo.bunti.devices;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import de.ctdo.bunti.DeviceChangedEvent;
|
||||
|
@ -9,8 +8,7 @@ import de.ctdo.bunti.model.BuntiSwitchingDevice;
|
|||
|
||||
|
||||
@Component
|
||||
public class DeviceMixerImpl implements DeviceMixer {
|
||||
private Logger logger = LoggerFactory.getLogger(getClass());
|
||||
public class DeviceMixerImpl implements DeviceMixer, ApplicationListener<DeviceChangedEvent> {
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(DeviceChangedEvent arg0) {
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
/DMXMixer.java
|
|
@ -1,10 +1,10 @@
|
|||
package de.ctdo.bunti.dmx;
|
||||
|
||||
public class DMXChannel {
|
||||
int offset;
|
||||
String name;
|
||||
int value;
|
||||
long lastChangedTimestamp = 0;
|
||||
private int offset;
|
||||
private String name;
|
||||
private int value;
|
||||
private long lastChangedTimestamp = 0;
|
||||
|
||||
public DMXChannel(int offset, String name) {
|
||||
this.name = name;
|
||||
|
|
|
@ -7,6 +7,8 @@ import java.util.Map;
|
|||
|
||||
/**
|
||||
* DMXChannel container
|
||||
* @author jCoder
|
||||
*
|
||||
*/
|
||||
public class DMXChannels {
|
||||
|
||||
|
@ -33,14 +35,14 @@ public class DMXChannels {
|
|||
return this.channelByName.get(name);
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Returns a channel by offset
|
||||
// * @param number number
|
||||
// * @return channel or null if not found
|
||||
// */
|
||||
// public DMXChannel getChannelByNumber(int number) {
|
||||
// return this.channelByNumber.get(number);
|
||||
// }
|
||||
/**
|
||||
* Returns a channel by offset
|
||||
* @param number number
|
||||
* @return channel or null if not found
|
||||
*/
|
||||
public DMXChannel getChannelByNumber(int number) {
|
||||
return this.channelByNumber.get(number);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a channel
|
||||
|
@ -53,50 +55,51 @@ public class DMXChannels {
|
|||
return false;
|
||||
}
|
||||
// description cannot be null
|
||||
if (channel.name == null) {
|
||||
if (channel.getName() == null) {
|
||||
return false;
|
||||
}
|
||||
// entry must not exist by offset
|
||||
if (this.channelByNumber.containsKey(channel.offset) == true) {
|
||||
if (this.channelByNumber.containsKey(channel.getOffset()) == true) {
|
||||
return false;
|
||||
}
|
||||
// entry must not exist by name
|
||||
if (this.channelByName.containsKey(channel.name) == true) {
|
||||
if (this.channelByName.containsKey(channel.getName()) == true) {
|
||||
return false;
|
||||
}
|
||||
this.channelByNumber.put(channel.offset, channel);
|
||||
this.channelByName.put(channel.name, channel);
|
||||
this.channelByNumber.put(channel.getOffset(), channel);
|
||||
this.channelByName.put(channel.getName(), channel);
|
||||
return true;
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Removes a channel by offset
|
||||
// * @param offset offset
|
||||
// * @return removed channel or null if it does not exist
|
||||
// */
|
||||
// public DMXChannel removeChannel(int offset) {
|
||||
// DMXChannel tmpChannel = this.channelByNumber.remove(offset);
|
||||
// if (tmpChannel != null) {
|
||||
// this.channelByName.remove(tmpChannel.name);
|
||||
// }
|
||||
// return tmpChannel;
|
||||
// }
|
||||
/**
|
||||
* Removes a channel by offset
|
||||
* @param offset offset
|
||||
* @return removed channel or null if it does not exist
|
||||
*/
|
||||
public DMXChannel removeChannel(int offset) {
|
||||
DMXChannel tmpChannel = this.channelByNumber.remove(offset);
|
||||
if (tmpChannel != null) {
|
||||
this.channelByName.remove(tmpChannel.getName());
|
||||
}
|
||||
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
|
||||
|
|
|
@ -1,112 +1,84 @@
|
|||
package de.ctdo.bunti.dmx;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import de.ctdo.bunti.DeviceChangedEvent;
|
||||
import de.ctdo.bunti.dao.BuntiDevicesDAO;
|
||||
import de.ctdo.bunti.artnet.SimpleArtNetSender;
|
||||
import de.ctdo.bunti.model.*;
|
||||
|
||||
@Component
|
||||
public class DMXMixerImpl implements DMXMixer {
|
||||
private Logger logger = LoggerFactory.getLogger(getClass());
|
||||
private final int TICKS_BETWEEN_DMX_SEND = 20;
|
||||
// private final String ARTNET_DEVICE_ADDRESS = "192.168.0.90";
|
||||
public class DMXMixerImpl implements DMXMixer, ApplicationListener<DeviceChangedEvent> {
|
||||
private final Logger logger = LoggerFactory.getLogger(getClass());
|
||||
private final String ARTNET_DEVICE_ADDRESS = "192.168.0.90";
|
||||
|
||||
private int[] dmx512databuffer = new int[DMX.DMX_CHANNELS_MAX+1];
|
||||
|
||||
// private int sequenceID = 0;
|
||||
private long ticksLastBufferFlush = 0;
|
||||
private BuntiDevicesDAO devicesDAO;
|
||||
private final Map<Integer,Integer> dmxMap = Collections.synchronizedMap(new HashMap<Integer,Integer>());
|
||||
private SimpleArtNetSender artNetSender;
|
||||
private boolean hasDataChanged = true;
|
||||
|
||||
@Autowired
|
||||
public void setDevicesDAO(BuntiDevicesDAO devicesDAO) {
|
||||
this.devicesDAO = devicesDAO;
|
||||
public void setArtNetSender(SimpleArtNetSender artNetSender) {
|
||||
this.artNetSender = artNetSender;
|
||||
}
|
||||
|
||||
|
||||
private void sendOutDMXBuffer() {
|
||||
|
||||
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();
|
||||
public void initDMXData() {
|
||||
for (int i = 0; i <= DMX.DMX_CHANNELS_MAX; i++) {
|
||||
dmxMap.put(i, 0);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
boolean retval = dmxDev.setValuesFromOptions(options);
|
||||
|
||||
if( retval ) {
|
||||
dmxDev.mergeDMXData(dmx512databuffer);
|
||||
if( dmxDev.setValuesFromOptions(options) ) {
|
||||
|
||||
sendOutDMXBufferIfNeeded();
|
||||
dmxMap.putAll(dmxDev.getChannelData());
|
||||
|
||||
|
||||
logger.info("setValuesFromOptions on " + device);
|
||||
} else {
|
||||
logger.error("setValuesFromOptions failed");
|
||||
logger.info("setValuesFromOptions on " + device + " failed");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// private void mergeDevicesIntoBuffer() {
|
||||
//
|
||||
// for (BuntiDMXDevice buntiDMXDevice : devicesDAO.getAllDMXDevices()) {
|
||||
// long lastchanged = buntiDMXDevice.getLastChanged();
|
||||
// long lastSend = buntiDMXDevice.getLastSendOut();
|
||||
//
|
||||
// if (lastchanged >= lastSend) {
|
||||
// buntiDMXDevice.mergeDMXData(dmx512databuffer);
|
||||
// logger.debug("merged " + buntiDMXDevice + " into dmx buffer");
|
||||
// buntiDMXDevice.setSendOutNow();
|
||||
// }
|
||||
//
|
||||
// }
|
||||
// }
|
||||
@Override
|
||||
public void setDMX512Channel(int channel, int value) {
|
||||
if(!DMX.checkChannelBoundaries(channel)) return;
|
||||
value = DMX.sanitizeDMXValue(value);
|
||||
|
||||
// public void setDMX512Channel(int channel, int value) {
|
||||
// if(!DMX.checkChannelBoundaries(channel)) return;
|
||||
// value = DMX.sanitizeDMXValue(value);
|
||||
//
|
||||
// dmx512databuffer[channel] = value;
|
||||
//
|
||||
// sendOutDMXBufferIfNeeded();
|
||||
// }
|
||||
dmxMap.put(channel, value);
|
||||
hasDataChanged = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(DeviceChangedEvent arg0) {
|
||||
|
||||
if( arg0.getDevice() instanceof BuntiDMXDevice) {
|
||||
|
||||
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;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
|
@ -58,28 +59,66 @@ public abstract class BuntiDMXDevice extends BuntiDevice {
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge the DMX values from this device into a global DMX512 Data Array.
|
||||
* @param dmxData DMX512 Data array to merge the local values into.
|
||||
* @return True on success, false otherwise.
|
||||
*/
|
||||
public boolean mergeDMXData(int[] dmxData) {
|
||||
// /**
|
||||
// * Merge the DMX values from this device into a global DMX512 Data Array.
|
||||
// * @param dmxData DMX512 Data array to merge the local values into.
|
||||
// * @return True on success, false otherwise.
|
||||
// */
|
||||
// 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) {
|
||||
return false;
|
||||
}
|
||||
public Map<Integer,Integer> getChannelData() {
|
||||
Map<Integer,Integer> map = new HashMap<Integer, Integer>();
|
||||
|
||||
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;
|
||||
if(index >= DMX.DMX_CHANNELS_MIN && index <= DMX.DMX_CHANNELS_MAX){
|
||||
map.put(index, channel.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<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:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:task="http://www.springframework.org/schema/task"
|
||||
xsi:schemaLocation="
|
||||
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" />
|
||||
|
||||
|
@ -12,4 +14,9 @@
|
|||
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
|
||||
<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>
|
Loading…
Reference in New Issue