mirror of
https://bitbucket.org/librepilot/librepilot.git
synced 2024-12-02 10:24:11 +01:00
Added some missing files. Improved object browser to use ListView.
ExpandableListView next.
This commit is contained in:
parent
6505507230
commit
e2a90b2265
BIN
androidgcs/Doc/.AndroidArchitecture.txt.swp
Normal file
BIN
androidgcs/Doc/.AndroidArchitecture.txt.swp
Normal file
Binary file not shown.
31
androidgcs/Doc/AndroidArchitecture.txt
Normal file
31
androidgcs/Doc/AndroidArchitecture.txt
Normal file
@ -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...
|
||||
|
||||
|
@ -1,13 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
>
|
||||
<TextView
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
/>
|
||||
<TextView android:text="TextView" android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content"></TextView>
|
||||
<ToggleButton android:text="ToggleButton" android:id="@+id/toggleButton1" android:layout_width="wrap_content" android:layout_height="wrap_content"></ToggleButton>
|
||||
</LinearLayout>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<ListView android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/object_list"></ListView>
|
||||
</RelativeLayout>
|
||||
|
7
androidgcs/res/layout/object_view.xml
Normal file
7
androidgcs/res/layout/object_view.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:padding="10dp"
|
||||
android:textSize="16sp" >
|
||||
</TextView>
|
6
androidgcs/res/menu/options_menu.xml
Normal file
6
androidgcs/res/menu/options_menu.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:title="@string/menu_item_settings" android:id="@+id/menu_settings"></item>
|
||||
<item android:title="@string/menu_item_connect" android:id="@+id/menu_connect"></item>
|
||||
<item android:title="@string/menu_item_disconnect" android:id="@+id/menu_disconnect"></item>
|
||||
</menu>
|
@ -1,4 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="app_name">OpenPilot GCS</string>
|
||||
<string name="menu_item_settings">Settings</string>
|
||||
<string name="menu_item_connect">Connect</string>
|
||||
<string name="menu_item_disconnect">Disconnect</string>
|
||||
<string name="object_browser_title">OpenPilot Object Browser</string>
|
||||
</resources>
|
||||
|
9
androidgcs/res/xml/telemetry_widget_info.xml
Normal file
9
androidgcs/res/xml/telemetry_widget_info.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<appwidget-provider
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
android:minWidth="294dp"
|
||||
android:minHeight="72dp"
|
||||
android:updatePeriodMillis="86400000"
|
||||
android:initialLayout="@layout/telemetry_widget">
|
||||
<!-- android:configure="com.example.android.ExampleAppWidgetConfigure" -->
|
||||
</appwidget-provider>
|
@ -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;
|
||||
}
|
||||
|
@ -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<List<UAVDataObject>> allobjects = objMngr.getDataObjects();
|
||||
List<UAVDataObject> linearized = new ArrayList<UAVDataObject>();
|
||||
ListIterator<List<UAVDataObject>> li = allobjects.listIterator();
|
||||
while(li.hasNext()) {
|
||||
linearized.addAll(li.next());
|
||||
}
|
||||
|
||||
ArrayAdapter<UAVDataObject> adapter = new ArrayAdapter<UAVDataObject>(this,R.layout.object_view, linearized);
|
||||
ListView objects = (ListView) findViewById(R.id.object_list);
|
||||
objects.setAdapter(adapter);
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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<UAVObject> 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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user