All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.neuronrobotics.sdk.common.device.server.BowlerAbstractServer Maven / Gradle / Ivy

package com.neuronrobotics.sdk.common.device.server;

import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;

import javax.management.RuntimeErrorException;

import com.neuronrobotics.sdk.common.BowlerAbstractCommand;
import com.neuronrobotics.sdk.common.BowlerAbstractConnection;
import com.neuronrobotics.sdk.common.BowlerAbstractDevice;
import com.neuronrobotics.sdk.common.BowlerDataType;
import com.neuronrobotics.sdk.common.BowlerDatagram;
import com.neuronrobotics.sdk.common.BowlerDatagramFactory;
import com.neuronrobotics.sdk.common.BowlerMethod;
import com.neuronrobotics.sdk.common.DeviceConnectionException;
import com.neuronrobotics.sdk.common.DeviceManager;
import com.neuronrobotics.sdk.common.IConnectionEventListener;
import com.neuronrobotics.sdk.common.ISynchronousDatagramListener;
import com.neuronrobotics.sdk.common.Log;
import com.neuronrobotics.sdk.common.MACAddress;
import com.neuronrobotics.sdk.common.NamespaceEncapsulation;
import com.neuronrobotics.sdk.common.RpcEncapsulation;
import com.neuronrobotics.sdk.common.device.server.bcs.core.BcsCoreNamespaceImp;
import com.neuronrobotics.sdk.common.device.server.bcs.rpc.BcsRpcNamespaceImp;
import com.neuronrobotics.sdk.network.BowlerTCPServer;
import com.neuronrobotics.sdk.network.BowlerUDPServer;
import com.neuronrobotics.sdk.network.UDPBowlerConnection;

// TODO: Auto-generated Javadoc
/**
 * The Class BowlerAbstractServer.
 */
