diff --git a/androidgcs/res/layout/system_alarms.xml b/androidgcs/res/layout/system_alarms.xml index a25c575dd..e67990427 100644 --- a/androidgcs/res/layout/system_alarms.xml +++ b/androidgcs/res/layout/system_alarms.xml @@ -4,6 +4,12 @@ android:layout_height="match_parent" android:layout_gravity="center" > + + + + + + + + + \ No newline at end of file diff --git a/androidgcs/src/org/openpilot/androidgcs/ObjectManagerActivity.java b/androidgcs/src/org/openpilot/androidgcs/ObjectManagerActivity.java index 330217c8c..6a9273cc1 100644 --- a/androidgcs/src/org/openpilot/androidgcs/ObjectManagerActivity.java +++ b/androidgcs/src/org/openpilot/androidgcs/ObjectManagerActivity.java @@ -29,7 +29,7 @@ import android.widget.TextView; public abstract class ObjectManagerActivity extends Activity { private final String TAG = "ObjectManagerActivity"; - private static int LOGLEVEL = 0; + private static int LOGLEVEL = 1; // private static boolean WARN = LOGLEVEL > 1; private static boolean DEBUG = LOGLEVEL > 0; @@ -162,6 +162,9 @@ public abstract class ObjectManagerActivity extends Activity { stats.addUpdatedObserver(telemetryObserver); telemetryStatsConnected = true; updateStats(); + + if (DEBUG) Log.d(TAG, "Notifying listeners about connection. There are " + connectionListeners.countObservers()); + connectionListeners.connected(); } /** @@ -175,6 +178,9 @@ public abstract class ObjectManagerActivity extends Activity { TextView txRate = (TextView) findViewById(R.id.telemetry_stats_tx_rate); rxRate.setText(""); txRate.setText(""); + + // Providing a null update triggers a disconnect on fragments + connectionListeners.disconnected(); } @Override @@ -223,6 +229,50 @@ public abstract class ObjectManagerActivity extends Activity { public void onBind() { } + + + /** + * Callbacks so ObjectManagerFragments get the onOPConnected and onOPDisconnected signals + */ + class ConnectionObserver extends Observable { + public void disconnected() { + synchronized(this) { + setChanged(); + notifyObservers(); + } + } + public void connected() { + synchronized(this) { + setChanged(); + notifyObservers(objMngr); + } + } + }; + private ConnectionObserver connectionListeners = new ConnectionObserver(); + public class OnConnectionListener implements Observer { + + // Local reference of the fragment to notify, store in constructor + ObjectManagerFragment fragment; + OnConnectionListener(ObjectManagerFragment fragment) { this.fragment = fragment; }; + + // Whenever the observer is updated either conenct or disconnect based on the data + @Override + public void update(Observable observable, Object data) { + Log.d(TAG, "onConnectionListener called"); + if (data == null) + fragment.onOPDisconnected(); + else + fragment.onOPConnected(objMngr); + } + + } ; + void addOnConnectionListenerFragment(ObjectManagerFragment frag) { + connectionListeners.addObserver(new OnConnectionListener(frag)); + if (DEBUG) Log.d(TAG, "Connecting " + frag + " there are now " + connectionListeners.countObservers()); + if (mConnected) + frag.onOPConnected(objMngr); + } + /** Defines callbacks for service binding, passed to bindService() */ private ServiceConnection mConnection = new ServiceConnection() { diff --git a/androidgcs/src/org/openpilot/androidgcs/ObjectManagerFragment.java b/androidgcs/src/org/openpilot/androidgcs/ObjectManagerFragment.java new file mode 100644 index 000000000..822e6b8b6 --- /dev/null +++ b/androidgcs/src/org/openpilot/androidgcs/ObjectManagerFragment.java @@ -0,0 +1,102 @@ +package org.openpilot.androidgcs; + +import java.util.List; +import java.util.ListIterator; +import java.util.Observable; +import java.util.Observer; + +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVObjectManager; + +import android.app.Activity; +import android.app.Fragment; +import android.os.Bundle; +import android.os.Handler; +import android.util.Log; + +public class ObjectManagerFragment extends Fragment { + + private static final String TAG = ObjectManagerFragment.class.getSimpleName(); + private static int LOGLEVEL = 1; +// private static boolean WARN = LOGLEVEL > 1; + private static boolean DEBUG = LOGLEVEL > 0; + + UAVObjectManager objMngr; + + /** Called when the activity is first created. */ + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (DEBUG) Log.d(TAG, "Created an ObjectManagerFragment"); + // For an activity this registers against the telemetry service intents. Fragments must be notified by their + // parent activity + } + + /** + * Attach to the parent activity so it can notify us when the connection + * changed + */ + public void onAttach(Activity activity) { + super.onAttach(activity); + if (DEBUG) Log.d(TAG,"onAttach"); + + ((ObjectManagerActivity)activity).addOnConnectionListenerFragment(this); + } + + // The below methods should all be called by the parent activity at the appropriate times + void onOPConnected(UAVObjectManager objMngr) { + this.objMngr = objMngr; + if (DEBUG) Log.d(TAG,"onOPConnected"); + } + + void onOPDisconnected() { + objMngr = null; + if (DEBUG) Log.d(TAG,"onOPDisconnected"); + } + + public void onBind() { + + } + + + /** + * Called whenever any objects subscribed to via registerObjects + */ + 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 UpdatedObserver implements Observer { + UAVObject obj; + UpdatedObserver(UAVObject obj) { this.obj = obj; }; + public void update(Observable observable, Object data) { + uavobjHandler.post(new Runnable() { + @Override + public void run() { 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 UpdatedObserver(object)); + } + protected void registerObjectUpdates(List> objects) { + ListIterator> li = objects.listIterator(); + while(li.hasNext()) { + ListIterator li2 = li.next().listIterator(); + while(li2.hasNext()) + registerObjectUpdates(li2.next()); + } + } + +} diff --git a/androidgcs/src/org/openpilot/androidgcs/SystemAlarmActivity.java b/androidgcs/src/org/openpilot/androidgcs/SystemAlarmActivity.java index 63c0a6ac4..bb93db465 100644 --- a/androidgcs/src/org/openpilot/androidgcs/SystemAlarmActivity.java +++ b/androidgcs/src/org/openpilot/androidgcs/SystemAlarmActivity.java @@ -1,51 +1,14 @@ package org.openpilot.androidgcs; -import java.util.List; - -import org.openpilot.uavtalk.UAVObject; -import org.openpilot.uavtalk.UAVObjectField; - import android.os.Bundle; -import android.widget.TextView; +/** + * All the work for this activity is performed by it's fragment + */ public class SystemAlarmActivity extends ObjectManagerActivity { - /** - * Update the UI whenever the attitude is updated - */ - protected void objectUpdated(UAVObject obj) { - if (obj.getName().compareTo("SystemAlarms") != 0) - return; - - TextView alarms = (TextView) findViewById(R.id.system_alarms_status); - UAVObjectField a = obj.getField("Alarm"); - List names = a.getElementNames(); - String contents = new String(); - List options = a.getOptions(); - - // Rank the alarms by order of severity, skip uninitialized - for (int j = options.size() - 1; j > 0; j--) { - for (int i = 0; i < names.size(); i++) { - if(a.getDouble(i) == j) - contents += names.get(i) + " : " + a.getValue(i).toString() + "\n"; - } - } - alarms.setText(contents); - } - @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.system_alarms); - } - - @Override - void onOPConnected() { - super.onOPConnected(); - - // Connect the update method to AttitudeActual - UAVObject obj = objMngr.getObject("SystemAlarms"); - if (obj != null) - registerObjectUpdates(obj); - objectUpdated(obj); - } + } } diff --git a/androidgcs/src/org/openpilot/androidgcs/SystemAlarmsFragment.java b/androidgcs/src/org/openpilot/androidgcs/SystemAlarmsFragment.java new file mode 100644 index 000000000..2ecda18f8 --- /dev/null +++ b/androidgcs/src/org/openpilot/androidgcs/SystemAlarmsFragment.java @@ -0,0 +1,62 @@ +package org.openpilot.androidgcs; + +import java.util.List; + +import org.openpilot.uavtalk.UAVObject; +import org.openpilot.uavtalk.UAVObjectField; +import org.openpilot.uavtalk.UAVObjectManager; + +import android.os.Bundle; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +public class SystemAlarmsFragment extends ObjectManagerFragment { + + private static final String TAG = SystemAlarmsFragment.class.getSimpleName(); + + //@Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + // Inflate the layout for this fragment + return inflater.inflate(R.layout.system_alarms_fragment, container, false); + } + + public void onOPConnected(UAVObjectManager objMngr) { + super.onOPConnected(objMngr); + Log.d(TAG,"On connected"); + + UAVObject obj = objMngr.getObject("SystemAlarms"); + if (obj != null) + registerObjectUpdates(obj); + objectUpdated(obj); + } + + /** + * Called whenever any objects subscribed to via registerObjects + */ + @Override + protected void objectUpdated(UAVObject obj) { + Log.d(TAG, "Updated"); + if (obj.getName().compareTo("SystemAlarms") == 0) { + TextView alarms = (TextView) getActivity().findViewById(R.id.system_alarms_fragment_field); + UAVObjectField a = obj.getField("Alarm"); + List names = a.getElementNames(); + String contents = new String(); + List options = a.getOptions(); + + // Rank the alarms by order of severity, skip uninitialized + for (int j = options.size() - 1; j > 0; j--) { + for (int i = 0; i < names.size(); i++) { + if(a.getDouble(i) == j) + contents += names.get(i) + " : " + a.getValue(i).toString() + "\n"; + } + } + alarms.setText(contents); + } + } + + +}