diff --git a/androidgcs/Doc/.AndroidArchitecture.txt.swp b/androidgcs/Doc/.AndroidArchitecture.txt.swp
new file mode 100644
index 000000000..167a07252
Binary files /dev/null and b/androidgcs/Doc/.AndroidArchitecture.txt.swp differ
diff --git a/androidgcs/Doc/AndroidArchitecture.txt b/androidgcs/Doc/AndroidArchitecture.txt
new file mode 100644
index 000000000..d9cdf2ada
--- /dev/null
+++ b/androidgcs/Doc/AndroidArchitecture.txt
@@ -0,0 +1,31 @@
+------- TELEMETRY ---------
+The Telemetry system has been implemented, and is composed of a few
+major components:
+
+Telemetry.java - receives command to transmit objects through telemetry and
+also emits notification when transactions are completed
+
+TelemetryMonitor.java - monitors the FlightTelemetryStats and GCSTelemetryStats
+to establish when a working connection is in place. Also initiates downloading
+all the objects on a new connection.
+
+UAVObjectManager.java - the central data store. The data is actually stored
+within objects, but this maintains the handles to all of them.
+
+UAVTalk.java - the actual communication layer. Can packetize an object and
+insert into stream and process the incoming stream and update objects
+accordingly.
+
+---- MESSAGE PASSING ----
+The current implementation/analog to the slots/sockets in QT are Observers
+which are registered as added to an Observable. This is used extensibly within
+the telemetry system. I will continue to use this _within_ the Telemetry
+module so it doesn't depend on any android features.
+
+In android there is a constraint that UI operations should all be done from the
+UI thread. The most common way to do this is for the UI object (such as
+Activity) to instantiate a Handler to which messages or runnables are posted.
+
+So for external objects they will register a runnable somehow...
+
+
diff --git a/androidgcs/res/layout/main.xml b/androidgcs/res/layout/main.xml
index 9e5f90add..880e276ff 100644
--- a/androidgcs/res/layout/main.xml
+++ b/androidgcs/res/layout/main.xml
@@ -1,13 +1,6 @@
-
-
-
-
-
+
+
+
diff --git a/androidgcs/res/layout/object_view.xml b/androidgcs/res/layout/object_view.xml
new file mode 100644
index 000000000..fdf5a0bae
--- /dev/null
+++ b/androidgcs/res/layout/object_view.xml
@@ -0,0 +1,7 @@
+
+
+
diff --git a/androidgcs/res/menu/options_menu.xml b/androidgcs/res/menu/options_menu.xml
new file mode 100644
index 000000000..db86aa670
--- /dev/null
+++ b/androidgcs/res/menu/options_menu.xml
@@ -0,0 +1,6 @@
+
+
diff --git a/androidgcs/res/values/strings.xml b/androidgcs/res/values/strings.xml
index 52fa56534..8daa0ec36 100644
--- a/androidgcs/res/values/strings.xml
+++ b/androidgcs/res/values/strings.xml
@@ -1,4 +1,8 @@
OpenPilot GCS
+ Settings
+ Connect
+ Disconnect
+ OpenPilot Object Browser
diff --git a/androidgcs/res/xml/telemetry_widget_info.xml b/androidgcs/res/xml/telemetry_widget_info.xml
new file mode 100644
index 000000000..f2ced6645
--- /dev/null
+++ b/androidgcs/res/xml/telemetry_widget_info.xml
@@ -0,0 +1,9 @@
+
+
+ android:minWidth="294dp"
+ android:minHeight="72dp"
+ android:updatePeriodMillis="86400000"
+ android:initialLayout="@layout/telemetry_widget">
+
+
diff --git a/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java b/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java
index 557c3b256..7b3030d4f 100644
--- a/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java
+++ b/androidgcs/src/org/openpilot/androidgcs/OPTelemetryService.java
@@ -1,5 +1,8 @@
package org.openpilot.androidgcs;
+import java.util.Observable;
+import java.util.Observer;
+
import org.openpilot.uavtalk.Telemetry;
import org.openpilot.uavtalk.TelemetryMonitor;
import org.openpilot.uavtalk.UAVDataObject;
@@ -27,7 +30,7 @@ import android.widget.Toast;
public class OPTelemetryService extends Service {
// Logging settings
- private final String TAG = "OPTElemetryService";
+ private final String TAG = "OPTelemetryService";
public static int LOGLEVEL = 2;
public static boolean WARN = LOGLEVEL > 1;
public static boolean DEBUG = LOGLEVEL > 0;
@@ -44,10 +47,13 @@ public class OPTelemetryService extends Service {
private ServiceHandler mServiceHandler;
// Message ids
- final int MSG_START = 0;
- final int MSG_CONNECT_BT = 1;
- final int MSG_CONNECT_FAKE = 2;
- final int MSG_TOAST = 100;
+ static final int MSG_START = 0;
+ static final int MSG_CONNECT_BT = 1;
+ static final int MSG_CONNECT_FAKE = 2;
+ static final int MSG_DISCONNECT = 3;
+ static final int MSG_TOAST = 100;
+
+ private boolean terminate = false;
private Thread activeTelem;
@@ -65,12 +71,28 @@ public class OPTelemetryService extends Service {
System.out.println("HERE");
stopSelf(msg.arg2);
case MSG_CONNECT_BT:
+ terminate = false;
activeTelem = new BTTelemetryThread();
activeTelem.start();
break;
case MSG_CONNECT_FAKE:
+ terminate = false;
activeTelem = new FakeTelemetryThread();
activeTelem.start();
+ break;
+ case MSG_DISCONNECT:
+ terminate = true;
+ try {
+ activeTelem.join();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ activeTelem = null;
+
+ Intent intent = new Intent();
+ intent.setAction(INTENT_ACTION_DISCONNECTED);
+ sendBroadcast(intent,null);
+
break;
case MSG_TOAST:
Toast.makeText(OPTelemetryService.this, (String) msg.obj, Toast.LENGTH_SHORT);
@@ -129,8 +151,18 @@ public class OPTelemetryService extends Service {
msg.arg1 = MSG_CONNECT_FAKE;
mServiceHandler.sendMessage(msg);
}
+ public void openBTConnection() {
+ Message msg = mServiceHandler.obtainMessage();
+ msg.arg1 = MSG_CONNECT_BT;
+ mServiceHandler.sendMessage(msg);
+ }
+ public void stopConnection() {
+ Message msg = mServiceHandler.obtainMessage();
+ msg.arg1 = MSG_DISCONNECT;
+ mServiceHandler.sendMessage(msg);
+ }
};
-
+
public void toastMessage(String msgText) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = MSG_TOAST;
@@ -151,17 +183,17 @@ public class OPTelemetryService extends Service {
objMngr = new UAVObjectManager();
UAVObjectsInitialize.register(objMngr);
}
-
+
public void run() {
- System.out.println("Runnin fake thread");
+ System.out.println("Running fake thread");
Intent intent = new Intent();
intent.setAction(INTENT_ACTION_CONNECTED);
sendBroadcast(intent,null);
-
+
//toastMessage("Started fake telemetry thread");
UAVDataObject systemStats = (UAVDataObject) objMngr.getObject("SystemStats");
- while(true) {
+ while( !terminate ) {
systemStats.updated();
try {
Thread.sleep(1000);
@@ -176,7 +208,7 @@ public class OPTelemetryService extends Service {
private UAVObjectManager objMngr;
private UAVTalk uavTalk;
private Telemetry tel;
- //private TelemetryMonitor mon;
+ private TelemetryMonitor mon;
public UAVObjectManager getObjectManager() { return objMngr; };
@@ -217,10 +249,21 @@ public class OPTelemetryService extends Service {
uavTalk = bt.getUavtalk();
tel = new Telemetry(uavTalk, objMngr);
- new TelemetryMonitor(objMngr,tel);
+ mon = new TelemetryMonitor(objMngr,tel);
+ mon.addObserver(new Observer() {
+ public void update(Observable arg0, Object arg1) {
+ System.out.println("Mon updated. Connected: " + mon.getConnected() + " objects updated: " + mon.getObjectsUpdated());
+ if(mon.getConnected() /*&& mon.getObjectsUpdated()*/) {
+ Intent intent = new Intent();
+ intent.setAction(INTENT_ACTION_CONNECTED);
+ sendBroadcast(intent,null);
+ }
+ }
+ });
+
if (DEBUG) Log.d(TAG, "Entering UAVTalk processing loop");
- while(true) {
+ while( !terminate ) {
if( !uavTalk.processInputStream() )
break;
}
diff --git a/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java b/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java
index 48aa1cd10..f68e839c1 100644
--- a/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java
+++ b/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java
@@ -1,42 +1,67 @@
package org.openpilot.androidgcs;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.ListIterator;
import java.util.Observable;
import java.util.Observer;
+import android.database.DataSetObserver;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.ExpandableListAdapter;
+import android.widget.ExpandableListView;
+import android.widget.ListView;
+import android.widget.SimpleAdapter;
+import android.widget.SimpleExpandableListAdapter;
import android.widget.TextView;
-import android.widget.ToggleButton;
+import android.widget.Toast;
+import org.openpilot.uavtalk.UAVDataObject;
import org.openpilot.uavtalk.UAVObject;
public class ObjectBrowser extends ObjectManagerActivity {
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch(item.getItemId()) {
+ case R.id.menu_connect:
+ binder.openBTConnection();
+ return true;
+ case R.id.menu_disconnect:
+ binder.stopConnection();
+ updateText.run();
+ return true;
+ case R.id.menu_settings:
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ MenuInflater inflater = getMenuInflater();
+ inflater.inflate(R.menu.options_menu, menu);
+ return true;
+ }
+
private final String TAG = "ObjectBrower";
boolean connected;
final Handler uavobjHandler = new Handler();
final Runnable updateText = new Runnable() {
public void run() {
- ToggleButton button = (ToggleButton) findViewById(R.id.toggleButton1);
- button.setChecked(!connected);
-
- Log.d(TAG,"HERE" + connected);
-
- TextView text = (TextView) findViewById(R.id.textView1);
-
- UAVObject obj1 = objMngr.getObject("SystemStats");
- UAVObject obj2 = objMngr.getObject("AttitudeRaw");
- UAVObject obj3 = objMngr.getObject("AttitudeActual");
- UAVObject obj4 = objMngr.getObject("SystemAlarms");
-
- if(obj1 == null || obj2 == null || obj3 == null || obj4 == null)
- return;
-
- Log.d(TAG,"And here");
- text.setText(obj1.toString() + "\n" + obj2.toString() + "\n" + obj3.toString() + "\n" + obj4.toString() );
-
+ Log.d(TAG,"Update");
+ update();
}
};
@@ -44,16 +69,15 @@ public class ObjectBrowser extends ObjectManagerActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
+ setContentView(R.layout.main);
}
@Override
void onOPConnected() {
- // Toast.makeText(this,"Telemetry estabilished",Toast.LENGTH_SHORT);
+ Toast.makeText(this,"Telemetry estabilished",Toast.LENGTH_SHORT);
Log.d(TAG, "onOPConnected()");
-
+
UAVObject obj = objMngr.getObject("SystemStats");
- Log.d(TAG, ((Boolean) (obj == null)).toString());
if(obj != null)
obj.addUpdatedObserver(new Observer() {
public void update(Observable observable, Object data) {
@@ -62,4 +86,18 @@ public class ObjectBrowser extends ObjectManagerActivity {
});
}
+
+ public void update() {
+ List> allobjects = objMngr.getDataObjects();
+ List linearized = new ArrayList();
+ ListIterator> li = allobjects.listIterator();
+ while(li.hasNext()) {
+ linearized.addAll(li.next());
+ }
+
+ ArrayAdapter adapter = new ArrayAdapter(this,R.layout.object_view, linearized);
+ ListView objects = (ListView) findViewById(R.id.object_list);
+ objects.setAdapter(adapter);
+
+ }
}
diff --git a/androidgcs/src/org/openpilot/androidgcs/ObjectManagerActivity.java b/androidgcs/src/org/openpilot/androidgcs/ObjectManagerActivity.java
index 9f57796dc..12a072de7 100644
--- a/androidgcs/src/org/openpilot/androidgcs/ObjectManagerActivity.java
+++ b/androidgcs/src/org/openpilot/androidgcs/ObjectManagerActivity.java
@@ -85,7 +85,6 @@ public abstract class ObjectManagerActivity extends Activity {
// We've bound to LocalService, cast the IBinder and attempt to open a connection
if (DEBUG) Log.d(TAG,"Service bound");
binder = (LocalBinder) service;
- binder.openFakeConnection();
}
public void onServiceDisconnected(ComponentName name) {
diff --git a/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java b/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java
index 7208181ad..daedcc85b 100644
--- a/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java
+++ b/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java
@@ -10,10 +10,10 @@ import java.util.TimerTask;
import android.util.Log;
-public class TelemetryMonitor {
+public class TelemetryMonitor extends Observable{
private static final String TAG = "TelemetryMonitor";
- public static int LOGLEVEL = 0;
+ public static int LOGLEVEL = 2;
public static boolean WARN = LOGLEVEL > 1;
public static boolean DEBUG = LOGLEVEL > 0;
@@ -31,6 +31,12 @@ public class TelemetryMonitor {
private long lastUpdateTime;
private List queue;
+ private boolean connected = false;
+ private boolean objects_updated = false;
+
+ public boolean getConnected() { return connected; };
+ public boolean getObjectsUpdated() { return objects_updated; };
+
public TelemetryMonitor(UAVObjectManager objMngr, Telemetry tel)
{
this.objMngr = objMngr;
@@ -116,8 +122,9 @@ public class TelemetryMonitor {
if ( queue.isEmpty() )
{
if (DEBUG) Log.d(TAG, "All objects retrieved: Connected Successfully");
- //qxtLog->debug("Object retrieval completed");
- //emit connected();
+ objects_updated = true;
+ setChanged();
+ notifyObservers();
return;
}
// Get next object from the queue
@@ -260,9 +267,9 @@ public class TelemetryMonitor {
// Force telemetry update if not yet connected
boolean gcsStatusChanged = !oldStatus.equals(statusField.getValue());
- boolean gcsConnected = ((String) statusField.getValue()).compareTo("Connected") == 0;
- boolean gcsDisconnected = ((String) statusField.getValue()).compareTo("Disconnected") == 0;
- boolean flightConnected = ((String) flightStatsObj.getField("Status").getValue()).compareTo("Connected") == 0;
+ boolean gcsConnected = statusField.getValue().equals("Connected");
+ boolean gcsDisconnected = statusField.getValue().equals("Disconnected");
+ boolean flightConnected = flightStatsObj.getField("Status").equals("Connected");
if ( !gcsConnected || !flightConnected )
{
@@ -275,14 +282,21 @@ public class TelemetryMonitor {
{
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);
- //emit disconnected();
+ connected = false;
+ objects_updated = false;
+ setChanged();
}
+ notifyObservers();
+
}
private void setPeriod(int ms) {
diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java b/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java
index 8671cdef9..39c1f6ee7 100644
--- a/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java
+++ b/androidgcs/src/org/openpilot/uavtalk/UAVTalk.java
@@ -197,8 +197,7 @@ public class UAVTalk extends Observable {
return false;
}
- // System.out.println("Received byte " + val + " in state + " +
- // rxState);
+ //System.out.println("Received byte " + val + " in state + " + rxState);
processInputByte(val);
return true;
}