public abstract class BowlerAbstractServer implements
		ISynchronousDatagramListener {

	/** The servers. */
	private ArrayList servers = new ArrayList();
	
	/** The local servers. */
	private ArrayList localServers = new ArrayList();

	/** The namespaces. */
	private ArrayList namespaces = new ArrayList();

	/** The bcs core. */
	private BcsCoreNamespaceImp bcsCore;
	
	/** The bcs rpc. */
	private BcsRpcNamespaceImp bcsRpc;
	
	/** The udp server. */
	private BowlerUDPServer udpServer;

	/** The mac address. */
	private MACAddress macAddress;

	/**
	 * Instantiates a new bowler abstract server.
	 *
	 * @param mac the mac
	 */
	public BowlerAbstractServer(MACAddress mac) {
		this.setMacAddress(mac);
		bcsCore = new BcsCoreNamespaceImp(this, mac);
		bcsRpc = new BcsRpcNamespaceImp(this, mac);
		setup();
	}

	/**
	 * Setup.
	 */
	private void setup() {
		if (!getNamespaces().contains(bcsCore)) {
			getNamespaces().add(bcsCore);
			bcsCore.setNamespaceIndex(0);
		}
		if (!getNamespaces().contains(bcsRpc)) {
			bcsRpc.setNamespaceIndex(1);
			getNamespaces().add(bcsRpc);
		}
	}

	/**
	 * Adds the bowler device server namespace.
	 *
	 * @param ns the ns
	 */
	public void addBowlerDeviceServerNamespace(
			BowlerAbstractDeviceServerNamespace ns) {
		setup();
		if (!getNamespaces().contains(ns)) {
			for (int i = 0; i < getNamespaces().size(); i++) {
				if (getNamespaces().get(i).getNamespace()
						.contains(ns.getNamespace())) {
					Log.error("Duplicate Namespace" + ns.getNamespace());
					return;
				}
			}
			ns.setNamespaceIndex(getNamespaces().size());
			getNamespaces().add(ns);
		}
	}

	/**
	 * Removes the bowler device server namespace.
	 *
	 * @param ns the ns
	 */
	public void removeBowlerDeviceServerNamespace(
			BowlerAbstractDeviceServerNamespace ns) {
		setup();
		if (getNamespaces().contains(ns))
			getNamespaces().remove(ns);
	}

	/**
	 * Process local.
	 *
	 * @param data the data
	 * @return the bowler datagram
	 */
	private BowlerDatagram processLocal(BowlerDatagram data) {
		setup();
		if (getNamespaces().size() == 0) {
			throw new RuntimeException("No namespaces defined");
		}
		for (BowlerAbstractDeviceServerNamespace n : getNamespaces()) {
			// System.out.println("Checking "+n.getNamespaces().get(0));
			if (n.checkRpc(data)) {
				BowlerDatagram d = n.process(data);
				if (d != null) {
					if (!d.getRPC().contains("_err"))
						return d;
				}
			}
		}
		Log.error("No namespace found for " + data);
		return null;
	}

	/**
	 * Gets the servers.
	 *
	 * @return the servers
	 */
	public ArrayList getServers() {
		return servers;
	}

	/** The server socket. */
	ServerSocket serverSocket;

	/**
	 * Start network server.
	 *
	 * @param port the port
	 * @throws IOException Signals that an I/O exception has occurred.
	 */
	public void startNetworkServer(final int port) throws IOException {
		udpServer = new BowlerUDPServer(port);
		serverSocket = new ServerSocket(port + 1);
		new Thread() {
			public void run() {
				setName("Bowler Platform Network Server");
				addServer(udpServer);
				while (true) {
					Socket s;
					try {
						//ex.printStackTrace();
						Log.warning("\n\nWaiting for UDP connection on port "+(port)+"...");
						Log.warning("\n\nWaiting for TCP connection on port "+(port+1)+"...");
						s = serverSocket.accept();
						addServer(new BowlerTCPServer(s));
						Log.warning("Got a connection!");
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}
		}.start();

	}

	/**
	 * Start network server.
	 *
	 * @throws IOException Signals that an I/O exception has occurred.
	 */
	public void startNetworkServer() throws IOException {
		startNetworkServer(1865);

	}

	/**
	 * Adds the server.
	 *
	 * @param srv the srv
	 */
	public void addServer(BowlerAbstractConnection srv) {
		if (!servers.contains(srv)) {
			srv.addConnectionEventListener(new IConnectionEventListener() {
				@Override
				public void onDisconnect(BowlerAbstractConnection source) {
					Log.warning("Removing server from listener");
					removeServer(source);
				}

				@Override
				public void onConnect(BowlerAbstractConnection source) {

				}
			});
			servers.add(srv);
			srv.connect();
			srv.setSynchronousDatagramListener(this);
		}
	}

	/* (non-Javadoc)
	 * @see com.neuronrobotics.sdk.common.ISynchronousDatagramListener#onSyncReceive(com.neuronrobotics.sdk.common.BowlerDatagram)
	 */
	@Override
	public BowlerDatagram onSyncReceive(BowlerDatagram data) {
		if (data.isUpstream()) {
			// a server ignores upstream packets received
			Log.error("Upstream packet detected" + data);
			return null;
		}
		if (!data.getRPC().contains("_png"))
			Log.debug("Server Got >> " + data);
		else {
			Log.info("Got >> ping");
		}
		BowlerDatagram bd = processLocal(data);
		if (bd != null) {
			if (!data.getRPC().contains("_png"))
				Log.debug("Server Response << " + bd);
			else {
				Log.info("Response << ping");
			}
			return bd;
		} else {
			Log.error("Packet unknown" + data);
		}
		return null;
	}

	/**
	 * Removes the server.
	 *
	 * @param b the b
	 */
	private void removeServer(BowlerAbstractConnection b) {
		if (b == udpServer) {
			try {
				udpServer.reconnect();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			return;
		}
		Log.error("Server Removed " + b);
		// new RuntimeException().printStackTrace();

		getServers().remove(b);
	}

	/**
	 * THis is the scripting interface to Bowler devices. THis allows a user to
	 * describe a namespace, rpc, and array or arguments to be paced into the
	 * packet based on the data types of the argument. The response in likewise
	 * unpacked into an array of objects.
	 *
	 * @param namespaceIndex the namespace index
	 * @param namespace            The string of the desired namespace
	 * @param rpcString            The string of the desired RPC
	 * @param arguments            An array of objects corresponding to the data to be stuffed
	 *            into the packet.
	 * @param asyncArguments the async arguments
	 * @throws DeviceConnectionException             If the desired RPC's are not available then this will be
	 *             thrown
	 */
	public void pushAsyncPacket(int namespaceIndex, String namespace,
			String rpcString, Object[] arguments,
			BowlerDataType[] asyncArguments) {
		if (arguments.length != asyncArguments.length) {
			throw new RuntimeException(
					"Arguments must match argument types exactly, your two arrays are different lengths");
		}
		RpcEncapsulation rpcl = new RpcEncapsulation(namespaceIndex, namespace,
				rpcString, BowlerMethod.ASYNCHRONOUS, asyncArguments, null,
				null);
		BowlerAbstractCommand command = BowlerAbstractConnection.getCommand(
				namespace, BowlerMethod.ASYNCHRONOUS, rpcString, arguments,
				rpcl);
		BowlerDatagram cmd = BowlerDatagramFactory.build(new MACAddress(),
				command);
		Log.debug("Async>>" + cmd);
		pushAsyncPacket(cmd);
	}

	/**
	 * Push async packet.
	 *
	 * @param data the data
	 */
	public synchronized void pushAsyncPacket(BowlerDatagram data) {
		localServers.clear();
		for (int i = 0; i < servers.size(); i++) {
			localServers.add(getServers().get(i));
		}

		for (int i = 0; i < servers.size(); i++) {
			try {
				boolean run = false;
				if (localServers.get(i).getClass() == BowlerTCPServer.class) {
					BowlerTCPServer b = (BowlerTCPServer) localServers.get(i);
					if (b.isClientConnected()) {
						run = true;
						Log.info("TCP Bowler client ...OK!");
					}
				} else {
					run = true;
				}
				if (localServers.get(i).getClass() != BowlerUDPServer.class) {
					// System.out.println("Sending packet to "+getServers().get(i).getClass());
					if (run && localServers.get(i).isConnected()) {
						// Log.warning("ASYNC<<\r\n"+data );
						String classString = localServers.get(i).getClass()
								.toString();
						localServers.get(i).sendAsync(data);
						Log.info("Sent packet to " + classString);
					}
				} else {
					try {
						localServers.get(i).sendAsync(data);
					} catch (NullPointerException ex) {
					}
				}
			} catch (IndexOutOfBoundsException ie) {
				ie.printStackTrace();
			} catch (Exception e) {
				try {
					e.printStackTrace();
					BowlerAbstractConnection abs = localServers.get(i);
					Log.error("No client connected to this connection "
							+ abs.getClass());
					abs.disconnect();

				} catch (Exception ex) {
					ex.printStackTrace();
				}
			}
		}
		localServers.clear();
	}

	/**
	 * Gets the namespaces.
	 *
	 * @return the namespaces
	 */
	public ArrayList getNamespaces() {
		return namespaces;
	}

	/**
	 * Sets the namespaces.
	 *
	 * @param namespaces the new namespaces
	 */
	public void setNamespaces(
			ArrayList namespaces) {
		this.namespaces = namespaces;
	}

	/**
	 * Gets the mac address.
	 *
	 * @return the mac address
	 */
	public MACAddress getMacAddress() {
		return macAddress;
	}

	/**
	 * Sets the mac address.
	 *
	 * @param macAddress the new mac address
	 */
	public void setMacAddress(MACAddress macAddress) {
		this.macAddress = macAddress;
	}



}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy