Permalink
Cannot retrieve contributors at this time
Fetching contributors…
| package com.litlebot.rioapi.proto2015; | |
| import java.io.IOException; | |
| import java.io.InterruptedIOException; | |
| import java.net.DatagramPacket; | |
| import java.net.DatagramSocket; | |
| import java.net.InetAddress; | |
| import java.net.SocketException; | |
| import java.util.ArrayList; | |
| /** | |
| * | |
| * The ComManager class manages the overall communication between the DS | |
| * and RIO device. Make an instance with the constructor then use connect() | |
| * and disconnect() to initialize and terminate communications. | |
| * | |
| * @author raystubbs | |
| * | |
| */ | |
| public class ComManager | |
| { | |
| private static final int RIO_CONTROL_PORT = 1110, DS_STATUS_PORT = 1150; | |
| private volatile boolean connected; | |
| private volatile int packetIndex; | |
| private volatile byte[] recvBuffer; | |
| private volatile ArrayList<Joystick> joysticks; | |
| private volatile InetAddress rioAddr; | |
| private volatile ControlPacket cntrlPkt; | |
| private volatile StatusPacket statPkt; | |
| private volatile DatagramSocket sendSok; | |
| private volatile DatagramSocket recvSok; | |
| private volatile StateController statCtrl; | |
| private volatile ConnectionCallback conCallback; | |
| private volatile ComCallback comCallback; | |
| /** | |
| * Initializes an instance of ComManager to communicate with | |
| * a RIO at the address rioAddr, and with statCtrl as the state | |
| * controller, which can be null to use the default which sets the | |
| * rio to a disabled state. | |
| * | |
| * @param rioAddr | |
| * Address of the RIO device. | |
| * | |
| * @param statCtrl | |
| * An instance of the StateController interface to tell the manager the | |
| * mode and position of the RIO. | |
| */ | |
| public ComManager(InetAddress rioAddr, StateController statCtrl) | |
| { | |
| this.rioAddr = rioAddr; | |
| this.statCtrl = statCtrl; | |
| this.connected = false; | |
| this.packetIndex = 0; | |
| this.recvBuffer = new byte[48]; | |
| this.joysticks = new ArrayList<Joystick>(); | |
| } | |
| //------------------Communications handlers-----------------------// | |
| Thread senderThread = new Thread() | |
| { | |
| public void run() | |
| { | |
| while(connected) | |
| { | |
| try | |
| { | |
| DatagramPacket sendPkt = cntrlPkt.toDataPacket(); | |
| sendSok.send(sendPkt); | |
| onPacketSent(cntrlPkt, sendPkt); | |
| } catch (IOException e) | |
| { | |
| e.printStackTrace(); | |
| } | |
| try | |
| { | |
| Thread.sleep(20); | |
| } catch (InterruptedException e) | |
| { | |
| e.printStackTrace(); | |
| } | |
| } | |
| } | |
| }; | |
| Thread receiverThread = new Thread() | |
| { | |
| public void run() | |
| { | |
| try | |
| { | |
| recvSok.setSoTimeout(40); | |
| } catch (SocketException e) | |
| { | |
| e.printStackTrace(); | |
| } | |
| DatagramPacket recvPkt = new DatagramPacket(recvBuffer, 48); | |
| int failCount = 0; | |
| while(connected && failCount < 5) | |
| { | |
| try | |
| { | |
| recvSok.receive(recvPkt); | |
| failCount = 0; | |
| statPkt.invalidateData(recvPkt); | |
| onPacketReceived(statPkt, recvPkt); | |
| } catch(InterruptedIOException e) | |
| { | |
| failCount++; | |
| }catch (IOException e) | |
| { | |
| e.printStackTrace(); | |
| } | |
| try | |
| { | |
| Thread.sleep(20); | |
| } catch (InterruptedException e) | |
| { | |
| e.printStackTrace(); | |
| } | |
| } | |
| if(failCount >= 4) | |
| { | |
| connected = false; | |
| onConnectionLost(); | |
| } | |
| } | |
| }; | |
| /** | |
| * Attempts to initialize communication with the RIO device, after a call | |
| * to this method the ComManager will send and receive UDP packets every 20 ms. | |
| * Any joysticks should be added to the ComManager before communications are | |
| * initialized. | |
| * | |
| * @return | |
| * true if the connection attempt was successful false otherwise. | |
| */ | |
| public boolean connect() | |
| { | |
| onConnectionAttempt(); | |
| /*Separate thread for connection because networking is | |
| * not allowed on main thread in Android*/ | |
| Thread connectionThread = new Thread() | |
| { | |
| public void run() | |
| { | |
| try | |
| { | |
| sendSok = new DatagramSocket(); | |
| recvSok = new DatagramSocket(DS_STATUS_PORT); | |
| } catch (SocketException e) | |
| { | |
| System.err.println("Could not create DatagramSocket"); | |
| e.printStackTrace(); | |
| onConnectionFailed(); | |
| return; | |
| } | |
| cntrlPkt = new ConnectionPacket(0, (statCtrl == null)?defaultStatCtrl:statCtrl, rioAddr, joysticks); | |
| statPkt = new StatusPacket(); | |
| try | |
| { | |
| recvSok.setSoTimeout(20); | |
| } catch (SocketException e) | |
| { | |
| e.printStackTrace(); | |
| } | |
| for(int a = 5 ; a >= 0 ; a--) | |
| { | |
| DatagramPacket recvPkt = new DatagramPacket(recvBuffer, 48); | |
| try | |
| { | |
| sendSok.send(cntrlPkt.toDataPacket()); | |
| recvSok.receive(recvPkt); | |
| sendSok.send(cntrlPkt.toDataPacket()); | |
| statPkt.invalidateData(recvPkt); | |
| connected = true; | |
| return; | |
| } catch (IOException e) | |
| { | |
| e.printStackTrace(); | |
| } | |
| } | |
| } | |
| }; | |
| connectionThread.start(); | |
| try | |
| { | |
| connectionThread.join(); | |
| } catch (InterruptedException e) | |
| { | |
| e.printStackTrace(); | |
| } | |
| if(connected) | |
| onConnected(); | |
| else | |
| { | |
| onConnectionFailed(); | |
| return false; | |
| } | |
| senderThread.start(); | |
| receiverThread.start(); | |
| return true; | |
| } | |
| /** | |
| * Terminates communications with a RIO device, and waits for | |
| * all threads in ComManager to finish before returning. | |
| */ | |
| public void disconnect() | |
| { | |
| if(connected) | |
| { | |
| connected = false; | |
| onDisconnected(); | |
| try | |
| { | |
| senderThread.join(); | |
| receiverThread.join(); | |
| } catch (InterruptedException e) | |
| { | |
| e.printStackTrace(); | |
| } | |
| } | |
| } | |
| //--------------adders, isers, getters and setters----------------// | |
| /** | |
| * Is the ComManager communicating with the RIO? | |
| * | |
| * @return | |
| * True if communication is occurring, otherwise false. | |
| */ | |
| public boolean isConnected() | |
| { | |
| return connected; | |
| } | |
| /** | |
| * Returns the packet number of the current communications packet. | |
| * | |
| * @return | |
| * Index of the current communications packets. | |
| */ | |
| public int getPacketIndex() | |
| { | |
| return packetIndex; | |
| } | |
| /** | |
| * Adds joystick, giving this ComManager responsibility for | |
| * communicating its data to the RIO. | |
| * | |
| * @param j | |
| * The Joystick instance to add. | |
| */ | |
| public void addJoystick(Joystick j) | |
| { | |
| joysticks.add(j); | |
| } | |
| /** | |
| * Sets the manager's ConnectionCallback. | |
| * | |
| * @param cc | |
| * An instance of the ConnectionCallback interface. | |
| */ | |
| public void setConnectionCallback(ConnectionCallback cc) | |
| { | |
| conCallback = cc; | |
| } | |
| /** | |
| * Sets the ComManager's ComCallback to handle packet sending | |
| * and packet receipt events. | |
| * | |
| * @param cc | |
| * An instance of the ComCallback interface. | |
| */ | |
| public void setComCallback(ComCallback cc) | |
| { | |
| comCallback = cc; | |
| } | |
| //------------------Event handlers---------------------------------// | |
| private void onConnectionAttempt() | |
| { | |
| if(conCallback != null) | |
| conCallback.onConnectionAttempt(this); | |
| } | |
| private void onConnected() | |
| { | |
| if(conCallback != null) | |
| conCallback.onConnected(this); | |
| } | |
| private void onDisconnected() | |
| { | |
| if(conCallback != null) | |
| conCallback.onDisconnected(this); | |
| if(sendSok != null) | |
| sendSok.close(); | |
| if(recvSok != null) | |
| recvSok.close(); | |
| } | |
| private void onConnectionLost() | |
| { | |
| if(conCallback != null) | |
| conCallback.onConnectionLost(this); | |
| onDisconnected(); | |
| } | |
| private void onConnectionFailed() | |
| { | |
| if(conCallback != null) | |
| conCallback.onConnectionFailed(this); | |
| onDisconnected(); | |
| } | |
| private void onPacketSent(ControlPacket cntrlPkt2, DatagramPacket dtPkt) | |
| { | |
| if(comCallback != null) | |
| comCallback.onPacketSent(cntrlPkt2, dtPkt); | |
| } | |
| private void onPacketReceived(StatusPacket statPkt, DatagramPacket dtPkt) | |
| { | |
| if(comCallback != null) | |
| comCallback.onPacketReceived(statPkt, dtPkt); | |
| } | |
| //-------------------Callback interfaces---------------------------// | |
| /*Most of these are called from the networking threads, so be careful*/ | |
| /** | |
| * A callback interface to handle connection events. | |
| * @author raystubbs | |
| * | |
| */ | |
| public interface ConnectionCallback | |
| { | |
| /** | |
| * Called from the main thread when ComManager.connect() is called | |
| * @param com | |
| */ | |
| void onConnectionAttempt(ComManager com); | |
| /** | |
| * Called from the connection thread when ComManager successfully establishes | |
| * communication with the RIO. | |
| * @param com | |
| */ | |
| void onConnected(ComManager com); | |
| /** | |
| * Called when the manager stops communication for any reason, | |
| * could be caused by a call to ComManager.disconnect(), a connection | |
| * failure, or an unexpected loss of communication for some other reason. | |
| * @param com | |
| */ | |
| void onDisconnected(ComManager com); | |
| /** | |
| * Called when the ComManager looses communication for an unknown reason. | |
| * @param com | |
| */ | |
| void onConnectionLost(ComManager com); | |
| /** | |
| * Called when the manager fails to establish communication. | |
| * @param com | |
| */ | |
| void onConnectionFailed(ComManager com); | |
| } | |
| /** | |
| * A callback interface to handle communication events. | |
| * @author raystubbs | |
| * | |
| */ | |
| public interface ComCallback | |
| { | |
| /** | |
| * Called when the ComManager sends a packet to the RIO. | |
| * | |
| * @param cntrlPkt | |
| * The packet sent in ControlPacket form | |
| * | |
| * @param dtPkt | |
| * The packet sent in DatagramPacket form | |
| */ | |
| void onPacketSent(ControlPacket cntrlPkt, DatagramPacket dtPkt); | |
| /** | |
| * Called when the ComManager receives a packet from the RIO. | |
| * | |
| * @param statPkt | |
| * The packet received in the form of a StatusPacket | |
| * | |
| * @param dtPkt | |
| * The packet received in the form of a DatagramPacket | |
| */ | |
| void onPacketReceived(StatusPacket statPkt, DatagramPacket dtPkt); | |
| } | |
| //------------------Default StatusController----------------------------// | |
| private StateController defaultStatCtrl = new StateController() | |
| { | |
| @Override | |
| public byte getMode() | |
| { | |
| return 0; | |
| } | |
| @Override | |
| public byte getPosition() | |
| { | |
| return 0; | |
| } | |
| }; | |
| } |