mirror of
https://bitbucket.org/librepilot/librepilot.git
synced 2024-11-30 08:24:11 +01:00
Merge branch 'android' into sim_android
This commit is contained in:
commit
a8fa1c6b0d
@ -29,11 +29,14 @@
|
||||
*/
|
||||
package org.openpilot.androidgcs;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Observable;
|
||||
import java.util.Observer;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.openpilot.androidgcs.fragments.ObjectManagerFragment;
|
||||
import org.openpilot.androidgcs.telemetry.OPTelemetryService;
|
||||
import org.openpilot.androidgcs.telemetry.OPTelemetryService.LocalBinder;
|
||||
@ -76,105 +79,22 @@ public abstract class ObjectManagerActivity extends Activity {
|
||||
BroadcastReceiver connectedReceiver;
|
||||
//! Indicate if this activity has already connected it's telemetry callbacks
|
||||
private boolean telemetryStatsConnected = false;
|
||||
|
||||
//! Maintain a list of all the UAVObject listeners for this activity
|
||||
private HashMap<Observer, UAVObject> listeners;
|
||||
/** Called when the activity is first created. */
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
connectedReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (DEBUG)
|
||||
Log.d(TAG, "Received intent");
|
||||
TelemTask task;
|
||||
if(intent.getAction().compareTo(OPTelemetryService.INTENT_ACTION_CONNECTED) == 0) {
|
||||
if(binder == null)
|
||||
return;
|
||||
if((task = binder.getTelemTask(0)) == null)
|
||||
return;
|
||||
objMngr = task.getObjectManager();
|
||||
mConnected = true;
|
||||
onOPConnected();
|
||||
Log.d(TAG, "Connected()");
|
||||
} else if (intent.getAction().compareTo(OPTelemetryService.INTENT_ACTION_DISCONNECTED) == 0) {
|
||||
objMngr = null;
|
||||
mConnected = false;
|
||||
onOPDisconnected();
|
||||
Log.d(TAG, "Disonnected()");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addCategory(OPTelemetryService.INTENT_CATEGORY_GCS);
|
||||
filter.addAction(OPTelemetryService.INTENT_ACTION_CONNECTED);
|
||||
filter.addAction(OPTelemetryService.INTENT_ACTION_DISCONNECTED);
|
||||
registerReceiver(connectedReceiver, filter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called whenever any objects subscribed to via registerObjects
|
||||
* whenever this Activity is not paused
|
||||
*/
|
||||
protected void objectUpdated(UAVObject obj) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* A message handler and a custom Observer to use it which calls
|
||||
* objectUpdated with the right object type
|
||||
*/
|
||||
final Handler uavobjHandler = new Handler();
|
||||
private class ActivityUpdatedObserver implements Observer {
|
||||
UAVObject obj;
|
||||
ActivityUpdatedObserver(UAVObject obj) { this.obj = obj; };
|
||||
@Override
|
||||
public void update(Observable observable, Object data) {
|
||||
uavobjHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() { objectUpdated(obj); }
|
||||
});
|
||||
}
|
||||
};
|
||||
private class FragmentUpdatedObserver implements Observer {
|
||||
UAVObject obj;
|
||||
ObjectManagerFragment frag;
|
||||
FragmentUpdatedObserver(UAVObject obj, ObjectManagerFragment frag) {
|
||||
this.obj = obj;
|
||||
this.frag = frag;
|
||||
};
|
||||
@Override
|
||||
public void update(Observable observable, Object data) {
|
||||
uavobjHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() { frag.objectUpdated(obj); }
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Register an activity to receive updates from this object
|
||||
*
|
||||
* the objectUpdated() method will be called in the original UI thread
|
||||
*/
|
||||
protected void registerObjectUpdates(UAVObject object) {
|
||||
object.addUpdatedObserver(new ActivityUpdatedObserver(object));
|
||||
}
|
||||
|
||||
public void registerObjectUpdates(UAVObject object,
|
||||
ObjectManagerFragment frag) {
|
||||
object.addUpdatedObserver(new FragmentUpdatedObserver(object, frag));
|
||||
}
|
||||
protected void registerObjectUpdates(List<List<UAVObject>> objects) {
|
||||
ListIterator<List<UAVObject>> li = objects.listIterator();
|
||||
while(li.hasNext()) {
|
||||
ListIterator<UAVObject> li2 = li.next().listIterator();
|
||||
while(li2.hasNext())
|
||||
registerObjectUpdates(li2.next());
|
||||
}
|
||||
}
|
||||
|
||||
private void updateStats() {
|
||||
UAVObject stats = objMngr.getObject("GCSTelemetryStats");
|
||||
TextView rxRate = (TextView) findViewById(R.id.telemetry_stats_rx_rate);
|
||||
@ -208,14 +128,21 @@ public abstract class ObjectManagerActivity extends Activity {
|
||||
if ( telemetryStatsConnected )
|
||||
return;
|
||||
|
||||
// Create a map for all the object updates register for this activity. If anyone
|
||||
// tries to register an object update before this a null exception will occur
|
||||
listeners = new HashMap<Observer,UAVObject>();
|
||||
|
||||
// We are not using the objectUpdated mechanism in place so that all the children
|
||||
// don't have to sort through the messages.
|
||||
UAVObject stats = objMngr.getObject("GCSTelemetryStats");
|
||||
if (stats == null)
|
||||
return;
|
||||
|
||||
stats.addUpdatedObserver(telemetryObserver);
|
||||
telemetryStatsConnected = true;
|
||||
if (!telemetryStatsConnected) {
|
||||
UAVObject stats = objMngr.getObject("GCSTelemetryStats");
|
||||
if (stats == null)
|
||||
return;
|
||||
|
||||
stats.addUpdatedObserver(telemetryObserver);
|
||||
telemetryStatsConnected = true;
|
||||
}
|
||||
updateStats();
|
||||
|
||||
if (DEBUG) Log.d(TAG, "Notifying listeners about connection. There are " + connectionListeners.countObservers());
|
||||
@ -236,46 +163,103 @@ public abstract class ObjectManagerActivity extends Activity {
|
||||
|
||||
// Providing a null update triggers a disconnect on fragments
|
||||
connectionListeners.disconnected();
|
||||
|
||||
if (objMngr == null) {
|
||||
Log.d(TAG, "onOPDisconnected(): Object manager already went away");
|
||||
return;
|
||||
}
|
||||
|
||||
if (telemetryStatsConnected) {
|
||||
UAVObject stats = objMngr.getObject("GCSTelemetryStats");
|
||||
if (stats != null) {
|
||||
stats.removeUpdatedObserver(telemetryObserver);
|
||||
}
|
||||
telemetryStatsConnected = false;
|
||||
}
|
||||
|
||||
// Disconnect from any UAVO updates
|
||||
if (DEBUG) Log.d(TAG, "onOpDisconnected(): Pausing the listeners and deleting the list");
|
||||
pauseObjectUpdates();
|
||||
listeners = null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
if (mConnected && !telemetryStatsConnected) {
|
||||
UAVObject stats = objMngr.getObject("GCSTelemetryStats");
|
||||
if (stats == null)
|
||||
return;
|
||||
|
||||
stats.addUpdatedObserver(telemetryObserver);
|
||||
telemetryStatsConnected = true;
|
||||
}
|
||||
|
||||
resumeObjectUpdates();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if (!mBound || binder == null) {
|
||||
Log.e(TAG, "Unable to connect to service");
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
switch(item.getItemId()) {
|
||||
case R.id.menu_connect:
|
||||
binder.openConnection();
|
||||
return true;
|
||||
case R.id.menu_disconnect:
|
||||
binder.stopConnection();
|
||||
return true;
|
||||
case R.id.menu_settings:
|
||||
startActivity(new Intent(this, Preferences.class));
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
|
||||
if (telemetryStatsConnected) {
|
||||
UAVObject stats = objMngr.getObject("GCSTelemetryStats");
|
||||
Assert.assertNotNull(stats); // Should not be null if we connected
|
||||
|
||||
stats.removeUpdatedObserver(telemetryObserver);
|
||||
telemetryStatsConnected = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
MenuInflater inflater = getMenuInflater();
|
||||
inflater.inflate(R.menu.status_menu, menu);
|
||||
inflater.inflate(R.menu.options_menu, menu);
|
||||
return true;
|
||||
pauseObjectUpdates();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
if (DEBUG) Log.d(TAG, "onStart()");
|
||||
|
||||
// Register a receiver to get connected/disconnected signals from the telemetry
|
||||
// service
|
||||
connectedReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (DEBUG)
|
||||
Log.d(TAG, "Received intent");
|
||||
TelemTask task;
|
||||
if(intent.getAction().compareTo(OPTelemetryService.INTENT_ACTION_CONNECTED) == 0) {
|
||||
if(binder == null)
|
||||
return;
|
||||
if((task = binder.getTelemTask(0)) == null)
|
||||
return;
|
||||
objMngr = task.getObjectManager();
|
||||
mConnected = true;
|
||||
onOPConnected();
|
||||
Log.d(TAG, "Connected()");
|
||||
} else if (intent.getAction().compareTo(OPTelemetryService.INTENT_ACTION_DISCONNECTED) == 0) {
|
||||
onOPDisconnected();
|
||||
objMngr = null;
|
||||
mConnected = false;
|
||||
Log.d(TAG, "Disonnected()");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Set up the filters
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addCategory(OPTelemetryService.INTENT_CATEGORY_GCS);
|
||||
filter.addAction(OPTelemetryService.INTENT_ACTION_CONNECTED);
|
||||
filter.addAction(OPTelemetryService.INTENT_ACTION_DISCONNECTED);
|
||||
registerReceiver(connectedReceiver, filter);
|
||||
|
||||
// Bind to the telemetry service (which will start it)
|
||||
Intent intent = new Intent(getApplicationContext(),
|
||||
org.openpilot.androidgcs.telemetry.OPTelemetryService.class);
|
||||
if (DEBUG)
|
||||
Log.d(TAG, "Attempting to bind: " + intent);
|
||||
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -284,14 +268,137 @@ public abstract class ObjectManagerActivity extends Activity {
|
||||
@Override
|
||||
public void onStop() {
|
||||
super.onStop();
|
||||
if (DEBUG) Log.d(TAG, "onStop()");
|
||||
unbindService(mConnection);
|
||||
//unregisterReceiver(connectedReceiver);
|
||||
unregisterReceiver(connectedReceiver);
|
||||
connectedReceiver = null;
|
||||
|
||||
// Disconnect from any UAVO updates
|
||||
if (DEBUG) Log.d(TAG, "onStop(): Pausing the listeners and deleting the list");
|
||||
pauseObjectUpdates();
|
||||
listeners = null;
|
||||
}
|
||||
|
||||
public void onBind() {
|
||||
/*********** This provides the object update messaging service ************/
|
||||
|
||||
/**
|
||||
* A message handler and a custom Observer to use it which calls
|
||||
* objectUpdated with the right object type
|
||||
*/
|
||||
final Handler uavobjHandler = new Handler();
|
||||
private class ActivityUpdatedObserver implements Observer {
|
||||
UAVObject obj;
|
||||
ActivityUpdatedObserver(UAVObject obj) { this.obj = obj; };
|
||||
@Override
|
||||
public void update(Observable observable, Object data) {
|
||||
uavobjHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() { objectUpdated(obj); }
|
||||
});
|
||||
}
|
||||
};
|
||||
private class FragmentUpdatedObserver implements Observer {
|
||||
UAVObject obj;
|
||||
ObjectManagerFragment frag;
|
||||
FragmentUpdatedObserver(UAVObject obj, ObjectManagerFragment frag) {
|
||||
this.obj = obj;
|
||||
this.frag = frag;
|
||||
};
|
||||
@Override
|
||||
public void update(Observable observable, Object data) {
|
||||
uavobjHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() { frag.objectUpdated(obj); }
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Unregister all the objects connected to this activity
|
||||
*/
|
||||
private boolean paused = false;
|
||||
|
||||
/**
|
||||
* When an activity is paused, disconnect from all
|
||||
* updates to ensure we don't draw to an invalid view
|
||||
*/
|
||||
protected void pauseObjectUpdates()
|
||||
{
|
||||
// When listeners is null then a pause occurred after
|
||||
// disconnecting from the service
|
||||
if (listeners == null)
|
||||
return;
|
||||
|
||||
Set<Observer> s = listeners.keySet();
|
||||
Iterator<Observer> i = s.iterator();
|
||||
while (i.hasNext()) {
|
||||
Observer o = i.next();
|
||||
UAVObject obj = listeners.get(o);
|
||||
obj.removeUpdatedObserver(o);
|
||||
}
|
||||
paused = true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* When an activity is resumed, reconnect all now the view
|
||||
* is valid again
|
||||
*/
|
||||
protected void resumeObjectUpdates()
|
||||
{
|
||||
// When listeners is null this is the resume at the beginning
|
||||
// before connecting to the telemetry service
|
||||
if(listeners == null)
|
||||
return;
|
||||
|
||||
Set<Observer> s = listeners.keySet();
|
||||
Iterator<Observer> i = s.iterator();
|
||||
while (i.hasNext()) {
|
||||
Observer o = i.next();
|
||||
UAVObject obj = listeners.get(o);
|
||||
obj.addUpdatedObserver(o);
|
||||
}
|
||||
paused = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register to listen to a single object from a fragment
|
||||
* @param object The object to listen to updates from
|
||||
* @param frag The fragment who should be notified
|
||||
* the objectUpdated() method will be called in the original UI thread
|
||||
*/
|
||||
public void registerObjectUpdates(UAVObject object,
|
||||
ObjectManagerFragment frag) {
|
||||
Observer o = new FragmentUpdatedObserver(object, frag);
|
||||
listeners.put(o, object);
|
||||
if (!paused)
|
||||
object.addUpdatedObserver(o);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register an activity to receive updates from this object
|
||||
* @param object The object the activity should listen to updates from
|
||||
* the objectUpdated() method will be called in the original UI thread
|
||||
*/
|
||||
protected void registerObjectUpdates(UAVObject object) {
|
||||
Observer o = new ActivityUpdatedObserver(object);
|
||||
listeners.put(o, object);
|
||||
if (!paused)
|
||||
object.addUpdatedObserver(o);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to register array of objects
|
||||
*/
|
||||
protected void registerObjectUpdates(List<List<UAVObject>> objects) {
|
||||
for (int i = 0; i < objects.size(); i++) {
|
||||
List<UAVObject> inner = objects.get(i);
|
||||
for (int j = 0; j < inner.size(); j++)
|
||||
registerObjectUpdates(inner.get(j));
|
||||
}
|
||||
}
|
||||
|
||||
/*********** Deals with fragments listening for connections ***************/
|
||||
|
||||
/**
|
||||
* Callbacks so ObjectManagerFragments get the onOPConnected and onOPDisconnected signals
|
||||
@ -328,7 +435,6 @@ public abstract class ObjectManagerActivity extends Activity {
|
||||
}
|
||||
|
||||
} ;
|
||||
|
||||
public void addOnConnectionListenerFragment(ObjectManagerFragment frag) {
|
||||
connectionListeners.addObserver(new OnConnectionListener(frag));
|
||||
if (DEBUG) Log.d(TAG, "Connecting " + frag + " there are now " + connectionListeners.countObservers());
|
||||
@ -337,6 +443,8 @@ public abstract class ObjectManagerActivity extends Activity {
|
||||
}
|
||||
|
||||
|
||||
/*********** Deals with (dis)connection to telemetry service ***************/
|
||||
|
||||
/** Defines callbacks for service binding, passed to bindService() */
|
||||
private final ServiceConnection mConnection = new ServiceConnection() {
|
||||
@Override
|
||||
@ -359,13 +467,45 @@ public abstract class ObjectManagerActivity extends Activity {
|
||||
|
||||
@Override
|
||||
public void onServiceDisconnected(ComponentName name) {
|
||||
onOPDisconnected();
|
||||
mBound = false;
|
||||
binder = null;
|
||||
mConnected = false;
|
||||
objMngr = null;
|
||||
objMngr = null;
|
||||
mConnected = false;
|
||||
onOPDisconnected();
|
||||
}
|
||||
};
|
||||
|
||||
/************* Deals with menus *****************/
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if (!mBound || binder == null) {
|
||||
Log.e(TAG, "Unable to connect to service");
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
switch(item.getItemId()) {
|
||||
case R.id.menu_connect:
|
||||
binder.openConnection();
|
||||
return true;
|
||||
case R.id.menu_disconnect:
|
||||
binder.stopConnection();
|
||||
return true;
|
||||
case R.id.menu_settings:
|
||||
startActivity(new Intent(this, Preferences.class));
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
MenuInflater inflater = getMenuInflater();
|
||||
inflater.inflate(R.menu.status_menu, menu);
|
||||
inflater.inflate(R.menu.options_menu, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -23,14 +23,18 @@
|
||||
|
||||
package org.openpilot.androidgcs;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Observable;
|
||||
import java.util.Observer;
|
||||
import java.util.Set;
|
||||
|
||||
import org.openpilot.androidgcs.fragments.ObjectManagerFragment;
|
||||
import org.openpilot.androidgcs.telemetry.OPTelemetryService;
|
||||
import org.openpilot.androidgcs.telemetry.OPTelemetryService.LocalBinder;
|
||||
import org.openpilot.androidgcs.telemetry.OPTelemetryService.TelemTask;
|
||||
import org.openpilot.uavtalk.UAVDataObject;
|
||||
import org.openpilot.uavtalk.UAVObject;
|
||||
import org.openpilot.uavtalk.UAVObjectManager;
|
||||
|
||||
@ -46,6 +50,7 @@ import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Point;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
@ -73,6 +78,7 @@ public class UAVLocation extends MapActivity
|
||||
UAVObjectManager objMngr;
|
||||
boolean mBound = false;
|
||||
boolean mConnected = false;
|
||||
BroadcastReceiver connectedReceiver;
|
||||
org.openpilot.androidgcs.telemetry.OPTelemetryService.LocalBinder binder;
|
||||
|
||||
GeoPoint homeLocation;
|
||||
@ -103,36 +109,6 @@ public class UAVLocation extends MapActivity
|
||||
|
||||
mapView.postInvalidate();
|
||||
|
||||
// ObjectManager related stuff (can't inherit standard class)
|
||||
BroadcastReceiver connectedReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
Log.d(TAG, "Received intent");
|
||||
TelemTask task;
|
||||
if(intent.getAction().compareTo(OPTelemetryService.INTENT_ACTION_CONNECTED) == 0) {
|
||||
|
||||
if(binder == null)
|
||||
return;
|
||||
if((task = binder.getTelemTask(0)) == null)
|
||||
return;
|
||||
objMngr = task.getObjectManager();
|
||||
mConnected = true;
|
||||
onOPConnected();
|
||||
Log.d(TAG, "Connected()");
|
||||
} else if (intent.getAction().compareTo(OPTelemetryService.INTENT_ACTION_DISCONNECTED) == 0) {
|
||||
objMngr = null;
|
||||
mConnected = false;
|
||||
onOPDisconnected();
|
||||
Log.d(TAG, "Disonnected()");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addCategory(OPTelemetryService.INTENT_CATEGORY_GCS);
|
||||
filter.addAction(OPTelemetryService.INTENT_ACTION_CONNECTED);
|
||||
filter.addAction(OPTelemetryService.INTENT_ACTION_DISCONNECTED);
|
||||
registerReceiver(connectedReceiver, filter);
|
||||
}
|
||||
|
||||
//@Override
|
||||
@ -192,40 +168,10 @@ public class UAVLocation extends MapActivity
|
||||
|
||||
void onOPConnected() {
|
||||
UAVObject obj = objMngr.getObject("HomeLocation");
|
||||
if(obj != null)
|
||||
obj.addUpdatedObserver(new Observer() {
|
||||
@Override
|
||||
public void update(Observable observable, Object data) {
|
||||
UAVDataObject obj = (UAVDataObject) data;
|
||||
Double lat = obj.getField("Latitude").getDouble() / 10;
|
||||
Double lon = obj.getField("Longitude").getDouble() / 10;
|
||||
homeLocation = new GeoPoint(lat.intValue(), lon.intValue());
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mapController.setCenter(homeLocation);
|
||||
}
|
||||
});
|
||||
System.out.println("HomeLocation: " + homeLocation.toString());
|
||||
}
|
||||
});
|
||||
obj.updateRequested();
|
||||
registerObjectUpdates(obj);
|
||||
|
||||
obj = objMngr.getObject("PositionActual");
|
||||
if(obj != null)
|
||||
obj.addUpdatedObserver(new Observer() {
|
||||
@Override
|
||||
public void update(Observable observable, Object data) {
|
||||
uavLocation = getUavLocation();
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mapView.invalidate();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
registerObjectUpdates(obj);
|
||||
}
|
||||
|
||||
private GeoPoint getUavLocation() {
|
||||
@ -260,7 +206,7 @@ public class UAVLocation extends MapActivity
|
||||
}
|
||||
|
||||
void onOPDisconnected() {
|
||||
|
||||
unregisterObjectUpdates();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -291,10 +237,56 @@ public class UAVLocation extends MapActivity
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
// ObjectManager related stuff (can't inherit standard class)
|
||||
connectedReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
Log.d(TAG, "Received intent");
|
||||
TelemTask task;
|
||||
if(intent.getAction().compareTo(OPTelemetryService.INTENT_ACTION_CONNECTED) == 0) {
|
||||
|
||||
if(binder == null)
|
||||
return;
|
||||
if((task = binder.getTelemTask(0)) == null)
|
||||
return;
|
||||
objMngr = task.getObjectManager();
|
||||
mConnected = true;
|
||||
onOPConnected();
|
||||
Log.d(TAG, "Connected()");
|
||||
} else if (intent.getAction().compareTo(OPTelemetryService.INTENT_ACTION_DISCONNECTED) == 0) {
|
||||
objMngr = null;
|
||||
mConnected = false;
|
||||
onOPDisconnected();
|
||||
Log.d(TAG, "Disonnected()");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addCategory(OPTelemetryService.INTENT_CATEGORY_GCS);
|
||||
filter.addAction(OPTelemetryService.INTENT_ACTION_CONNECTED);
|
||||
filter.addAction(OPTelemetryService.INTENT_ACTION_DISCONNECTED);
|
||||
registerReceiver(connectedReceiver, filter);
|
||||
|
||||
Intent intent = new Intent(this, OPTelemetryService.class);
|
||||
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
|
||||
}
|
||||
|
||||
/**
|
||||
* When stopping disconnect form the service and the broadcast receiver
|
||||
*/
|
||||
@Override
|
||||
public void onStop() {
|
||||
super.onStop();
|
||||
if (DEBUG) Log.d(TAG, "onStop()");
|
||||
unbindService(mConnection);
|
||||
unregisterReceiver(connectedReceiver);
|
||||
connectedReceiver = null;
|
||||
|
||||
// TODO: The register and unregister probably should move to onPause / onResume
|
||||
unregisterObjectUpdates();
|
||||
}
|
||||
|
||||
public void onBind() {
|
||||
|
||||
}
|
||||
@ -330,4 +322,96 @@ public class UAVLocation extends MapActivity
|
||||
onOPDisconnected();
|
||||
}
|
||||
};
|
||||
|
||||
/******* STRAIGHT COPY PASTE FROM ObjectManagerActivity *************/
|
||||
/**
|
||||
* Called whenever any objects subscribed to via registerObjects
|
||||
*/
|
||||
protected void objectUpdated(UAVObject obj) {
|
||||
if (obj == null)
|
||||
return;
|
||||
if (obj.getName().compareTo("HomeLocation") == 0) {
|
||||
Double lat = obj.getField("Latitude").getDouble() / 10;
|
||||
Double lon = obj.getField("Longitude").getDouble() / 10;
|
||||
homeLocation = new GeoPoint(lat.intValue(), lon.intValue());
|
||||
mapController.setCenter(homeLocation);
|
||||
} else if (obj.getName().compareTo("PositionActual") == 0) {
|
||||
uavLocation = getUavLocation();
|
||||
mapView.invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A message handler and a custom Observer to use it which calls
|
||||
* objectUpdated with the right object type
|
||||
*/
|
||||
final Handler uavobjHandler = new Handler();
|
||||
private class ActivityUpdatedObserver implements Observer {
|
||||
UAVObject obj;
|
||||
ActivityUpdatedObserver(UAVObject obj) { this.obj = obj; };
|
||||
@Override
|
||||
public void update(Observable observable, Object data) {
|
||||
uavobjHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() { objectUpdated(obj); }
|
||||
});
|
||||
}
|
||||
};
|
||||
private class FragmentUpdatedObserver implements Observer {
|
||||
UAVObject obj;
|
||||
ObjectManagerFragment frag;
|
||||
FragmentUpdatedObserver(UAVObject obj, ObjectManagerFragment frag) {
|
||||
this.obj = obj;
|
||||
this.frag = frag;
|
||||
};
|
||||
@Override
|
||||
public void update(Observable observable, Object data) {
|
||||
uavobjHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() { frag.objectUpdated(obj); }
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Register an activity to receive updates from this object
|
||||
*
|
||||
* the objectUpdated() method will be called in the original UI thread
|
||||
*/
|
||||
HashMap<Observer, UAVObject> listeners = new HashMap<Observer,UAVObject>();
|
||||
protected void registerObjectUpdates(UAVObject object) {
|
||||
Observer o = new ActivityUpdatedObserver(object);
|
||||
object.addUpdatedObserver(o);
|
||||
listeners.put(o, object);
|
||||
}
|
||||
/**
|
||||
* Unregister all the objects connected to this activity
|
||||
*/
|
||||
protected void unregisterObjectUpdates()
|
||||
{
|
||||
Set<Observer> s = listeners.keySet();
|
||||
Iterator<Observer> i = s.iterator();
|
||||
while (i.hasNext()) {
|
||||
Observer o = i.next();
|
||||
UAVObject obj = listeners.get(o);
|
||||
obj.removeUpdatedObserver(o);
|
||||
}
|
||||
listeners.clear();
|
||||
}
|
||||
public void registerObjectUpdates(UAVObject object,
|
||||
ObjectManagerFragment frag) {
|
||||
Observer o = new FragmentUpdatedObserver(object, frag);
|
||||
object.addUpdatedObserver(o);
|
||||
listeners.put(o, object);
|
||||
}
|
||||
protected void registerObjectUpdates(List<List<UAVObject>> objects) {
|
||||
ListIterator<List<UAVObject>> li = objects.listIterator();
|
||||
while(li.hasNext()) {
|
||||
ListIterator<UAVObject> li2 = li.next().listIterator();
|
||||
while(li2.hasNext())
|
||||
registerObjectUpdates(li2.next());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ import org.openpilot.uavtalk.UAVObject;
|
||||
import org.openpilot.uavtalk.UAVObjectField;
|
||||
import org.openpilot.uavtalk.UAVObjectManager;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
@ -72,7 +73,16 @@ public class SystemAlarmsFragment extends ObjectManagerFragment {
|
||||
if (DEBUG)
|
||||
Log.d(TAG, "Updated");
|
||||
if (obj.getName().compareTo("SystemAlarms") == 0) {
|
||||
Activity activity = getActivity();
|
||||
if (activity == null) {
|
||||
// TODO: Need to unregister all the callbacks
|
||||
return;
|
||||
}
|
||||
TextView alarms = (TextView) getActivity().findViewById(R.id.system_alarms_fragment_field);
|
||||
if (alarms == null) {
|
||||
// TODO: Need to figure out how to unregister all the callbacks
|
||||
return;
|
||||
}
|
||||
UAVObjectField a = obj.getField("Alarm");
|
||||
List<String> names = a.getElementNames();
|
||||
String contents = new String();
|
||||
|
@ -27,6 +27,7 @@
|
||||
package org.openpilot.androidgcs.telemetry;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Observable;
|
||||
import java.util.Observer;
|
||||
|
||||
@ -83,75 +84,85 @@ public class OPTelemetryService extends Service {
|
||||
|
||||
private final IBinder mBinder = new LocalBinder();
|
||||
|
||||
private final class ServiceHandler extends Handler {
|
||||
public ServiceHandler(Looper looper) {
|
||||
super(looper);
|
||||
}
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
if (DEBUG)
|
||||
Log.d(TAG, "handleMessage: " + msg);
|
||||
switch(msg.arg1) {
|
||||
case MSG_START:
|
||||
stopSelf(msg.arg2);
|
||||
break;
|
||||
case MSG_CONNECT:
|
||||
terminate = false;
|
||||
int connection_type;
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(OPTelemetryService.this);
|
||||
try {
|
||||
connection_type = Integer.decode(prefs.getString("connection_type", ""));
|
||||
} catch (NumberFormatException e) {
|
||||
connection_type = 0;
|
||||
}
|
||||
static class ServiceHandler extends Handler {
|
||||
private final WeakReference<OPTelemetryService> mService;
|
||||
|
||||
switch(connection_type) {
|
||||
case 0: // No connection
|
||||
return;
|
||||
case 1:
|
||||
Toast.makeText(getApplicationContext(), "Attempting fake connection", Toast.LENGTH_SHORT).show();
|
||||
activeTelem = new FakeTelemetryThread();
|
||||
break;
|
||||
case 2:
|
||||
Toast.makeText(getApplicationContext(), "Attempting BT connection", Toast.LENGTH_SHORT).show();
|
||||
activeTelem = new BTTelemetryThread();
|
||||
break;
|
||||
case 3:
|
||||
Toast.makeText(getApplicationContext(), "Attempting TCP connection", Toast.LENGTH_SHORT).show();
|
||||
activeTelem = new TcpTelemetryThread();
|
||||
break;
|
||||
default:
|
||||
throw new Error("Unsupported");
|
||||
}
|
||||
activeTelem.start();
|
||||
break;
|
||||
case MSG_DISCONNECT:
|
||||
Toast.makeText(getApplicationContext(), "Disconnect requested", Toast.LENGTH_SHORT).show();
|
||||
terminate = true;
|
||||
activeTelem.interrupt();
|
||||
try {
|
||||
activeTelem.join();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
activeTelem = null;
|
||||
ServiceHandler(OPTelemetryService service, Looper looper) {
|
||||
super(looper);
|
||||
mService = new WeakReference<OPTelemetryService>(service);
|
||||
}
|
||||
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(INTENT_ACTION_DISCONNECTED);
|
||||
sendBroadcast(intent,null);
|
||||
@Override
|
||||
public void handleMessage(Message msg)
|
||||
{
|
||||
OPTelemetryService service = mService.get();
|
||||
if (service != null) {
|
||||
service.handleMessage(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stopSelf();
|
||||
|
||||
break;
|
||||
case MSG_TOAST:
|
||||
Toast.makeText(OPTelemetryService.this, (String) msg.obj, Toast.LENGTH_SHORT).show();
|
||||
break;
|
||||
default:
|
||||
System.out.println(msg.toString());
|
||||
throw new Error("Invalid message");
|
||||
void handleMessage(Message msg) {
|
||||
switch(msg.arg1) {
|
||||
case MSG_START:
|
||||
stopSelf(msg.arg2);
|
||||
break;
|
||||
case MSG_CONNECT:
|
||||
terminate = false;
|
||||
int connection_type;
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(OPTelemetryService.this);
|
||||
try {
|
||||
connection_type = Integer.decode(prefs.getString("connection_type", ""));
|
||||
} catch (NumberFormatException e) {
|
||||
connection_type = 0;
|
||||
}
|
||||
|
||||
switch(connection_type) {
|
||||
case 0: // No connection
|
||||
return;
|
||||
case 1:
|
||||
Toast.makeText(getApplicationContext(), "Attempting fake connection", Toast.LENGTH_SHORT).show();
|
||||
activeTelem = new FakeTelemetryThread();
|
||||
break;
|
||||
case 2:
|
||||
Toast.makeText(getApplicationContext(), "Attempting BT connection", Toast.LENGTH_SHORT).show();
|
||||
activeTelem = new BTTelemetryThread();
|
||||
break;
|
||||
case 3:
|
||||
Toast.makeText(getApplicationContext(), "Attempting TCP connection", Toast.LENGTH_SHORT).show();
|
||||
activeTelem = new TcpTelemetryThread();
|
||||
break;
|
||||
default:
|
||||
throw new Error("Unsupported");
|
||||
}
|
||||
activeTelem.start();
|
||||
break;
|
||||
case MSG_DISCONNECT:
|
||||
Toast.makeText(getApplicationContext(), "Disconnect requested", Toast.LENGTH_SHORT).show();
|
||||
terminate = true;
|
||||
activeTelem.interrupt();
|
||||
try {
|
||||
activeTelem.join();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
activeTelem = null;
|
||||
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(INTENT_ACTION_DISCONNECTED);
|
||||
sendBroadcast(intent,null);
|
||||
|
||||
stopSelf();
|
||||
|
||||
break;
|
||||
case MSG_TOAST:
|
||||
Toast.makeText(this, (String) msg.obj, Toast.LENGTH_SHORT).show();
|
||||
break;
|
||||
default:
|
||||
System.out.println(msg.toString());
|
||||
throw new Error("Invalid message");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the service starts. It creates a thread to handle messages (e.g. connect and disconnect)
|
||||
@ -160,15 +171,12 @@ public class OPTelemetryService extends Service {
|
||||
public void startup() {
|
||||
Toast.makeText(getApplicationContext(), "Telemetry service starting", Toast.LENGTH_SHORT).show();
|
||||
|
||||
if (DEBUG)
|
||||
Log.d(TAG, "startup()");
|
||||
|
||||
thread = new HandlerThread("TelemetryServiceHandler", Process.THREAD_PRIORITY_BACKGROUND);
|
||||
thread.start();
|
||||
|
||||
// Get the HandlerThread's Looper and use it for our Handler
|
||||
mServiceLooper = thread.getLooper();
|
||||
mServiceHandler = new ServiceHandler(mServiceLooper);
|
||||
mServiceHandler = new ServiceHandler(this, mServiceLooper);
|
||||
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(OPTelemetryService.this);
|
||||
if(prefs.getBoolean("autoconnect", false)) {
|
||||
@ -190,16 +198,13 @@ public class OPTelemetryService extends Service {
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
// Currently only using as bound service
|
||||
if (DEBUG)
|
||||
Log.d(TAG, "onStartCommand()");
|
||||
|
||||
// If we get killed, after returning from here, restart
|
||||
return START_STICKY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
if (DEBUG)
|
||||
Log.d(TAG, "onBind()");
|
||||
return mBinder;
|
||||
}
|
||||
|
||||
@ -360,7 +365,7 @@ public class OPTelemetryService extends Service {
|
||||
mon.addObserver(new Observer() {
|
||||
@Override
|
||||
public void update(Observable arg0, Object arg1) {
|
||||
System.out.println("Mon updated. Connected: " + mon.getConnected() + " objects updated: " + mon.getObjectsUpdated());
|
||||
if (DEBUG) Log.d(TAG, "Mon updated. Connected: " + mon.getConnected() + " objects updated: " + mon.getObjectsUpdated());
|
||||
if(mon.getConnected() /*&& mon.getObjectsUpdated()*/) {
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(INTENT_ACTION_CONNECTED);
|
||||
@ -439,8 +444,8 @@ public class OPTelemetryService extends Service {
|
||||
mon.addObserver(new Observer() {
|
||||
@Override
|
||||
public void update(Observable arg0, Object arg1) {
|
||||
System.out.println("Mon updated. Connected: " + mon.getConnected() + " objects updated: " + mon.getObjectsUpdated());
|
||||
if(mon.getConnected() /*&& mon.getObjectsUpdated()*/) {
|
||||
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);
|
||||
|
@ -87,9 +87,9 @@ public class Telemetry {
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public Telemetry(UAVTalk utalk, UAVObjectManager objMngr)
|
||||
public Telemetry(UAVTalk utalkIn, UAVObjectManager objMngr)
|
||||
{
|
||||
this.utalk = utalk;
|
||||
this.utalk = utalkIn;
|
||||
this.objMngr = objMngr;
|
||||
|
||||
// Process all objects in the list
|
||||
@ -113,16 +113,28 @@ public class Telemetry {
|
||||
});
|
||||
|
||||
// Listen to transaction completions
|
||||
utalk.addObserver(new Observer() {
|
||||
this.utalk.setOnTransactionCompletedListener(
|
||||
this.utalk.new OnTransactionCompletedListener() {
|
||||
@Override
|
||||
public void update(Observable observable, Object data) {
|
||||
try {
|
||||
transactionCompleted((UAVObject) data);
|
||||
void TransactionSucceeded(UAVObject data) {
|
||||
try {
|
||||
transactionCompleted(data);
|
||||
} catch (IOException e) {
|
||||
// Disconnect when stream fails
|
||||
observable.deleteObserver(this);
|
||||
utalk.setOnTransactionCompletedListener(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@Override
|
||||
void TransactionFailed(UAVObject data) {
|
||||
try {
|
||||
Log.d(TAG, "TransactionFailed(" + data.getName() + ")");
|
||||
transactionCompleted(data);
|
||||
} catch (IOException e) {
|
||||
// Disconnect when stream fails
|
||||
utalk.setOnTransactionCompletedListener(null);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
// Get GCS stats object
|
||||
@ -475,7 +487,6 @@ public class Telemetry {
|
||||
++txErrors;
|
||||
obj.transactionCompleted(false);
|
||||
Log.w(TAG,"Telemetry: priority event queue is full, event lost " + obj.getName());
|
||||
new Exception().printStackTrace();
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -36,20 +36,20 @@ import java.util.TimerTask;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
public class TelemetryMonitor extends Observable{
|
||||
public class TelemetryMonitor extends Observable {
|
||||
|
||||
private static final String TAG = "TelemetryMonitor";
|
||||
public static int LOGLEVEL = 0;
|
||||
public static boolean WARN = LOGLEVEL > 1;
|
||||
public static boolean DEBUG = LOGLEVEL > 0;
|
||||
|
||||
static final int STATS_UPDATE_PERIOD_MS = 4000;
|
||||
static final int STATS_CONNECT_PERIOD_MS = 1000;
|
||||
static final int CONNECTION_TIMEOUT_MS = 8000;
|
||||
static final int STATS_UPDATE_PERIOD_MS = 4000;
|
||||
static final int STATS_CONNECT_PERIOD_MS = 1000;
|
||||
static final int CONNECTION_TIMEOUT_MS = 8000;
|
||||
|
||||
private final UAVObjectManager objMngr;
|
||||
private final Telemetry tel;
|
||||
// private UAVObject objPending;
|
||||
// private UAVObject objPending;
|
||||
private UAVObject gcsStatsObj;
|
||||
private UAVObject flightStatsObj;
|
||||
private Timer periodicTask;
|
||||
@ -60,324 +60,333 @@ public class TelemetryMonitor extends Observable{
|
||||
private boolean connected = false;
|
||||
private boolean objects_updated = false;
|
||||
|
||||
public boolean getConnected() { return connected; };
|
||||
public boolean getObjectsUpdated() { return objects_updated; };
|
||||
public boolean getConnected() {
|
||||
return connected;
|
||||
};
|
||||
|
||||
public TelemetryMonitor(UAVObjectManager objMngr, Telemetry tel)
|
||||
{
|
||||
this.objMngr = objMngr;
|
||||
this.tel = tel;
|
||||
// this.objPending = null;
|
||||
queue = new ArrayList<UAVObject>();
|
||||
public boolean getObjectsUpdated() {
|
||||
return objects_updated;
|
||||
};
|
||||
|
||||
// Get stats objects
|
||||
gcsStatsObj = objMngr.getObject("GCSTelemetryStats");
|
||||
flightStatsObj = objMngr.getObject("FlightTelemetryStats");
|
||||
public TelemetryMonitor(UAVObjectManager objMngr, Telemetry tel) {
|
||||
this.objMngr = objMngr;
|
||||
this.tel = tel;
|
||||
// this.objPending = null;
|
||||
queue = new ArrayList<UAVObject>();
|
||||
|
||||
flightStatsObj.addUpdatedObserver(new Observer() {
|
||||
// Get stats objects
|
||||
gcsStatsObj = objMngr.getObject("GCSTelemetryStats");
|
||||
flightStatsObj = objMngr.getObject("FlightTelemetryStats");
|
||||
|
||||
flightStatsObj.addUpdatedObserver(new Observer() {
|
||||
@Override
|
||||
public void update(Observable observable, Object data) {
|
||||
try {
|
||||
flightStatsUpdated((UAVObject) data);
|
||||
} catch (IOException e) {
|
||||
// The UAVTalk stream was broken, disconnect this signal
|
||||
// TODO: Should this actually be disconnected. Do we create a new TelemetryMonitor for this
|
||||
// TODO: Should this actually be disconnected. Do we create
|
||||
// a new TelemetryMonitor for this
|
||||
// or fix the stream?
|
||||
flightStatsObj.removeUpdatedObserver(this);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Start update timer
|
||||
setPeriod(STATS_CONNECT_PERIOD_MS);
|
||||
// Start update timer
|
||||
setPeriod(STATS_CONNECT_PERIOD_MS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiate object retrieval, initialize queue with objects to be retrieved.
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
public synchronized void startRetrievingObjects() throws IOException
|
||||
{
|
||||
if (DEBUG) Log.d(TAG, "Start retrieving objects");
|
||||
public synchronized void startRetrievingObjects() throws IOException {
|
||||
if (DEBUG)
|
||||
Log.d(TAG, "Start retrieving objects");
|
||||
|
||||
// Clear object queue
|
||||
queue.clear();
|
||||
// Get all objects, add metaobjects, settings and data objects with OnChange update mode to the queue
|
||||
List< List<UAVObject> > objs = objMngr.getObjects();
|
||||
// Clear object queue
|
||||
queue.clear();
|
||||
// Get all objects, add metaobjects, settings and data objects with
|
||||
// OnChange update mode to the queue
|
||||
List<List<UAVObject>> objs = objMngr.getObjects();
|
||||
|
||||
ListIterator<List<UAVObject>> objListIterator = objs.listIterator();
|
||||
while( objListIterator.hasNext() )
|
||||
{
|
||||
List <UAVObject> instList = objListIterator.next();
|
||||
UAVObject obj = instList.get(0);
|
||||
UAVObject.Metadata mdata = obj.getMetadata();
|
||||
if ( obj.isMetadata() )
|
||||
{
|
||||
queue.add(obj);
|
||||
}
|
||||
else /* Data object */
|
||||
{
|
||||
UAVDataObject dobj = (UAVDataObject) obj;
|
||||
if ( dobj.isSettings() )
|
||||
{
|
||||
queue.add(obj);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( mdata.GetFlightTelemetryUpdateMode() == UAVObject.UpdateMode.UPDATEMODE_ONCHANGE )
|
||||
{
|
||||
queue.add(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Start retrieving
|
||||
System.out.println(TAG + "Starting to retrieve meta and settings objects from the autopilot (" + queue.size() + " objects)");
|
||||
retrieveNextObject();
|
||||
ListIterator<List<UAVObject>> objListIterator = objs.listIterator();
|
||||
while (objListIterator.hasNext()) {
|
||||
List<UAVObject> instList = objListIterator.next();
|
||||
UAVObject obj = instList.get(0);
|
||||
UAVObject.Metadata mdata = obj.getMetadata();
|
||||
if (obj.isMetadata()) {
|
||||
queue.add(obj);
|
||||
} else /* Data object */
|
||||
{
|
||||
UAVDataObject dobj = (UAVDataObject) obj;
|
||||
if (dobj.isSettings()) {
|
||||
queue.add(obj);
|
||||
} else {
|
||||
if (mdata.GetFlightTelemetryUpdateMode() == UAVObject.UpdateMode.UPDATEMODE_ONCHANGE) {
|
||||
queue.add(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Start retrieving
|
||||
Log.d(TAG,
|
||||
"Starting to retrieve meta and settings objects from the autopilot ("
|
||||
+ queue.size() + " objects)");
|
||||
retrieveNextObject();
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel the object retrieval
|
||||
*/
|
||||
public void stopRetrievingObjects()
|
||||
{
|
||||
public void stopRetrievingObjects() {
|
||||
Log.d(TAG, "Stop retrieving objects");
|
||||
queue.clear();
|
||||
queue.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the next object in the queue
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
public synchronized void retrieveNextObject() throws IOException
|
||||
{
|
||||
// If queue is empty return
|
||||
if ( queue.isEmpty() )
|
||||
{
|
||||
if (DEBUG) Log.d(TAG, "All objects retrieved: Connected Successfully");
|
||||
objects_updated = true;
|
||||
setChanged();
|
||||
notifyObservers();
|
||||
return;
|
||||
}
|
||||
// Get next object from the queue
|
||||
UAVObject obj = queue.remove(0);
|
||||
public synchronized void retrieveNextObject() throws IOException {
|
||||
// If queue is empty return
|
||||
if (queue.isEmpty()) {
|
||||
if (DEBUG)
|
||||
Log.d(TAG, "All objects retrieved: Connected Successfully");
|
||||
objects_updated = true;
|
||||
setChanged();
|
||||
notifyObservers();
|
||||
return;
|
||||
}
|
||||
// Get next object from the queue
|
||||
UAVObject obj = queue.remove(0);
|
||||
|
||||
if(obj == null) {
|
||||
throw new Error("Got null object forom transaction queue");
|
||||
}
|
||||
if (obj == null) {
|
||||
throw new Error("Got null object forom transaction queue");
|
||||
}
|
||||
|
||||
if (DEBUG) Log.d(TAG, "Retrieving object: " + obj.getName()) ;
|
||||
// Connect to object
|
||||
if (DEBUG)
|
||||
Log.d(TAG, "Retrieving object: " + obj.getName());
|
||||
|
||||
// TODO: Does this need to stay here permanently? This appears to be used for setup mainly
|
||||
obj.addTransactionCompleted(new Observer() {
|
||||
// TODO: Does this need to stay here permanently? This appears to be
|
||||
// used for setup mainly
|
||||
obj.addTransactionCompleted(new Observer() {
|
||||
@Override
|
||||
public void update(Observable observable, Object data) {
|
||||
UAVObject.TransactionResult result = (UAVObject.TransactionResult) data;
|
||||
if (DEBUG) Log.d(TAG,"Got transaction completed event from " + result.obj.getName() + " status: " + result.success);
|
||||
if (DEBUG)
|
||||
Log.d(TAG, "Got transaction completed event from "
|
||||
+ result.obj.getName() + " status: "
|
||||
+ result.success);
|
||||
try {
|
||||
transactionCompleted(result.obj, result.success);
|
||||
} catch (IOException e) {
|
||||
// When the telemetry stream is broken disconnect these updates
|
||||
// When the telemetry stream is broken disconnect these
|
||||
// updates
|
||||
observable.deleteObserver(this);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Request update
|
||||
tel.updateRequested(obj);
|
||||
// objPending = obj;
|
||||
// Request update
|
||||
tel.updateRequested(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the retrieved object when a transaction is completed.
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
public synchronized void transactionCompleted(UAVObject obj, boolean success) throws IOException
|
||||
{
|
||||
//QMutexLocker locker(mutex);
|
||||
// Disconnect from sending object
|
||||
if (DEBUG) Log.d(TAG,"transactionCompleted. Status: " + success);
|
||||
// TODO: Need to be able to disconnect signals
|
||||
//obj->disconnect(this);
|
||||
// objPending = null;
|
||||
public synchronized void transactionCompleted(UAVObject obj, boolean success)
|
||||
throws IOException {
|
||||
if (DEBUG)
|
||||
Log.d(TAG, "transactionCompleted. Status: " + success);
|
||||
|
||||
if(!success) {
|
||||
//Log.e(TAG, "Transaction failed: " + obj.getName() + " sending again.");
|
||||
return;
|
||||
}
|
||||
if (!success) {
|
||||
// Right now success = false means received a NAK so don't
|
||||
// re-attempt
|
||||
Log.e(TAG, "Transaction failed.");
|
||||
}
|
||||
|
||||
// Process next object if telemetry is still available
|
||||
if ( ((String) gcsStatsObj.getField("Status").getValue()).compareTo("Connected") == 0 )
|
||||
{
|
||||
retrieveNextObject();
|
||||
}
|
||||
else
|
||||
{
|
||||
stopRetrievingObjects();
|
||||
}
|
||||
// Process next object if telemetry is still available
|
||||
if (((String) gcsStatsObj.getField("Status").getValue())
|
||||
.compareTo("Connected") == 0) {
|
||||
retrieveNextObject();
|
||||
} else {
|
||||
stopRetrievingObjects();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called each time the flight stats object is updated by the autopilot
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
public synchronized void flightStatsUpdated(UAVObject obj) throws IOException
|
||||
{
|
||||
// Force update if not yet connected
|
||||
gcsStatsObj = objMngr.getObject("GCSTelemetryStats");
|
||||
flightStatsObj = objMngr.getObject("FlightTelemetryStats");
|
||||
if (DEBUG) Log.d(TAG,"GCS Status: " + gcsStatsObj.getField("Status").getValue());
|
||||
if (DEBUG) Log.d(TAG,"Flight Status: " + flightStatsObj.getField("Status").getValue());
|
||||
if ( ((String) gcsStatsObj.getField("Status").getValue()).compareTo("Connected") != 0 ||
|
||||
((String) flightStatsObj.getField("Status").getValue()).compareTo("Connected") == 0 )
|
||||
{
|
||||
processStatsUpdates();
|
||||
}
|
||||
public synchronized void flightStatsUpdated(UAVObject obj)
|
||||
throws IOException {
|
||||
// Force update if not yet connected
|
||||
gcsStatsObj = objMngr.getObject("GCSTelemetryStats");
|
||||
flightStatsObj = objMngr.getObject("FlightTelemetryStats");
|
||||
if (DEBUG)
|
||||
Log.d(TAG, "GCS Status: "
|
||||
+ gcsStatsObj.getField("Status").getValue());
|
||||
if (DEBUG)
|
||||
Log.d(TAG, "Flight Status: "
|
||||
+ flightStatsObj.getField("Status").getValue());
|
||||
if (((String) gcsStatsObj.getField("Status").getValue())
|
||||
.compareTo("Connected") != 0
|
||||
|| ((String) flightStatsObj.getField("Status").getValue())
|
||||
.compareTo("Connected") == 0) {
|
||||
processStatsUpdates();
|
||||
}
|
||||
}
|
||||
|
||||
private long lastStatsTime;
|
||||
|
||||
/**
|
||||
* Called periodically to update the statistics and connection status.
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
public synchronized void processStatsUpdates() throws IOException
|
||||
{
|
||||
// Get telemetry stats
|
||||
if (DEBUG) Log.d(TAG, "processStatsUpdates()");
|
||||
Telemetry.TelemetryStats telStats = tel.getStats();
|
||||
public synchronized void processStatsUpdates() throws IOException {
|
||||
// Get telemetry stats
|
||||
if (DEBUG)
|
||||
Log.d(TAG, "processStatsUpdates()");
|
||||
Telemetry.TelemetryStats telStats = tel.getStats();
|
||||
|
||||
if (DEBUG) Log.d(TAG, "processStatsUpdates() - stats reset");
|
||||
if (DEBUG)
|
||||
Log.d(TAG, "processStatsUpdates() - stats reset");
|
||||
|
||||
// Need to compute time because this update is not regular enough
|
||||
float dT = (System.currentTimeMillis() - lastStatsTime) / 1000.0f;
|
||||
lastStatsTime = System.currentTimeMillis();
|
||||
// Need to compute time because this update is not regular enough
|
||||
float dT = (System.currentTimeMillis() - lastStatsTime) / 1000.0f;
|
||||
lastStatsTime = System.currentTimeMillis();
|
||||
|
||||
// Update stats object
|
||||
gcsStatsObj.getField("RxDataRate").setDouble( telStats.rxBytes / dT );
|
||||
gcsStatsObj.getField("TxDataRate").setDouble( telStats.txBytes / dT );
|
||||
UAVObjectField field = gcsStatsObj.getField("RxFailures");
|
||||
field.setDouble(field.getDouble() + telStats.rxErrors);
|
||||
field = gcsStatsObj.getField("TxFailures");
|
||||
field.setDouble(field.getDouble() + telStats.txErrors);
|
||||
field = gcsStatsObj.getField("TxRetries");
|
||||
field.setDouble(field.getDouble() + telStats.txRetries);
|
||||
// Update stats object
|
||||
gcsStatsObj.getField("RxDataRate").setDouble(telStats.rxBytes / dT);
|
||||
gcsStatsObj.getField("TxDataRate").setDouble(telStats.txBytes / dT);
|
||||
UAVObjectField field = gcsStatsObj.getField("RxFailures");
|
||||
field.setDouble(field.getDouble() + telStats.rxErrors);
|
||||
field = gcsStatsObj.getField("TxFailures");
|
||||
field.setDouble(field.getDouble() + telStats.txErrors);
|
||||
field = gcsStatsObj.getField("TxRetries");
|
||||
field.setDouble(field.getDouble() + telStats.txRetries);
|
||||
|
||||
tel.resetStats();
|
||||
tel.resetStats();
|
||||
|
||||
if (DEBUG) Log.d(TAG, "processStatsUpdates() - stats updated");
|
||||
if (DEBUG)
|
||||
Log.d(TAG, "processStatsUpdates() - stats updated");
|
||||
|
||||
// Check for a connection timeout
|
||||
boolean connectionTimeout;
|
||||
if ( telStats.rxObjects > 0 )
|
||||
{
|
||||
lastUpdateTime = System.currentTimeMillis();
|
||||
// Check for a connection timeout
|
||||
boolean connectionTimeout;
|
||||
if (telStats.rxObjects > 0) {
|
||||
lastUpdateTime = System.currentTimeMillis();
|
||||
|
||||
}
|
||||
if ( (System.currentTimeMillis() - lastUpdateTime) > CONNECTION_TIMEOUT_MS )
|
||||
{
|
||||
connectionTimeout = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
connectionTimeout = false;
|
||||
}
|
||||
}
|
||||
if ((System.currentTimeMillis() - lastUpdateTime) > CONNECTION_TIMEOUT_MS) {
|
||||
connectionTimeout = true;
|
||||
} else {
|
||||
connectionTimeout = false;
|
||||
}
|
||||
|
||||
// Update connection state
|
||||
gcsStatsObj = objMngr.getObject("GCSTelemetryStats");
|
||||
flightStatsObj = objMngr.getObject("FlightTelemetryStats");
|
||||
if(gcsStatsObj == null) {
|
||||
System.out.println("No GCS stats yet");
|
||||
return;
|
||||
}
|
||||
UAVObjectField statusField = gcsStatsObj.getField("Status");
|
||||
String oldStatus = new String((String) statusField.getValue());
|
||||
// Update connection state
|
||||
gcsStatsObj = objMngr.getObject("GCSTelemetryStats");
|
||||
flightStatsObj = objMngr.getObject("FlightTelemetryStats");
|
||||
if (gcsStatsObj == null) {
|
||||
Log.d(TAG, "No GCS stats yet");
|
||||
return;
|
||||
}
|
||||
UAVObjectField statusField = gcsStatsObj.getField("Status");
|
||||
String oldStatus = new String((String) statusField.getValue());
|
||||
|
||||
if (DEBUG) Log.d(TAG,"GCS: " + statusField.getValue() + " Flight: " + flightStatsObj.getField("Status").getValue());
|
||||
if (DEBUG)
|
||||
Log.d(TAG, "GCS: " + statusField.getValue() + " Flight: "
|
||||
+ flightStatsObj.getField("Status").getValue());
|
||||
|
||||
if ( oldStatus.compareTo("Disconnected") == 0 )
|
||||
{
|
||||
// Request connection
|
||||
statusField.setValue("HandshakeReq");
|
||||
}
|
||||
else if ( oldStatus.compareTo("HandshakeReq") == 0 )
|
||||
{
|
||||
// Check for connection acknowledge
|
||||
if ( ((String) flightStatsObj.getField("Status").getValue()).compareTo("HandshakeAck") == 0 )
|
||||
{
|
||||
statusField.setValue("Connected");
|
||||
if (DEBUG) Log.d(TAG,"Connected" + statusField.toString());
|
||||
}
|
||||
}
|
||||
else if ( oldStatus.compareTo("Connected") == 0 )
|
||||
{
|
||||
// Check if the connection is still active and the the autopilot is still connected
|
||||
if ( ((String) flightStatsObj.getField("Status").getValue()).compareTo("Disconnected") == 0 || connectionTimeout)
|
||||
{
|
||||
statusField.setValue("Disconnected");
|
||||
}
|
||||
}
|
||||
if (oldStatus.compareTo("Disconnected") == 0) {
|
||||
// Request connection
|
||||
statusField.setValue("HandshakeReq");
|
||||
} else if (oldStatus.compareTo("HandshakeReq") == 0) {
|
||||
// Check for connection acknowledge
|
||||
if (((String) flightStatsObj.getField("Status").getValue())
|
||||
.compareTo("HandshakeAck") == 0) {
|
||||
statusField.setValue("Connected");
|
||||
if (DEBUG)
|
||||
Log.d(TAG, "Connected" + statusField.toString());
|
||||
}
|
||||
} else if (oldStatus.compareTo("Connected") == 0) {
|
||||
// Check if the connection is still active and the the autopilot is
|
||||
// still connected
|
||||
if (((String) flightStatsObj.getField("Status").getValue())
|
||||
.compareTo("Disconnected") == 0 || connectionTimeout) {
|
||||
statusField.setValue("Disconnected");
|
||||
}
|
||||
}
|
||||
|
||||
// Force telemetry update if not yet connected
|
||||
boolean gcsStatusChanged = !oldStatus.equals(statusField.getValue());
|
||||
// Force telemetry update if not yet connected
|
||||
boolean gcsStatusChanged = !oldStatus.equals(statusField.getValue());
|
||||
|
||||
boolean gcsConnected = statusField.getValue().equals("Connected");
|
||||
boolean gcsDisconnected = statusField.getValue().equals("Disconnected");
|
||||
boolean flightConnected = flightStatsObj.getField("Status").equals("Connected");
|
||||
boolean gcsConnected = statusField.getValue().equals("Connected");
|
||||
boolean gcsDisconnected = statusField.getValue().equals("Disconnected");
|
||||
boolean flightConnected = flightStatsObj.getField("Status").equals(
|
||||
"Connected");
|
||||
|
||||
if ( !gcsConnected || !flightConnected )
|
||||
{
|
||||
if (DEBUG) Log.d(TAG,"Sending gcs status");
|
||||
gcsStatsObj.updated();
|
||||
}
|
||||
if (!gcsConnected || !flightConnected) {
|
||||
if (DEBUG)
|
||||
Log.d(TAG, "Sending gcs status");
|
||||
gcsStatsObj.updated();
|
||||
}
|
||||
|
||||
// Act on new connections or disconnections
|
||||
if (gcsConnected && gcsStatusChanged)
|
||||
{
|
||||
if (DEBUG) Log.d(TAG,"Connection with the autopilot established");
|
||||
setPeriod(STATS_UPDATE_PERIOD_MS);
|
||||
connected = true;
|
||||
objects_updated = false;
|
||||
startRetrievingObjects();
|
||||
setChanged();
|
||||
}
|
||||
if (gcsDisconnected && gcsStatusChanged)
|
||||
{
|
||||
if (DEBUG) Log.d(TAG,"Trying to connect to the autopilot");
|
||||
setPeriod(STATS_CONNECT_PERIOD_MS);
|
||||
connected = false;
|
||||
objects_updated = false;
|
||||
setChanged();
|
||||
}
|
||||
// Act on new connections or disconnections
|
||||
if (gcsConnected && gcsStatusChanged) {
|
||||
if (DEBUG)
|
||||
Log.d(TAG, "Connection with the autopilot established");
|
||||
setPeriod(STATS_UPDATE_PERIOD_MS);
|
||||
connected = true;
|
||||
objects_updated = false;
|
||||
startRetrievingObjects();
|
||||
setChanged();
|
||||
}
|
||||
if (gcsDisconnected && gcsStatusChanged) {
|
||||
if (DEBUG)
|
||||
Log.d(TAG, "Trying to connect to the autopilot");
|
||||
setPeriod(STATS_CONNECT_PERIOD_MS);
|
||||
connected = false;
|
||||
objects_updated = false;
|
||||
setChanged();
|
||||
}
|
||||
|
||||
if (DEBUG) Log.d(TAG, "processStatsUpdates() - before notify");
|
||||
notifyObservers();
|
||||
if (DEBUG) Log.d(TAG, "processStatsUpdates() - after notify");
|
||||
if (DEBUG)
|
||||
Log.d(TAG, "processStatsUpdates() - before notify");
|
||||
notifyObservers();
|
||||
if (DEBUG)
|
||||
Log.d(TAG, "processStatsUpdates() - after notify");
|
||||
}
|
||||
|
||||
private void setPeriod(int ms) {
|
||||
if(periodicTask == null)
|
||||
periodicTask = new Timer();
|
||||
if (periodicTask == null)
|
||||
periodicTask = new Timer();
|
||||
|
||||
periodicTask.cancel();
|
||||
currentPeriod = ms;
|
||||
periodicTask = new Timer();
|
||||
periodicTask.scheduleAtFixedRate(new TimerTask() {
|
||||
periodicTask.scheduleAtFixedRate(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
processStatsUpdates();
|
||||
} catch (IOException e) {
|
||||
// Once the stream has died stop trying to process these updates
|
||||
// Once the stream has died stop trying to process these
|
||||
// updates
|
||||
periodicTask.cancel();
|
||||
}
|
||||
}
|
||||
}, currentPeriod, currentPeriod);
|
||||
}, currentPeriod, currentPeriod);
|
||||
}
|
||||
|
||||
public void stopMonitor()
|
||||
{
|
||||
public void stopMonitor() {
|
||||
periodicTask.cancel();
|
||||
periodicTask = null;
|
||||
}
|
||||
|
@ -174,9 +174,10 @@ public class UAVObjectField {
|
||||
Integer val = (Integer) getValue(index);
|
||||
dataOut.put(val.byteValue());
|
||||
}
|
||||
break;
|
||||
case STRING:
|
||||
// TODO: Implement strings
|
||||
throw new Error("Strings not yet implemented");
|
||||
throw new Error("Strings not yet implemented. Field name: " + getName());
|
||||
}
|
||||
// Done
|
||||
return getNumBytes();
|
||||
|
@ -31,16 +31,18 @@ import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.Observable;
|
||||
|
||||
import junit.framework.Assert;
|
||||
import android.util.Log;
|
||||
|
||||
public class UAVTalk extends Observable {
|
||||
public class UAVTalk {
|
||||
|
||||
static final String TAG = "UAVTalk";
|
||||
public static int LOGLEVEL = 0;
|
||||
public static boolean WARN = LOGLEVEL > 1;
|
||||
public static boolean DEBUG = LOGLEVEL > 0;
|
||||
public static boolean VERBOSE = LOGLEVEL > 3;
|
||||
public static boolean WARN = LOGLEVEL > 2;
|
||||
public static boolean DEBUG = LOGLEVEL > 1;
|
||||
public static boolean ERROR = LOGLEVEL > 0;
|
||||
|
||||
private Thread inputProcessingThread = null;
|
||||
|
||||
@ -102,12 +104,13 @@ public class UAVTalk extends Observable {
|
||||
STATE_SYNC, STATE_TYPE, STATE_SIZE, STATE_OBJID, STATE_INSTID, STATE_DATA, STATE_CS
|
||||
};
|
||||
|
||||
static final int TYPE_MASK = 0xFC;
|
||||
static final int TYPE_MASK = 0xF8;
|
||||
static final int TYPE_VER = 0x20;
|
||||
static final int TYPE_OBJ = (TYPE_VER | 0x00);
|
||||
static final int TYPE_OBJ_REQ = (TYPE_VER | 0x01);
|
||||
static final int TYPE_OBJ_ACK = (TYPE_VER | 0x02);
|
||||
static final int TYPE_ACK = (TYPE_VER | 0x03);
|
||||
static final int TYPE_NACK = (TYPE_VER | 0x04);
|
||||
|
||||
static final int MIN_HEADER_LENGTH = 8; // sync(1), type (1), size(2),
|
||||
// object ID(4)
|
||||
@ -271,6 +274,8 @@ public class UAVTalk extends Observable {
|
||||
// Send object depending on if a response is needed
|
||||
if (type == TYPE_OBJ_ACK || type == TYPE_OBJ_REQ) {
|
||||
if (transmitObject(obj, type, allInstances)) {
|
||||
if(type == TYPE_OBJ_REQ)
|
||||
if (ERROR) Log.e(TAG, "Sending obj req");
|
||||
respObj = obj;
|
||||
respAllInstances = allInstances;
|
||||
return true;
|
||||
@ -290,7 +295,7 @@ public class UAVTalk extends Observable {
|
||||
* @throws IOException
|
||||
*/
|
||||
public synchronized boolean processInputByte(int rxbyte) throws IOException {
|
||||
assert (objMngr != null);
|
||||
Assert.assertNotNull(objMngr);
|
||||
|
||||
// Update stats
|
||||
stats.rxBytes++;
|
||||
@ -318,12 +323,13 @@ public class UAVTalk extends Observable {
|
||||
rxCS = updateCRC(rxCS, rxbyte);
|
||||
|
||||
if ((rxbyte & TYPE_MASK) != TYPE_VER) {
|
||||
Log.e(TAG, "Unknown UAVTalk type:" + rxbyte);
|
||||
rxState = RxStateType.STATE_SYNC;
|
||||
break;
|
||||
}
|
||||
|
||||
rxType = rxbyte;
|
||||
|
||||
if (VERBOSE) Log.v(TAG, "Received packet type: " + rxType);
|
||||
packetSize = 0;
|
||||
|
||||
rxState = RxStateType.STATE_SIZE;
|
||||
@ -380,7 +386,7 @@ public class UAVTalk extends Observable {
|
||||
}
|
||||
|
||||
// Determine data length
|
||||
if (rxType == TYPE_OBJ_REQ || rxType == TYPE_ACK)
|
||||
if (rxType == TYPE_OBJ_REQ || rxType == TYPE_ACK || rxType == TYPE_NACK)
|
||||
rxLength = 0;
|
||||
else
|
||||
rxLength = rxObj.getNumBytes();
|
||||
@ -565,6 +571,24 @@ public class UAVTalk extends Observable {
|
||||
error = true;
|
||||
}
|
||||
break;
|
||||
case TYPE_NACK:
|
||||
if (DEBUG) Log.d(TAG, "Received NAK: " + objId + " " + objMngr.getObject(objId).getName());
|
||||
// All instances, not allowed for NACK messages
|
||||
if (!allInstances)
|
||||
{
|
||||
// Get object
|
||||
obj = objMngr.getObject(objId, instId);
|
||||
// Check if object exists:
|
||||
if (obj != null)
|
||||
{
|
||||
updateNack(obj);
|
||||
}
|
||||
else
|
||||
{
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TYPE_ACK:
|
||||
// All instances, not allowed for ACK messages
|
||||
if (!allInstances) {
|
||||
@ -636,15 +660,33 @@ public class UAVTalk extends Observable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a transaction is pending and if yes complete it.
|
||||
*/
|
||||
void updateNack(UAVObject obj)
|
||||
{
|
||||
if (DEBUG) Log.d(TAG, "NACK received: " + obj.getName());
|
||||
Assert.assertNotNull(obj);
|
||||
//obj.transactionCompleted(false);
|
||||
if (respObj != null && respObj.getObjID() == obj.getObjID() &&
|
||||
(respObj.getInstID() == obj.getInstID() || respAllInstances)) {
|
||||
if (transactionListener != null)
|
||||
transactionListener.TransactionFailed(obj);
|
||||
respObj = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a transaction is pending and if yes complete it.
|
||||
*/
|
||||
synchronized void updateAck(UAVObject obj) {
|
||||
if (DEBUG) Log.d(TAG, "ACK received: " + obj.getName());
|
||||
Assert.assertNotNull(obj);
|
||||
if (respObj != null && respObj.getObjID() == obj.getObjID()
|
||||
&& (respObj.getInstID() == obj.getInstID() || respAllInstances)) {
|
||||
if (transactionListener != null)
|
||||
transactionListener.TransactionSucceeded(obj);
|
||||
respObj = null;
|
||||
setChanged();
|
||||
notifyObservers(obj);
|
||||
}
|
||||
}
|
||||
|
||||
@ -784,4 +826,14 @@ public class UAVTalk extends Observable {
|
||||
return crc;
|
||||
}
|
||||
|
||||
private OnTransactionCompletedListener transactionListener = null;
|
||||
abstract class OnTransactionCompletedListener {
|
||||
abstract void TransactionSucceeded(UAVObject data);
|
||||
abstract void TransactionFailed(UAVObject data);
|
||||
};
|
||||
void setOnTransactionCompletedListener(OnTransactionCompletedListener onTransactionListener) {
|
||||
this.transactionListener = onTransactionListener;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user