diff --git a/androidgcs/AndroidManifest.xml b/androidgcs/AndroidManifest.xml index 7a96a6600..8b3a9e4b3 100644 --- a/androidgcs/AndroidManifest.xml +++ b/androidgcs/AndroidManifest.xml @@ -5,8 +5,18 @@ android:versionName="1.0"> - + + + + + + + + + + \ No newline at end of file diff --git a/androidgcs/default.properties b/androidgcs/default.properties index 46769a720..66db0d159 100644 --- a/androidgcs/default.properties +++ b/androidgcs/default.properties @@ -8,4 +8,4 @@ # project structure. # Project target. -target=android-7 +target=android-10 diff --git a/androidgcs/res/layout/main.xml b/androidgcs/res/layout/main.xml index 3a5f117d3..7e4a852bf 100644 --- a/androidgcs/res/layout/main.xml +++ b/androidgcs/res/layout/main.xml @@ -7,6 +7,5 @@ diff --git a/androidgcs/res/values/strings.xml b/androidgcs/res/values/strings.xml index 0d9f93bc2..52fa56534 100644 --- a/androidgcs/res/values/strings.xml +++ b/androidgcs/res/values/strings.xml @@ -1,5 +1,4 @@ - Hello World! OpenPilot GCS diff --git a/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java b/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java new file mode 100644 index 000000000..3c6231258 --- /dev/null +++ b/androidgcs/src/org/openpilot/androidgcs/ObjectBrowser.java @@ -0,0 +1,129 @@ +package org.openpilot.androidgcs; + +import java.io.IOException; +import java.util.Set; +import java.util.UUID; + +import android.app.Activity; +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothSocket; +import android.content.Intent; +import android.os.Bundle; +import android.util.Log; + +import org.openpilot.androidgcs.*; +import org.openpilot.uavtalk.Telemetry; +import org.openpilot.uavtalk.TelemetryMonitor; +import org.openpilot.uavtalk.UAVObjectManager; +import org.openpilot.uavtalk.UAVTalk; +import org.openpilot.uavtalk.uavobjects.UAVObjectsInitialize; + +public class ObjectBrowser extends Activity { + + private final String TAG = "ObjectBrower"; + private final String DEVICE_NAME = "RN42-222D"; + private final int REQUEST_ENABLE_BT = 0; + private UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); + BluetoothAdapter mBluetoothAdapter; + UAVObjectManager objMngr; + UAVTalk uavTalk; + + /** Called when the activity is first created. */ + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + + Log.d(TAG, "Launching Object Browser"); + + mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); + if (mBluetoothAdapter == null) { + // Device does not support Bluetooth + Log.d(TAG, "Device does not support Bluetooth"); + return; + } + + if (!mBluetoothAdapter.isEnabled()) { + Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); + startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT); + } else { + queryDevices(); + } + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + if(requestCode == REQUEST_ENABLE_BT && resultCode == RESULT_OK) { + Log.d(TAG, "Bluetooth started succesfully"); + queryDevices(); + } + if(requestCode == REQUEST_ENABLE_BT && resultCode != RESULT_OK) + Log.d(TAG, "Bluetooth could not be started"); + + } + + public void queryDevices() { + Log.d(TAG, "Searching for devices"); + Set pairedDevices = mBluetoothAdapter.getBondedDevices(); + // If there are paired devices + if (pairedDevices.size() > 0) { + // Loop through paired devices + for (BluetoothDevice device : pairedDevices) { + // Add the name and address to an array adapter to show in a ListView + //mArrayAdapter.add(device.getName() + "\n" + device.getAddress()); + Log.d(TAG, "Paired device: " + device.getName()); + if(device.getName().compareTo(DEVICE_NAME) == 0) { + openTelmetryBluetooth(device); + openTelmetryBluetooth(device); + } + } + } + + } + + private void openTelmetryBluetooth(BluetoothDevice device) { + Log.d(TAG, "Opening conncetion to " + device.getName()); + BluetoothSocket socket = null; + try { + socket = device.createInsecureRfcommSocketToServiceRecord(MY_UUID); + } catch (IOException e) { + Log.e(TAG,"Unable to create Rfcomm socket"); + e.printStackTrace(); + } + + mBluetoothAdapter.cancelDiscovery(); + + try { + socket.connect(); + } + catch (IOException e) { + Log.e(TAG,"Unable to connect to requested device", e); + try { + socket.close(); + } catch (IOException e2) { + Log.e(TAG, "unable to close() socket during connection failure", e2); + } + return; + } + + objMngr = new UAVObjectManager(); + UAVObjectsInitialize.register(objMngr); + + try { + uavTalk = new UAVTalk(socket.getInputStream(), socket.getOutputStream(), objMngr); + } catch (IOException e) { + Log.e(TAG,"Error starting UAVTalk"); + // TODO Auto-generated catch block + e.printStackTrace(); + return; + } + + Thread inputStream = uavTalk.getInputProcessThread(); + inputStream.start(); + + Telemetry tel = new Telemetry(uavTalk, objMngr); + TelemetryMonitor mon = new TelemetryMonitor(objMngr,tel); + + } +} diff --git a/androidgcs/src/org/openpilot/uavtalk/Telemetry.java b/androidgcs/src/org/openpilot/uavtalk/Telemetry.java index 7f04e344b..b403f85e3 100644 --- a/androidgcs/src/org/openpilot/uavtalk/Telemetry.java +++ b/androidgcs/src/org/openpilot/uavtalk/Telemetry.java @@ -12,8 +12,12 @@ import java.util.TimerTask; import org.openpilot.uavtalk.UAVObject.Acked; +import android.util.Log; + public class Telemetry { + private final String TAG = "Telemetry"; + public class TelemetryStats { public int txBytes; public int rxBytes; @@ -133,7 +137,7 @@ public class Telemetry { /** * Register a new object for periodic updates (if enabled) */ - private void registerObject(UAVObject obj) + private synchronized void registerObject(UAVObject obj) { // Setup object for periodic updates addObject(obj); @@ -145,7 +149,7 @@ public class Telemetry { /** * Add an object in the list used for periodic updates */ - private void addObject(UAVObject obj) + private synchronized void addObject(UAVObject obj) { // Check if object type is already in the list ListIterator li = objList.listIterator(); @@ -169,7 +173,7 @@ public class Telemetry { /** * Update the object's timers */ - private void setUpdatePeriod(UAVObject obj, int periodMs) + private synchronized void setUpdatePeriod(UAVObject obj, int periodMs) { // Find object type (not instance!) and update its period ListIterator li = objList.listIterator(); @@ -186,7 +190,7 @@ public class Telemetry { /** * Connect to all instances of an object depending on the event mask specified */ - private void connectToObjectInstances(UAVObject obj, int eventMask) + private synchronized void connectToObjectInstances(UAVObject obj, int eventMask) { List objs = objMngr.getObjectInstances(obj.getObjID()); ListIterator li = objs.listIterator(); @@ -235,7 +239,7 @@ public class Telemetry { /** * Update an object based on its metadata properties */ - private void updateObject(UAVObject obj) + private synchronized void updateObject(UAVObject obj) { // Get metadata UAVObject.Metadata metadata = obj.getMetadata(); @@ -287,12 +291,12 @@ public class Telemetry { /** * Called when a transaction is successfully completed (uavtalk event) */ - private void transactionCompleted(UAVObject obj) + private synchronized void transactionCompleted(UAVObject obj) { // Check if there is a pending transaction and the objects match if ( transPending && transInfo.obj.getObjID() == obj.getObjID() ) { - // qDebug() << QString("Telemetry: transaction completed for %1").arg(obj->getName()); + Log.d(TAG,"Telemetry: transaction completed for " + obj.getName()); // Complete transaction transTimer.cancel(); transPending = false; @@ -302,16 +306,16 @@ public class Telemetry { processObjectQueue(); } else { - // qDebug() << "Error: received a transaction completed when did not expect it."; + Log.e(TAG,"Error: received a transaction completed when did not expect it."); } } /** * Called when a transaction is not completed within the timeout period (timer event) */ - private void transactionTimeout() + private synchronized void transactionTimeout() { -// qDebug() << "Telemetry: transaction timeout."; + Log.d(TAG,"Telemetry: transaction timeout."); transTimer.cancel(); // Proceed only if there is a pending transaction if ( transPending ) @@ -340,11 +344,11 @@ public class Telemetry { /** * Start an object transaction with UAVTalk, all information is stored in transInfo */ - private void processObjectTransaction() + private synchronized void processObjectTransaction() { if (transPending) { - // qDebug() << tr("Process Object transaction for %1").arg(transInfo.obj->getName()); + Log.d(TAG, "Process Object transaction for " + transInfo.obj.getName()); // Initiate transaction if (transInfo.objRequest) { @@ -366,17 +370,17 @@ public class Telemetry { } } else { - // qDebug() << "Error: inside of processObjectTransaction with no transPending"; + Log.e(TAG,"Error: inside of processObjectTransaction with no transPending"); } } /** * Process the event received from an object */ - private void processObjectUpdates(UAVObject obj, int event, boolean allInstances, boolean priority) + private synchronized void processObjectUpdates(UAVObject obj, int event, boolean allInstances, boolean priority) { // Push event into queue -// qDebug() << "Push event into queue for obj " << QString("%1 event %2").arg(obj->getName()).arg(event); + Log.d(TAG, "Push event into queue for obj " + obj.getName() + " event " + event); ObjectQueueInfo objInfo = new ObjectQueueInfo(); objInfo.obj = obj; objInfo.event = event; @@ -391,7 +395,7 @@ public class Telemetry { { ++txErrors; obj.transactionCompleted(false); - //qxtLog->warning(tr("Telemetry: priority event queue is full, event lost (%1)").arg(obj->getName())); + Log.w(TAG,"Telemetry: priority event queue is full, event lost " + obj.getName()); } } else @@ -410,25 +414,26 @@ public class Telemetry { // If there is no transaction in progress then process event if (!transPending) { - // qDebug() << "No transaction pending, process object queue..."; + processObjectQueue(); + } else { - // qDebug() << "Transaction pending, DO NOT process object queue..."; + Log.d(TAG,"Transaction pending, DO NOT process object queue..."); } } /** * Process events from the object queue */ - private void processObjectQueue() + private synchronized void processObjectQueue() { - // qDebug() << "Process object queue " << tr("- Depth (%1 %2)").arg(objQueue.length()).arg(objPriorityQueue.length()); + Log.d(TAG, "Process object queue - Depth " + objQueue.size() + " priority " + objPriorityQueue.size()); // Don nothing if a transaction is already in progress (should not happen) if (transPending) { -// qxtLog->error("Telemetry: Dequeue while a transaction pending!"); + Log.e(TAG,"Dequeue while a transaction pending"); return; } diff --git a/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java b/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java index eb406923d..e2050fc25 100644 --- a/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java +++ b/androidgcs/src/org/openpilot/uavtalk/TelemetryMonitor.java @@ -55,7 +55,7 @@ public class TelemetryMonitor { /** * Initiate object retrieval, initialize queue with objects to be retrieved. */ - public void startRetrievingObjects() + public synchronized void startRetrievingObjects() { // Clear object queue queue.clear(); @@ -108,7 +108,7 @@ public class TelemetryMonitor { /** * Retrieve the next object in the queue */ - public void retrieveNextObject() + public synchronized void retrieveNextObject() { // If queue is empty return if ( queue.isEmpty() ) @@ -120,7 +120,12 @@ public class TelemetryMonitor { // Get next object from the queue UAVObject obj = queue.remove(0); -// Log.d(TAG, "Retrieving object: " + obj.getName()) ; + if(obj == null) { + Log.e(TAG, "Got null object forom transaction queue"); + return; + } + + Log.d(TAG, "Retrieving object: " + obj.getName()) ; // Connect to object obj.addTransactionCompleted(new Observer() { public void update(Observable observable, Object data) { @@ -137,10 +142,12 @@ public class TelemetryMonitor { /** * Called by the retrieved object when a transaction is completed. */ - public void transactionCompleted(UAVObject obj, boolean success) + public synchronized void transactionCompleted(UAVObject obj, boolean success) { //QMutexLocker locker(mutex); // Disconnect from sending object + Log.d(TAG,"transactionCompleted"); + // TODO: Need to be able to disconnect signals //obj->disconnect(this); objPending = null; diff --git a/androidgcs/src/org/openpilot/uavtalk/UAVObject.java b/androidgcs/src/org/openpilot/uavtalk/UAVObject.java index fac67cabc..b74df9218 100644 --- a/androidgcs/src/org/openpilot/uavtalk/UAVObject.java +++ b/androidgcs/src/org/openpilot/uavtalk/UAVObject.java @@ -17,12 +17,16 @@ public abstract class UAVObject { } public void event () { - setChanged(); - notifyObservers(parent); + synchronized(this) { + setChanged(); + notifyObservers(parent); + } } public void event (Object data) { - setChanged(); - notifyObservers(data); + synchronized(this) { + setChanged(); + notifyObservers(data); + } } }