1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2025-01-18 03:52:11 +01:00

AndroidGCS: Refactor TCP and HID onto a common TelemTask class which handles

most of the logic of setting up the UAVTalk, ObjectMangager, Telemetry and
TelemetryMonitor classes.  Provides a cleaner shutdown too.
This commit is contained in:
James Cotton 2012-08-11 14:49:35 -05:00
parent 5addc15f60
commit d0bb6c3813
4 changed files with 405 additions and 379 deletions

View File

@ -11,12 +11,7 @@ import java.util.HashMap;
import java.util.Iterator;
import junit.framework.Assert;
import org.openpilot.uavtalk.UAVObjectManager;
import org.openpilot.uavtalk.UAVTalk;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@ -30,21 +25,13 @@ import android.hardware.usb.UsbManager;
import android.hardware.usb.UsbRequest;
import android.util.Log;
public class HidUAVTalk {
public class HidUAVTalk extends TelemetryTask {
private static final String TAG = HidUAVTalk.class.getSimpleName();
public static int LOGLEVEL = 0;
public static boolean WARN = LOGLEVEL > 1;
public static boolean DEBUG = LOGLEVEL > 0;
Service hostDisplayActivity;
private boolean connected;
private UAVTalk uavTalk;
private UAVObjectManager objMngr;
//! USB constants
static final int OPENPILOT_VENDOR_ID = 0x20A0;
@ -56,51 +43,57 @@ public class HidUAVTalk {
static final int USB_PRODUCT_ID_OSD = 0x4194;
static final int USB_PRODUCT_ID_SPARE = 0x4195;
public HidUAVTalk(Service service) {
hostDisplayActivity = service;
}
public boolean getConnected() {
return connected;
}
public UAVTalk getUavtalk() {
return uavTalk;
}
/**
* Opens a TCP socket to the address determined on construction. If successful
* creates a UAVTalk stream connection this socket to the passed in object manager
*/
public boolean openTelemetryHid(UAVObjectManager objMngr) {
uavTalk = new UAVTalk(inStream, outStream, objMngr);
this.objMngr = objMngr;
return true;
private static final String ACTION_USB_PERMISSION = "com.access.device.USB_PERMISSION";
UsbDevice currentDevice;
public HidUAVTalk(OPTelemetryService service) {
super(service);
}
@Override
public void disconnect() {
CleanUpAndClose();
//hostDisplayActivity.unregisterReceiver(usbReceiver);
//hostDisplayActivity.unregisterReceiver(usbPermissionReceiver);
inStream.stop();
outStream.stop();
telemService.unregisterReceiver(usbPermissionReceiver);
((TalkInputStream)inStream).stop();
((TalkOutputStream)outStream).stop();
super.disconnect();
try {
readThread.join();
writeThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
if (readRequest != null) {
readRequest.cancel();
readRequest.close();
readRequest = null;
}
if (writeRequest != null) {
writeRequest.cancel();
writeRequest.close();
writeRequest = null;
}
}
public boolean connect(UAVObjectManager objMngr) {
@Override
boolean attemptConnection() {
if (DEBUG) Log.d(TAG, "connect()");
// Register to get permission requested dialog
usbManager = (UsbManager) hostDisplayActivity.getSystemService(Context.USB_SERVICE);
permissionIntent = PendingIntent.getBroadcast(hostDisplayActivity, 0, new Intent(ACTION_USB_PERMISSION), 0);
usbManager = (UsbManager) telemService.getSystemService(Context.USB_SERVICE);
permissionIntent = PendingIntent.getBroadcast(telemService, 0, new Intent(ACTION_USB_PERMISSION), 0);
permissionFilter = new IntentFilter(ACTION_USB_PERMISSION);
hostDisplayActivity.registerReceiver(usbPermissionReceiver, permissionFilter);
// Register to get notified on device attached
/*deviceAttachedFilter = new IntentFilter();
deviceAttachedFilter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
deviceAttachedFilter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
hostDisplayActivity.registerReceiver(usbReceiver, deviceAttachedFilter);*/
telemService.registerReceiver(usbPermissionReceiver, permissionFilter);
// Go through all the devices plugged in
HashMap<String, UsbDevice> deviceList = usbManager.getDeviceList();
if (DEBUG) Log.d(TAG, "Found " + deviceList.size() + " devices");
Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
@ -108,33 +101,13 @@ public class HidUAVTalk {
UsbDevice dev = deviceIterator.next();
if (DEBUG) Log.d(TAG, "Testing device: " + dev);
usbManager.requestPermission(dev, permissionIntent);
//ConnectToDeviceInterface(dev);
}
if (DEBUG) Log.d(TAG, "Registered the deviceAttachedFilter");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if( !openTelemetryHid(objMngr) )
return false;
return connected;
return deviceList.size() > 0;
}
public HidUAVTalk(OPTelemetryService opTelemetryService) {
this.hostDisplayActivity = opTelemetryService;
}
private static final String ACTION_USB_PERMISSION = "com.access.device.USB_PERMISSION";
UsbDevice currentDevice;
/*
* Receives a requested broadcast from the operating system.
* In this case the following actions are handled:
@ -172,9 +145,6 @@ public class HidUAVTalk {
{
if (DEBUG) Log.d(TAG, "Unable to connect to device");
}
sendEnabledMessage();
// TODO: Create a listener to receive messages from the host
}
}
else
@ -224,12 +194,8 @@ public class HidUAVTalk {
}
}
}
private void sendEnabledMessage() {
// TODO Auto-generated method stub
};
};
private UsbEndpoint usbEndpointRead;
private UsbEndpoint usbEndpointWrite;
@ -246,11 +212,6 @@ public class HidUAVTalk {
private IntentFilter permissionFilter;
protected void sendEnabledMessage() {
// TODO Auto-generated method stub
}
protected void CleanUpAndClose() {
if (UsingSingleInterface) {
if(connectionRead != null && usbInterfaceRead != null)
@ -372,12 +333,53 @@ public class HidUAVTalk {
}
connectedDevice = connectDevice;
connected = true;
if (DEBUG) Log.d(TAG, "Opened endpoints");
// Create the USB requests
readRequest = new UsbRequest();
readRequest.initialize(connectionRead, usbEndpointRead);
writeRequest = new UsbRequest();
writeRequest.initialize(connectionWrite, usbEndpointWrite);
handler.post(new Runnable() {
@Override
public void run() {
inStream = new TalkInputStream();
outStream = new TalkOutputStream();
attemptSucceeded();
}
});
readThread = new Thread(new Runnable() {
@Override
public void run() {
while (!shutdown) {
readData();
sendData();
}
}
});
readThread.start();
writeThread = new Thread(new Runnable() {
@Override
public void run() {
while (!shutdown) {
sendData();
}
}
});
//writeThread.start();
return true;
}
Thread readThread;
Thread writeThread;
private int byteToInt(byte b) { return b & 0x000000ff; }
private class TalkInputStream extends InputStream {
@ -409,7 +411,6 @@ public class HidUAVTalk {
data.put(b);
}
};
private final TalkInputStream inStream = new TalkInputStream();
private class ByteFifo {
@ -479,11 +480,6 @@ public class HidUAVTalk {
int bufferDataLength = usbEndpointRead.getMaxPacketSize();
ByteBuffer buffer = ByteBuffer.allocate(bufferDataLength + 1);
if(readRequest == null) {
readRequest = new UsbRequest();
readRequest.initialize(connectionRead, usbEndpointRead);
}
// queue a request on the interrupt endpoint
if(!readRequest.queue(buffer, bufferDataLength)) {
if (DEBUG) Log.d(TAG, "Failed to queue request");
@ -511,17 +507,12 @@ public class HidUAVTalk {
buffer.position(2);
buffer.get(dst, 0, dataSize);
if (DEBUG) Log.d(TAG, "Entered read");
inStream.write(dst);
((TalkInputStream)inStream).write(dst);
if (DEBUG) Log.d(TAG, "Got read: " + dataSize + " bytes");
}
} else
return 0;
if(false) {
readRequest.cancel();
readRequest.close();
}
return dataSize;
}
@ -600,30 +591,32 @@ public class HidUAVTalk {
// Remove that data from the write buffer
data.compact();
writePosition -= size;
if (DEBUG) Log.d(TAG, "packetizeData(): size="+size);
}
WriteToDevice(packet);
}
};
private final TalkOutputStream outStream = new TalkOutputStream();
private static final int MAX_HID_PACKET_SIZE = 64;
/**
* Send a packet or wait for data to be available
*/
public void send() {
synchronized(outStream.data){
if (outStream.writePosition > 0)
outStream.packetizeData();
public void sendData() {
TalkOutputStream o = (TalkOutputStream) outStream;
synchronized(o.data){
if (o.writePosition > 0)
o.packetizeData();
else {
outStream.data.notify();
outStream.packetizeData();
o.data.notify();
o.packetizeData();
}
}
}
UsbRequest writeRequest = null;
boolean WriteToDevice(ByteBuffer DataToSend) {
if (DEBUG) Log.d(TAG, "Writing to device()");
//The report must be formatted correctly for the device being connected to. On some devices, this requires that a specific value must be the first byte in the report. This can be followed by the length of the data in the report. This format is determined by the device, and isn't specified here.
@ -708,4 +701,5 @@ public class HidUAVTalk {
// TODO Auto-generated method stub
return false;
}
}

View File

@ -81,6 +81,7 @@ public class OPTelemetryService extends Service {
private boolean terminate = false;
private Thread activeTelem;
private TelemetryTask telemTask;
private final IBinder mBinder = new LocalBinder();
@ -130,11 +131,13 @@ public class OPTelemetryService extends Service {
break;
case 3:
Toast.makeText(getApplicationContext(), "Attempting TCP connection", Toast.LENGTH_SHORT).show();
activeTelem = new TcpTelemetryThread();
telemTask = new TcpUAVTalk(this);
activeTelem = new Thread(telemTask);
break;
case 4:
Toast.makeText(getApplicationContext(), "Attempting USB HID connection", Toast.LENGTH_SHORT).show();
activeTelem = new HidTelemetryThread();
telemTask = new HidUAVTalk(this);
activeTelem = new Thread(telemTask);
break;
default:
throw new Error("Unsupported");
@ -143,8 +146,19 @@ public class OPTelemetryService extends Service {
break;
case MSG_DISCONNECT:
Toast.makeText(getApplicationContext(), "Disconnect requested", Toast.LENGTH_SHORT).show();
if (DEBUG) Log.d(TAG, "Calling disconnect");
terminate = true;
if (activeTelem != null) {
if (telemTask != null) {
telemTask.disconnect();
telemTask = null;
try {
activeTelem.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
else if (activeTelem != null) {
activeTelem.interrupt();
try {
activeTelem.join();
@ -153,6 +167,7 @@ public class OPTelemetryService extends Service {
}
activeTelem = null;
}
if (DEBUG) Log.d(TAG, "Telemetry thread terminated");
Intent intent = new Intent();
intent.setAction(INTENT_ACTION_DISCONNECTED);
sendBroadcast(intent,null);
@ -215,12 +230,25 @@ public class OPTelemetryService extends Service {
@Override
public void onDestroy() {
if (telemTask != null) {
Log.d(TAG, "onDestory() shutting down telemetry task");
telemTask.disconnect();
telemTask = null;
try {
activeTelem.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Log.d(TAG, "onDestory() shut down telemetry task");
Toast.makeText(this, "Telemetry service done", Toast.LENGTH_SHORT).show();
}
public class LocalBinder extends Binder {
public TelemTask getTelemTask(int id) {
return (TelemTask) activeTelem;
return telemTask.getTelemTaskIface();
}
public void openConnection() {
Toast.makeText(getApplicationContext(), "Requested open connection", Toast.LENGTH_SHORT).show();
@ -395,225 +423,4 @@ public class OPTelemetryService extends Service {
}
};
private class TcpTelemetryThread extends Thread implements TelemTask {
private final UAVObjectManager objMngr;
private UAVTalk uavTalk;
private Telemetry tel;
private TelemetryMonitor mon;
@Override
public UAVObjectManager getObjectManager() { return objMngr; };
TcpTelemetryThread() {
objMngr = new UAVObjectManager();
UAVObjectsInitialize.register(objMngr);
}
@Override
public void run() {
if (DEBUG) Log.d(TAG, "Telemetry Thread started");
Looper.prepare();
TcpUAVTalk tcp = new TcpUAVTalk(OPTelemetryService.this);
for( int i = 0; i < 10; i++ ) {
if (DEBUG) Log.d(TAG, "Attempting network Connection");
tcp.connect(objMngr);
if( tcp.getConnected() )
break;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Log.e(TAG, "Thread interrupted while trying to connect");
e.printStackTrace();
return;
}
}
if( ! tcp.getConnected() || terminate ) {
toastMessage("TCP connection failed");
return;
}
toastMessage("TCP Connected");
if (DEBUG) Log.d(TAG, "Connected via network");
uavTalk = tcp.getUavtalk();
tel = new Telemetry(uavTalk, objMngr);
mon = new TelemetryMonitor(objMngr,tel);
mon.addObserver(new Observer() {
@Override
public void update(Observable arg0, Object arg1) {
if (DEBUG) Log.d(TAG, "Mon updated. Connected: " + mon.getConnected() + " objects updated: " + mon.getObjectsUpdated());
if(mon.getConnected()) {
Intent intent = new Intent();
intent.setAction(INTENT_ACTION_CONNECTED);
sendBroadcast(intent,null);
}
}
});
if (DEBUG) Log.d(TAG, "Entering UAVTalk processing loop");
while( !terminate ) {
try {
if( !uavTalk.processInputStream() )
break;
} catch (IOException e) {
e.printStackTrace();
toastMessage("TCP Stream interrupted");
break;
}
}
Looper.myLooper().quit();
// Shut down all the attached
mon.stopMonitor();
mon = null;
tel.stopTelemetry();
tel = null;
// Finally close the stream if it is still open
tcp.disconnect();
if (DEBUG) Log.d(TAG, "UAVTalk stream disconnected");
toastMessage("TCP Thread finished");
}
};
private class HidTelemetryThread extends Thread implements TelemTask {
private final UAVObjectManager objMngr;
private UAVTalk uavTalk;
private Telemetry tel;
private TelemetryMonitor mon;
@Override
public UAVObjectManager getObjectManager() { return objMngr; };
HidTelemetryThread() {
objMngr = new UAVObjectManager();
UAVObjectsInitialize.register(objMngr);
}
@Override
public void run() {
if (DEBUG) Log.d(TAG, "HID Telemetry Thread started");
Looper.prepare();
final HidUAVTalk hid = new HidUAVTalk(OPTelemetryService.this);
hid.connect(objMngr);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if( !hid.getConnected() ) {
toastMessage("HID connection failed");
return;
}
uavTalk = hid.getUavtalk();
tel = new Telemetry(uavTalk, objMngr);
mon = new TelemetryMonitor(objMngr,tel);
mon.addObserver(new Observer() {
@Override
public void update(Observable arg0, Object arg1) {
if (DEBUG) Log.d(TAG, "Mon updated. Connected: " + mon.getConnected() + " objects updated: " + mon.getObjectsUpdated());
if(mon.getConnected()) {
Intent intent = new Intent();
intent.setAction(INTENT_ACTION_CONNECTED);
sendBroadcast(intent,null);
}
}
});
// Read data from HID and push it ont the UAVTalk input stream
Thread t = new Thread(this) {
@Override
public void run() {
while(!terminate) {
hid.readData();
hid.send();
}
Log.e(TAG, "TERMINATED");
}
};
t.start();
// Read data from HID and push it ont the UAVTalk input stream
Thread t2 = new Thread(this) {
@Override
public void run() {
while(!terminate) {
hid.send();
try {
sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
};
//t2.start();
// Process any bytes that have been pushed onto the UAVTalk stream
if (DEBUG) Log.d(TAG, "Entering UAVTalk processing loop");
while( !terminate ) {
try {
if( !uavTalk.processInputStream() )
break;
} catch (IOException e) {
e.printStackTrace();
toastMessage("TCP Stream interrupted");
break;
}
}
try {
Thread.sleep(5000);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
Looper.myLooper().quit();
// Stop the HID reading loop
t.interrupt();
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
hid.disconnect();
// Shut down all the attached
mon.stopMonitor();
mon = null;
tel.stopTelemetry();
tel = null;
// Finally close the stream if it is still open
hid.disconnect();
if (DEBUG) Log.d(TAG, "UAVTalk stream disconnected");
toastMessage("TCP Thread finished");
}
};
}

View File

@ -28,15 +28,11 @@ import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import org.openpilot.uavtalk.UAVObjectManager;
import org.openpilot.uavtalk.UAVTalk;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.util.Log;
public class TcpUAVTalk {
public class TcpUAVTalk extends TelemetryTask {
private final String TAG = "TcpUAVTalk";
public static int LOGLEVEL = 2;
public static boolean WARN = LOGLEVEL > 1;
@ -46,16 +42,23 @@ public class TcpUAVTalk {
private String ip_address = "1";
private int port = 9001;
private UAVTalk uavTalk;
private boolean connected;
private Socket socket;
/**
* Construct a TcpUAVTalk object attached to the OPTelemetryService. Gets the
* connection settings from the preferences.
*/
public TcpUAVTalk(Context caller) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(caller);
public TcpUAVTalk(OPTelemetryService caller) {
super(caller);
}
@Override
boolean attemptConnection() {
if( getConnected() )
return true;
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(telemService);
ip_address = prefs.getString("ip_address","127.0.0.1");
try {
port = Integer.decode(prefs.getString("port", ""));
@ -65,44 +68,6 @@ public class TcpUAVTalk {
if (DEBUG) Log.d(TAG, "Trying to open UAVTalk with " + ip_address);
connected = false;
}
/**
* Connect a TCP object to an object manager. Returns true if already
* connected, otherwise returns true if managed a successful socket.
*/
public boolean connect(UAVObjectManager objMngr) {
if( getConnected() )
return true;
if( !openTelemetryTcp(objMngr) )
return false;
return true;
}
public void disconnect() {
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
socket = null;
}
public boolean getConnected() {
return connected;
}
public UAVTalk getUavtalk() {
return uavTalk;
}
/**
* Opens a TCP socket to the address determined on construction. If successful
* creates a UAVTalk stream connection this socket to the passed in object manager
*/
private boolean openTelemetryTcp(UAVObjectManager objMngr) {
Log.d(TAG, "Opening connection to " + ip_address + " at address " + port);
InetAddress serverAddr = null;
@ -121,18 +86,43 @@ public class TcpUAVTalk {
return false;
}
connected = true;
try {
uavTalk = new UAVTalk(socket.getInputStream(), socket.getOutputStream(), objMngr);
inStream = socket.getInputStream();
outStream = socket.getOutputStream();
} catch (IOException e) {
Log.e(TAG,"Error starting UAVTalk");
// TODO Auto-generated catch block
//e.printStackTrace();
try {
socket.close();
} catch (IOException e2) {
}
return false;
}
// Post message to call attempt succeeded on the parent class
handler.post(new Runnable() {
@Override
public void run() {
TcpUAVTalk.this.attemptSucceeded();
}
});
return true;
}
@Override
public void disconnect() {
super.disconnect();
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
socket = null;
}
}
}

View File

@ -0,0 +1,235 @@
package org.openpilot.androidgcs.telemetry;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Observable;
import java.util.Observer;
import org.openpilot.uavtalk.Telemetry;
import org.openpilot.uavtalk.TelemetryMonitor;
import org.openpilot.uavtalk.UAVObjectManager;
import org.openpilot.uavtalk.UAVTalk;
import org.openpilot.uavtalk.uavobjects.UAVObjectsInitialize;
import android.content.Intent;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
public abstract class TelemetryTask implements Runnable {
// Logging settings
private final String TAG = TelemetryTask.class.getSimpleName();
public static final int LOGLEVEL = 2;
public static final boolean WARN = LOGLEVEL > 1;
public static final boolean DEBUG = LOGLEVEL > 0;
/*
* This is a self contained runnable that will establish (if possible)
* a telemetry connection and provides a listener interface to be
* notified of a set of events
*
* 1. attempt to establish connection
* 2. callback when it succeeds (or fails) which notifies listener
* 3. once physical connection is established instantiate uavtalk / objectmanager
* 4. notify listener they are connected
* 5. detect physical link failure and notify listener about that
* 6. provide "close link" method
*
* There are essentially four tasks that need to occur here
* 1. Transfer data from the outputStream to the physical link (some protocols do this automatically)
* 2. Transfer data from the physical link to the inputStream (again some protocols do this automatically)
* 3. Transfer data from the inputStream to UAVTalk (uavTalk.processInputByte)
* 4. Transfer data from objects via UAVTalk to output stream (occurs from Telemetry object)
*/
//! Private variables
protected Handler handler;
//! Handle to the parent service
protected final OPTelemetryService telemService;
//! The object manager that will be used for this telemetry task
protected UAVObjectManager objMngr;
//! The UAVTalk connected to the below streams
private UAVTalk uavTalk;
//! The input stream for the telemetry channel
protected InputStream inStream;
//! The output stream for the telemetry channel
protected OutputStream outStream;
//! The telemetry object which takes care of higher level transactions
private Telemetry tel;
//! The telemetry monitor which takes care of high level connects / disconnects
private TelemetryMonitor mon;
//! Flag to indicate a shut down was requested. Derived classes should take care to respect this.
boolean shutdown;
//! Indicate a physical connection is established
private boolean connected;
TelemetryTask(OPTelemetryService s) {
telemService = s;
shutdown = false;
connected = false;
}
/**
* Attempt a connection. This method may return before the results are
* known.
* @return False if the attempt failed and no connection will be established
* @return True if the attempt succeeded but does not guarantee success
*/
abstract boolean attemptConnection();
/**
* Called when a physical channel is opened
*
* When this method is called the derived class must have
* created a valid inStream and outStream
*/
boolean attemptSucceeded() {
// Create a new object manager and register all objects
// in the future the particular register method should
// be dependent on what is connected (e.g. board and
// version number).
objMngr = new UAVObjectManager();
UAVObjectsInitialize.register(objMngr);
// Create the required telemetry objects attached to this
// data stream
uavTalk = new UAVTalk(inStream, outStream, objMngr);
tel = new Telemetry(uavTalk, objMngr);
mon = new TelemetryMonitor(objMngr,tel);
// Create an observer to notify system of connection
mon.addObserver(connectionObserver);
// Create a new thread that processes the input bytes
startInputProcessing();
connected = true;
return connected;
}
boolean attemptedFailed() {
connected = false;
return connected;
}
void disconnect() {
// Make the default input procesing loop stop
shutdown = true;
// Shut down all the attached
if (mon != null) {
mon.stopMonitor();
mon.deleteObserver(connectionObserver);
mon = null;
}
if (tel != null) {
tel.stopTelemetry();
tel = null;
}
// Stop the master telemetry thread
handler.post(new Runnable() {
@Override
public void run() {
Looper.myLooper().quit();
}
});
// TODO: Make sure the input and output stream is closed
// TODO: Make sure any threads for input and output are closed
}
/**
* Default implementation for processing input stream
* which creates a new thread that keeps attempting
* to read from the input stream.
*/
private void startInputProcessing() {
new Thread(new processUavTalk()).start();
}
//! Runnable to process input stream
class processUavTalk implements Runnable {
@Override
public void run() {
if (DEBUG) Log.d(TAG, "Entering UAVTalk processing loop");
while (!shutdown) {
try {
if( !uavTalk.processInputStream() )
break;
} catch (IOException e) {
e.printStackTrace();
telemService.toastMessage("Telemetry input stream interrupted");
break;
}
}
if (DEBUG) Log.d(TAG, "UAVTalk processing loop finished");
}
};
@Override
public void run() {
try {
Looper.prepare();
handler = new Handler();
if (DEBUG) Log.d(TAG, "Attempting connection");
if( attemptConnection() == false )
return; // Attempt failed
Looper.loop();
if (DEBUG) Log.d(TAG, "TelemetryTask runnable finished");
} catch (Throwable t) {
Log.e(TAG, "halted due to an error", t);
}
telemService.toastMessage("Telemetry Thread finished");
}
private final Observer connectionObserver = new Observer() {
@Override
public void update(Observable arg0, Object arg1) {
if (DEBUG) Log.d(TAG, "Mon updated. Connected: " + mon.getConnected() + " objects updated: " + mon.getObjectsUpdated());
if(mon.getConnected()) {
Intent intent = new Intent();
intent.setAction(OPTelemetryService.INTENT_ACTION_CONNECTED);
telemService.sendBroadcast(intent,null);
}
}
};
/**** General accessors ****/
public boolean getConnected() {
return connected;
}
public UAVTalk getUavtalk() {
return uavTalk;
}
public OPTelemetryService.TelemTask getTelemTaskIface() {
return new OPTelemetryService.TelemTask() {
@Override
public UAVObjectManager getObjectManager() {
return objMngr;
}
};
}
}