1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2025-03-01 18:29:16 +01:00

AndroidGCS: Add copyright headers to the UAVTalk/UAVObject/Telemetry implementations.

This commit is contained in:
James Cotton 2012-08-08 09:05:42 -05:00
parent 2008486922
commit dc6b3af707
8 changed files with 436 additions and 226 deletions

View File

@ -1,3 +1,27 @@
/**
******************************************************************************
* @file Telemetry.java
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
* @brief Port of Telemetry.cpp from the GCS. Handles transactions on the
* UAVTalk channel.
* @see The GNU Public License (GPL) Version 3
*
*****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.openpilot.uavtalk; package org.openpilot.uavtalk;
import java.io.IOException; import java.io.IOException;
@ -14,7 +38,7 @@ import java.util.TimerTask;
import android.util.Log; import android.util.Log;
public class Telemetry { public class Telemetry {
private final String TAG = "Telemetry"; private final String TAG = "Telemetry";
public static int LOGLEVEL = 0; public static int LOGLEVEL = 0;
public static boolean WARN = LOGLEVEL > 2; public static boolean WARN = LOGLEVEL > 2;
@ -31,7 +55,7 @@ public class Telemetry {
public int rxErrors; public int rxErrors;
public int txRetries; public int txRetries;
} ; } ;
class ObjectTimeInfo { class ObjectTimeInfo {
UAVObject obj; UAVObject obj;
int updatePeriodMs; /** Update period in ms or 0 if no periodic updates are needed */ int updatePeriodMs; /** Update period in ms or 0 if no periodic updates are needed */
@ -51,7 +75,7 @@ public class Telemetry {
int retriesRemaining; int retriesRemaining;
boolean acked; boolean acked;
} ; } ;
/** /**
* Events generated by objects. Not enum because used in mask. * Events generated by objects. Not enum because used in mask.
*/ */
@ -59,7 +83,7 @@ public class Telemetry {
private static final int EV_UPDATED = 0x02; /** Object data updated by changing the data structure */ private static final int EV_UPDATED = 0x02; /** Object data updated by changing the data structure */
private static final int EV_UPDATED_MANUAL = 0x04; /** Object update event manually generated */ private static final int EV_UPDATED_MANUAL = 0x04; /** Object update event manually generated */
private static final int EV_UPDATE_REQ = 0x08; /** Request to update object data */ private static final int EV_UPDATE_REQ = 0x08; /** Request to update object data */
/** /**
* Constructor * Constructor
*/ */
@ -71,33 +95,36 @@ public class Telemetry {
// Process all objects in the list // Process all objects in the list
List< List<UAVObject> > objs = objMngr.getObjects(); List< List<UAVObject> > objs = objMngr.getObjects();
ListIterator<List<UAVObject>> li = objs.listIterator(); ListIterator<List<UAVObject>> li = objs.listIterator();
while(li.hasNext()) while(li.hasNext())
registerObject(li.next().get(0)); // we only need to register one instance per object type registerObject(li.next().get(0)); // we only need to register one instance per object type
// Listen to new object creations // Listen to new object creations
objMngr.addNewInstanceObserver(new Observer() { objMngr.addNewInstanceObserver(new Observer() {
@Override
public void update(Observable observable, Object data) { public void update(Observable observable, Object data) {
newInstance((UAVObject) data); newInstance((UAVObject) data);
} }
}); });
objMngr.addNewObjectObserver(new Observer() { objMngr.addNewObjectObserver(new Observer() {
@Override
public void update(Observable observable, Object data) { public void update(Observable observable, Object data) {
newObject((UAVObject) data); newObject((UAVObject) data);
} }
}); });
// Listen to transaction completions // Listen to transaction completions
utalk.addObserver(new Observer() { utalk.addObserver(new Observer() {
@Override
public void update(Observable observable, Object data) { public void update(Observable observable, Object data) {
try { try {
transactionCompleted((UAVObject) data); transactionCompleted((UAVObject) data);
} catch (IOException e) { } catch (IOException e) {
// Disconnect when stream fails // Disconnect when stream fails
observable.deleteObserver(this); observable.deleteObserver(this);
} }
} }
}); });
// Get GCS stats object // Get GCS stats object
gcsStatsObj = objMngr.getObject("GCSTelemetryStats"); gcsStatsObj = objMngr.getObject("GCSTelemetryStats");
@ -110,16 +137,16 @@ public class Telemetry {
txErrors = 0; txErrors = 0;
txRetries = 0; txRetries = 0;
} }
synchronized void transTimerSetPeriod(int periodMs) { synchronized void transTimerSetPeriod(int periodMs) {
if(transTimerTask != null) if(transTimerTask != null)
transTimerTask.cancel(); transTimerTask.cancel();
if(transTimer != null) if(transTimer != null)
transTimer.purge(); transTimer.purge();
transTimer = new Timer(); transTimer = new Timer();
transTimerTask = new TimerTask() { transTimerTask = new TimerTask() {
@Override @Override
public void run() { public void run() {
@ -128,11 +155,11 @@ public class Telemetry {
} catch (IOException e) { } catch (IOException e) {
cancel(); cancel();
} }
} }
}; };
transTimer.schedule(transTimerTask, periodMs, periodMs); transTimer.schedule(transTimerTask, periodMs, periodMs);
} }
synchronized void updateTimerSetPeriod(int periodMs) { synchronized void updateTimerSetPeriod(int periodMs) {
if (updateTimer != null) { if (updateTimer != null) {
updateTimer.cancel(); updateTimer.cancel();
@ -152,7 +179,7 @@ public class Telemetry {
updateTimerTask.cancel(); updateTimerTask.cancel();
updateTimer.cancel(); updateTimer.cancel();
} }
} }
}; };
updateTimer.schedule(updateTimerTask, periodMs, periodMs); updateTimer.schedule(updateTimerTask, periodMs, periodMs);
@ -223,11 +250,12 @@ public class Telemetry {
obj = li.next(); obj = li.next();
//TODO: Disconnect all //TODO: Disconnect all
// obj.disconnect(this); // obj.disconnect(this);
// Connect only the selected events // Connect only the selected events
if ( (eventMask&EV_UNPACKED) != 0) if ( (eventMask&EV_UNPACKED) != 0)
{ {
obj.addUnpackedObserver(new Observer() { obj.addUnpackedObserver(new Observer() {
@Override
public void update(Observable observable, Object data) { public void update(Observable observable, Object data) {
try { try {
objectUnpacked( (UAVObject) data); objectUnpacked( (UAVObject) data);
@ -235,12 +263,13 @@ public class Telemetry {
// TODO Auto-generated catch block // TODO Auto-generated catch block
e.printStackTrace(); e.printStackTrace();
} }
} }
}); });
} }
if ( (eventMask&EV_UPDATED) != 0) if ( (eventMask&EV_UPDATED) != 0)
{ {
obj.addUpdatedAutoObserver(new Observer() { obj.addUpdatedAutoObserver(new Observer() {
@Override
public void update(Observable observable, Object data) { public void update(Observable observable, Object data) {
try { try {
objectUpdatedAuto( (UAVObject) data); objectUpdatedAuto( (UAVObject) data);
@ -248,12 +277,13 @@ public class Telemetry {
// TODO Auto-generated catch block // TODO Auto-generated catch block
e.printStackTrace(); e.printStackTrace();
} }
} }
}); });
} }
if ( (eventMask&EV_UPDATED_MANUAL) != 0) if ( (eventMask&EV_UPDATED_MANUAL) != 0)
{ {
obj.addUpdatedManualObserver(new Observer() { obj.addUpdatedManualObserver(new Observer() {
@Override
public void update(Observable observable, Object data) { public void update(Observable observable, Object data) {
try { try {
objectUpdatedManual( (UAVObject) data); objectUpdatedManual( (UAVObject) data);
@ -261,12 +291,13 @@ public class Telemetry {
// TODO Auto-generated catch block // TODO Auto-generated catch block
e.printStackTrace(); e.printStackTrace();
} }
} }
}); });
} }
if ( (eventMask&EV_UPDATE_REQ) != 0) if ( (eventMask&EV_UPDATE_REQ) != 0)
{ {
obj.addUpdateRequestedObserver(new Observer() { obj.addUpdateRequestedObserver(new Observer() {
@Override
public void update(Observable observable, Object data) { public void update(Observable observable, Object data) {
try { try {
updateRequested( (UAVObject) data); updateRequested( (UAVObject) data);
@ -274,7 +305,7 @@ public class Telemetry {
// TODO Auto-generated catch block // TODO Auto-generated catch block
e.printStackTrace(); e.printStackTrace();
} }
} }
}); });
} }
} }
@ -331,7 +362,7 @@ public class Telemetry {
/** /**
* Called when a transaction is successfully completed (uavtalk event) * Called when a transaction is successfully completed (uavtalk event)
* @throws IOException * @throws IOException
*/ */
private synchronized void transactionCompleted(UAVObject obj) throws IOException private synchronized void transactionCompleted(UAVObject obj) throws IOException
{ {
@ -355,7 +386,7 @@ public class Telemetry {
/** /**
* Called when a transaction is not completed within the timeout period (timer event) * Called when a transaction is not completed within the timeout period (timer event)
* @throws IOException * @throws IOException
*/ */
private synchronized void transactionTimeout() throws IOException private synchronized void transactionTimeout() throws IOException
{ {
@ -387,7 +418,7 @@ public class Telemetry {
/** /**
* Start an object transaction with UAVTalk, all information is stored in transInfo * Start an object transaction with UAVTalk, all information is stored in transInfo
* @throws IOException * @throws IOException
*/ */
private synchronized void processObjectTransaction() throws IOException private synchronized void processObjectTransaction() throws IOException
{ {
@ -421,7 +452,7 @@ public class Telemetry {
/** /**
* Process the event received from an object * Process the event received from an object
* @throws IOException * @throws IOException
*/ */
private synchronized void processObjectUpdates(UAVObject obj, int event, boolean allInstances, boolean priority) throws IOException private synchronized void processObjectUpdates(UAVObject obj, int event, boolean allInstances, boolean priority) throws IOException
{ {
@ -450,7 +481,7 @@ public class Telemetry {
else else
{ {
if ( objQueue.size() < MAX_QUEUE_SIZE ) if ( objQueue.size() < MAX_QUEUE_SIZE )
{ {
objQueue.add(objInfo); objQueue.add(objInfo);
} }
else else
@ -469,7 +500,7 @@ public class Telemetry {
/** /**
* Process events from the object queue * Process events from the object queue
* @throws IOException * @throws IOException
*/ */
private synchronized void processObjectQueue() throws IOException private synchronized void processObjectQueue() throws IOException
{ {
@ -536,7 +567,7 @@ public class Telemetry {
} }
// If this is a metaobject then make necessary telemetry updates // If this is a metaobject then make necessary telemetry updates
if (objInfo.obj.isMetadata()) if (objInfo.obj.isMetadata())
{ {
UAVMetaObject metaobj = (UAVMetaObject) objInfo.obj; UAVMetaObject metaobj = (UAVMetaObject) objInfo.obj;
updateObject( metaobj.getParentObject() ); updateObject( metaobj.getParentObject() );
@ -554,11 +585,11 @@ public class Telemetry {
/** /**
* Check is any objects are pending for periodic updates * Check is any objects are pending for periodic updates
* TODO: Clean-up * TODO: Clean-up
* @throws IOException * @throws IOException
*/ */
private synchronized void processPeriodicUpdates() throws IOException private synchronized void processPeriodicUpdates() throws IOException
{ {
if (DEBUG) Log.d(TAG, "processPeriodicUpdates()"); if (DEBUG) Log.d(TAG, "processPeriodicUpdates()");
// Stop timer // Stop timer
updateTimer.cancel(); updateTimer.cancel();
@ -669,7 +700,7 @@ public class Telemetry {
{ {
registerObject(obj); registerObject(obj);
} }
/** /**
* Stop all the telemetry timers * Stop all the telemetry timers
*/ */
@ -692,24 +723,24 @@ public class Telemetry {
/** /**
* Private variables * Private variables
*/ */
private UAVObjectManager objMngr; private final UAVObjectManager objMngr;
private UAVTalk utalk; private final UAVTalk utalk;
private UAVObject gcsStatsObj; private UAVObject gcsStatsObj;
private List<ObjectTimeInfo> objList = new ArrayList<ObjectTimeInfo>(); private final List<ObjectTimeInfo> objList = new ArrayList<ObjectTimeInfo>();
private Queue<ObjectQueueInfo> objQueue = new LinkedList<ObjectQueueInfo>(); private final Queue<ObjectQueueInfo> objQueue = new LinkedList<ObjectQueueInfo>();
private Queue<ObjectQueueInfo> objPriorityQueue = new LinkedList<ObjectQueueInfo>(); private final Queue<ObjectQueueInfo> objPriorityQueue = new LinkedList<ObjectQueueInfo>();
private ObjectTransactionInfo transInfo = new ObjectTransactionInfo(); private final ObjectTransactionInfo transInfo = new ObjectTransactionInfo();
private boolean transPending; private boolean transPending;
private Timer updateTimer; private Timer updateTimer;
private TimerTask updateTimerTask; private TimerTask updateTimerTask;
private Timer transTimer; private Timer transTimer;
private TimerTask transTimerTask; private TimerTask transTimerTask;
private int timeToNextUpdateMs; private int timeToNextUpdateMs;
private int txErrors; private int txErrors;
private int txRetries; private int txRetries;
/** /**
* Private constants * Private constants
*/ */
@ -718,7 +749,7 @@ public class Telemetry {
private static final int MAX_UPDATE_PERIOD_MS = 1000; private static final int MAX_UPDATE_PERIOD_MS = 1000;
private static final int MIN_UPDATE_PERIOD_MS = 1; private static final int MIN_UPDATE_PERIOD_MS = 1;
private static final int MAX_QUEUE_SIZE = 20; private static final int MAX_QUEUE_SIZE = 20;
} }

View File

@ -1,3 +1,28 @@
/**
******************************************************************************
* @file TelemetryMonitor.java
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
* @brief High level monitoring of telemetry to handle connection and
* disconnection and then signal the rest of the application.
* This also makes sure to fetch all objects on initial connection.
* @see The GNU Public License (GPL) Version 3
*
*****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.openpilot.uavtalk; package org.openpilot.uavtalk;
import java.io.IOException; import java.io.IOException;
@ -22,22 +47,22 @@ public class TelemetryMonitor extends Observable{
static final int STATS_CONNECT_PERIOD_MS = 1000; static final int STATS_CONNECT_PERIOD_MS = 1000;
static final int CONNECTION_TIMEOUT_MS = 8000; static final int CONNECTION_TIMEOUT_MS = 8000;
private UAVObjectManager objMngr; private final UAVObjectManager objMngr;
private Telemetry tel; private final Telemetry tel;
// private UAVObject objPending; // private UAVObject objPending;
private UAVObject gcsStatsObj; private UAVObject gcsStatsObj;
private UAVObject flightStatsObj; private UAVObject flightStatsObj;
private Timer periodicTask; private Timer periodicTask;
private int currentPeriod; private int currentPeriod;
private long lastUpdateTime; private long lastUpdateTime;
private List<UAVObject> queue; private final List<UAVObject> queue;
private boolean connected = false; private boolean connected = false;
private boolean objects_updated = false; private boolean objects_updated = false;
public boolean getConnected() { return connected; }; public boolean getConnected() { return connected; };
public boolean getObjectsUpdated() { return objects_updated; }; public boolean getObjectsUpdated() { return objects_updated; };
public TelemetryMonitor(UAVObjectManager objMngr, Telemetry tel) public TelemetryMonitor(UAVObjectManager objMngr, Telemetry tel)
{ {
this.objMngr = objMngr; this.objMngr = objMngr;
@ -50,6 +75,7 @@ public class TelemetryMonitor extends Observable{
flightStatsObj = objMngr.getObject("FlightTelemetryStats"); flightStatsObj = objMngr.getObject("FlightTelemetryStats");
flightStatsObj.addUpdatedObserver(new Observer() { flightStatsObj.addUpdatedObserver(new Observer() {
@Override
public void update(Observable observable, Object data) { public void update(Observable observable, Object data) {
try { try {
flightStatsUpdated((UAVObject) data); flightStatsUpdated((UAVObject) data);
@ -59,7 +85,7 @@ public class TelemetryMonitor extends Observable{
// or fix the stream? // or fix the stream?
flightStatsObj.removeUpdatedObserver(this); flightStatsObj.removeUpdatedObserver(this);
} }
} }
}); });
// Start update timer // Start update timer
@ -68,17 +94,17 @@ public class TelemetryMonitor extends Observable{
/** /**
* Initiate object retrieval, initialize queue with objects to be retrieved. * Initiate object retrieval, initialize queue with objects to be retrieved.
* @throws IOException * @throws IOException
*/ */
public synchronized void startRetrievingObjects() throws IOException public synchronized void startRetrievingObjects() throws IOException
{ {
if (DEBUG) Log.d(TAG, "Start retrieving objects"); if (DEBUG) Log.d(TAG, "Start retrieving objects");
// Clear object queue // Clear object queue
queue.clear(); queue.clear();
// Get all objects, add metaobjects, settings and data objects with OnChange update mode to the queue // Get all objects, add metaobjects, settings and data objects with OnChange update mode to the queue
List< List<UAVObject> > objs = objMngr.getObjects(); List< List<UAVObject> > objs = objMngr.getObjects();
ListIterator<List<UAVObject>> objListIterator = objs.listIterator(); ListIterator<List<UAVObject>> objListIterator = objs.listIterator();
while( objListIterator.hasNext() ) while( objListIterator.hasNext() )
{ {
@ -121,7 +147,7 @@ public class TelemetryMonitor extends Observable{
/** /**
* Retrieve the next object in the queue * Retrieve the next object in the queue
* @throws IOException * @throws IOException
*/ */
public synchronized void retrieveNextObject() throws IOException public synchronized void retrieveNextObject() throws IOException
{ {
@ -136,16 +162,17 @@ public class TelemetryMonitor extends Observable{
} }
// Get next object from the queue // Get next object from the queue
UAVObject obj = queue.remove(0); UAVObject obj = queue.remove(0);
if(obj == null) { if(obj == null) {
throw new Error("Got null object forom transaction queue"); throw new Error("Got null object forom transaction queue");
} }
if (DEBUG) Log.d(TAG, "Retrieving object: " + obj.getName()) ; if (DEBUG) Log.d(TAG, "Retrieving object: " + obj.getName()) ;
// Connect to object // Connect to object
// TODO: Does this need to stay here permanently? This appears to be used for setup mainly // TODO: Does this need to stay here permanently? This appears to be used for setup mainly
obj.addTransactionCompleted(new Observer() { obj.addTransactionCompleted(new Observer() {
@Override
public void update(Observable observable, Object data) { public void update(Observable observable, Object data) {
UAVObject.TransactionResult result = (UAVObject.TransactionResult) 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);
@ -155,7 +182,7 @@ public class TelemetryMonitor extends Observable{
// When the telemetry stream is broken disconnect these updates // When the telemetry stream is broken disconnect these updates
observable.deleteObserver(this); observable.deleteObserver(this);
} }
} }
}); });
// Request update // Request update
@ -165,7 +192,7 @@ public class TelemetryMonitor extends Observable{
/** /**
* Called by the retrieved object when a transaction is completed. * Called by the retrieved object when a transaction is completed.
* @throws IOException * @throws IOException
*/ */
public synchronized void transactionCompleted(UAVObject obj, boolean success) throws IOException public synchronized void transactionCompleted(UAVObject obj, boolean success) throws IOException
{ {
@ -175,12 +202,12 @@ public class TelemetryMonitor extends Observable{
// TODO: Need to be able to disconnect signals // TODO: Need to be able to disconnect signals
//obj->disconnect(this); //obj->disconnect(this);
// objPending = null; // objPending = null;
if(!success) { if(!success) {
//Log.e(TAG, "Transaction failed: " + obj.getName() + " sending again."); //Log.e(TAG, "Transaction failed: " + obj.getName() + " sending again.");
return; return;
} }
// Process next object if telemetry is still available // Process next object if telemetry is still available
if ( ((String) gcsStatsObj.getField("Status").getValue()).compareTo("Connected") == 0 ) if ( ((String) gcsStatsObj.getField("Status").getValue()).compareTo("Connected") == 0 )
{ {
@ -194,7 +221,7 @@ public class TelemetryMonitor extends Observable{
/** /**
* Called each time the flight stats object is updated by the autopilot * Called each time the flight stats object is updated by the autopilot
* @throws IOException * @throws IOException
*/ */
public synchronized void flightStatsUpdated(UAVObject obj) throws IOException public synchronized void flightStatsUpdated(UAVObject obj) throws IOException
{ {
@ -213,7 +240,7 @@ public class TelemetryMonitor extends Observable{
private long lastStatsTime; private long lastStatsTime;
/** /**
* Called periodically to update the statistics and connection status. * Called periodically to update the statistics and connection status.
* @throws IOException * @throws IOException
*/ */
public synchronized void processStatsUpdates() throws IOException public synchronized void processStatsUpdates() throws IOException
{ {
@ -222,14 +249,14 @@ public class TelemetryMonitor extends Observable{
Telemetry.TelemetryStats telStats = tel.getStats(); 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 // Need to compute time because this update is not regular enough
float dT = (float) (System.currentTimeMillis() - lastStatsTime) / 1000.0f; float dT = (System.currentTimeMillis() - lastStatsTime) / 1000.0f;
lastStatsTime = System.currentTimeMillis(); lastStatsTime = System.currentTimeMillis();
// Update stats object // Update stats object
gcsStatsObj.getField("RxDataRate").setDouble( (float)telStats.rxBytes / dT ); gcsStatsObj.getField("RxDataRate").setDouble( telStats.rxBytes / dT );
gcsStatsObj.getField("TxDataRate").setDouble( (float)telStats.txBytes / dT ); gcsStatsObj.getField("TxDataRate").setDouble( telStats.txBytes / dT );
UAVObjectField field = gcsStatsObj.getField("RxFailures"); UAVObjectField field = gcsStatsObj.getField("RxFailures");
field.setDouble(field.getDouble() + telStats.rxErrors); field.setDouble(field.getDouble() + telStats.rxErrors);
field = gcsStatsObj.getField("TxFailures"); field = gcsStatsObj.getField("TxFailures");
@ -240,7 +267,7 @@ public class TelemetryMonitor extends Observable{
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 // Check for a connection timeout
boolean connectionTimeout; boolean connectionTimeout;
if ( telStats.rxObjects > 0 ) if ( telStats.rxObjects > 0 )
@ -266,7 +293,7 @@ public class TelemetryMonitor extends Observable{
} }
UAVObjectField statusField = gcsStatsObj.getField("Status"); UAVObjectField statusField = gcsStatsObj.getField("Status");
String oldStatus = new String((String) statusField.getValue()); 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 ) if ( oldStatus.compareTo("Disconnected") == 0 )
@ -294,11 +321,11 @@ public class TelemetryMonitor extends Observable{
// Force telemetry update if not yet connected // Force telemetry update if not yet connected
boolean gcsStatusChanged = !oldStatus.equals(statusField.getValue()); boolean gcsStatusChanged = !oldStatus.equals(statusField.getValue());
boolean gcsConnected = statusField.getValue().equals("Connected"); boolean gcsConnected = statusField.getValue().equals("Connected");
boolean gcsDisconnected = statusField.getValue().equals("Disconnected"); boolean gcsDisconnected = statusField.getValue().equals("Disconnected");
boolean flightConnected = flightStatsObj.getField("Status").equals("Connected"); boolean flightConnected = flightStatsObj.getField("Status").equals("Connected");
if ( !gcsConnected || !flightConnected ) if ( !gcsConnected || !flightConnected )
{ {
if (DEBUG) Log.d(TAG,"Sending gcs status"); if (DEBUG) Log.d(TAG,"Sending gcs status");
@ -323,7 +350,7 @@ public class TelemetryMonitor extends Observable{
objects_updated = false; objects_updated = false;
setChanged(); setChanged();
} }
if (DEBUG) Log.d(TAG, "processStatsUpdates() - before notify"); if (DEBUG) Log.d(TAG, "processStatsUpdates() - before notify");
notifyObservers(); notifyObservers();
if (DEBUG) Log.d(TAG, "processStatsUpdates() - after notify"); if (DEBUG) Log.d(TAG, "processStatsUpdates() - after notify");
@ -344,11 +371,11 @@ public class TelemetryMonitor extends Observable{
} catch (IOException e) { } 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(); periodicTask.cancel();
} }
} }
}, currentPeriod, currentPeriod); }, currentPeriod, currentPeriod);
} }
public void stopMonitor() public void stopMonitor()
{ {
periodicTask.cancel(); periodicTask.cancel();

View File

@ -1,11 +1,34 @@
/**
******************************************************************************
* @file UAVDataObject.java
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
* @brief The base object for all UAVO data.
* @see The GNU Public License (GPL) Version 3
*
*****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.openpilot.uavtalk; package org.openpilot.uavtalk;
public abstract class UAVDataObject extends UAVObject { public abstract class UAVDataObject extends UAVObject {
/** /**
* @brief Constructor for UAVDataObject * @brief Constructor for UAVDataObject
* @param objID the object id to be created * @param objID the object id to be created
* @param isSingleInst * @param isSingleInst
* @param isSet * @param isSet
* @param name * @param name
*/ */
@ -24,6 +47,7 @@ public abstract class UAVDataObject extends UAVObject {
super.initialize(instID); super.initialize(instID);
} }
@Override
public boolean isMetadata() { return false; }; public boolean isMetadata() { return false; };
/** /**
* Assign a metaobject * Assign a metaobject
@ -45,6 +69,7 @@ public abstract class UAVDataObject extends UAVObject {
/** /**
* Set the object's metadata * Set the object's metadata
*/ */
@Override
public void setMetadata(Metadata mdata) public void setMetadata(Metadata mdata)
{ {
if ( mobj != null ) if ( mobj != null )
@ -56,6 +81,7 @@ public abstract class UAVDataObject extends UAVObject {
/** /**
* Get the object's metadata * Get the object's metadata
*/ */
@Override
public Metadata getMetadata() public Metadata getMetadata()
{ {
if ( mobj != null) if ( mobj != null)
@ -75,13 +101,13 @@ public abstract class UAVDataObject extends UAVObject {
{ {
return mobj; return mobj;
} }
// TODO: Make abstract // TODO: Make abstract
public UAVDataObject clone(long instID) { public UAVDataObject clone(long instID) {
return (UAVDataObject) super.clone(); return (UAVDataObject) super.clone();
} }
private UAVMetaObject mobj; private UAVMetaObject mobj;
private boolean isSet; private final boolean isSet;
} }

View File

@ -1,3 +1,26 @@
/**
******************************************************************************
* @file UAVMetaObject.java
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
* @brief Base object for all UAVO meta data
* @see The GNU Public License (GPL) Version 3
*
*****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.openpilot.uavtalk; package org.openpilot.uavtalk;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
@ -10,7 +33,7 @@ public class UAVMetaObject extends UAVObject {
public UAVMetaObject(long objID, String name, UAVDataObject parent) throws Exception { public UAVMetaObject(long objID, String name, UAVDataObject parent) throws Exception {
super(objID, true, name); super(objID, true, name);
this.parent = parent; this.parent = parent;
ownMetadata = new Metadata(); ownMetadata = new Metadata();
ownMetadata.flags = 0; // TODO: Fix flags ownMetadata.flags = 0; // TODO: Fix flags
@ -27,7 +50,7 @@ public class UAVMetaObject extends UAVObject {
modesBitField.add("FlightUpdateOnChange"); modesBitField.add("FlightUpdateOnChange");
modesBitField.add("GCSUpdatePeriodic"); modesBitField.add("GCSUpdatePeriodic");
modesBitField.add("GCSUpdateOnChange"); modesBitField.add("GCSUpdateOnChange");
List<UAVObjectField> fields = new ArrayList<UAVObjectField>(); List<UAVObjectField> fields = new ArrayList<UAVObjectField>();
fields.add( new UAVObjectField("Modes", "", UAVObjectField.FieldType.BITFIELD, 1, modesBitField) ); fields.add( new UAVObjectField("Modes", "", UAVObjectField.FieldType.BITFIELD, 1, modesBitField) );
fields.add( new UAVObjectField("Flight Telemetry Update Period", "ms", UAVObjectField.FieldType.UINT16, 1, null) ); fields.add( new UAVObjectField("Flight Telemetry Update Period", "ms", UAVObjectField.FieldType.UINT16, 1, null) );
@ -47,12 +70,12 @@ public class UAVMetaObject extends UAVObject {
initializeFields(fields, ByteBuffer.allocate(numBytes), numBytes); initializeFields(fields, ByteBuffer.allocate(numBytes), numBytes);
// Setup metadata of parent // Setup metadata of parent
parentMetadata = parent.getDefaultMetadata(); parentMetadata = parent.getDefaultMetadata();
} }
@Override @Override
public boolean isMetadata() { public boolean isMetadata() {
return true; return true;
}; };
/** /**
@ -67,6 +90,7 @@ public class UAVMetaObject extends UAVObject {
* Set the metadata of the metaobject, this function will * Set the metadata of the metaobject, this function will
* do nothing since metaobjects have read-only metadata. * do nothing since metaobjects have read-only metadata.
*/ */
@Override
public void setMetadata(Metadata mdata) public void setMetadata(Metadata mdata)
{ {
return; // can not update metaobject's metadata return; // can not update metaobject's metadata
@ -75,6 +99,7 @@ public class UAVMetaObject extends UAVObject {
/** /**
* Get the metadata of the metaobject * Get the metadata of the metaobject
*/ */
@Override
public Metadata getMetadata() public Metadata getMetadata()
{ {
return ownMetadata; return ownMetadata;
@ -83,6 +108,7 @@ public class UAVMetaObject extends UAVObject {
/** /**
* Get the default metadata * Get the default metadata
*/ */
@Override
public Metadata getDefaultMetadata() public Metadata getDefaultMetadata()
{ {
return ownMetadata; return ownMetadata;
@ -110,8 +136,8 @@ public class UAVMetaObject extends UAVObject {
} }
private UAVObject parent; private final UAVObject parent;
private Metadata ownMetadata; private final Metadata ownMetadata;
private Metadata parentMetadata; private Metadata parentMetadata;

View File

@ -1,17 +1,40 @@
/**
******************************************************************************
* @file UAVObject.java
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
* @brief Base object for UAVDataObject and UAVMetaObject.
* @see The GNU Public License (GPL) Version 3
*
*****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.openpilot.uavtalk; package org.openpilot.uavtalk;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.ListIterator; import java.util.ListIterator;
import java.util.Observer;
import java.util.Observable; import java.util.Observable;
import java.util.Observer;
public abstract class UAVObject { public abstract class UAVObject {
public class CallbackListener extends Observable { public class CallbackListener extends Observable {
private UAVObject parent; private final UAVObject parent;
public CallbackListener(UAVObject parent) { public CallbackListener(UAVObject parent) {
this.parent = parent; this.parent = parent;
} }
@ -29,7 +52,7 @@ public abstract class UAVObject {
} }
} }
} }
public class TransactionResult { public class TransactionResult {
public UAVObject obj; public UAVObject obj;
public boolean success; public boolean success;
@ -38,8 +61,8 @@ public abstract class UAVObject {
this.success = success; this.success = success;
} }
} }
private CallbackListener transactionCompletedListeners = new CallbackListener(this); private final CallbackListener transactionCompletedListeners = new CallbackListener(this);
public void addTransactionCompleted(Observer o) { public void addTransactionCompleted(Observer o) {
synchronized(transactionCompletedListeners) { synchronized(transactionCompletedListeners) {
transactionCompletedListeners.addObserver(o); transactionCompletedListeners.addObserver(o);
@ -55,8 +78,8 @@ public abstract class UAVObject {
transactionCompletedListeners.event(new TransactionResult(this,status)); transactionCompletedListeners.event(new TransactionResult(this,status));
} }
} }
private CallbackListener updatedListeners = new CallbackListener(this); private final CallbackListener updatedListeners = new CallbackListener(this);
public void removeUpdatedObserver(Observer o) { public void removeUpdatedObserver(Observer o) {
synchronized(updatedListeners) { synchronized(updatedListeners) {
updatedListeners.deleteObserver(o); updatedListeners.deleteObserver(o);
@ -75,8 +98,8 @@ public abstract class UAVObject {
updatedManual(); updatedManual();
} }
public void updated() { updated(true); }; public void updated() { updated(true); };
private CallbackListener unpackedListeners = new CallbackListener(this); private final CallbackListener unpackedListeners = new CallbackListener(this);
public void addUnpackedObserver(Observer o) { public void addUnpackedObserver(Observer o) {
synchronized(unpackedListeners) { synchronized(unpackedListeners) {
unpackedListeners.addObserver(o); unpackedListeners.addObserver(o);
@ -88,7 +111,7 @@ public abstract class UAVObject {
} }
} }
private CallbackListener updatedAutoListeners = new CallbackListener(this); private final CallbackListener updatedAutoListeners = new CallbackListener(this);
public void addUpdatedAutoObserver(Observer o) { public void addUpdatedAutoObserver(Observer o) {
synchronized(updatedAutoListeners) { synchronized(updatedAutoListeners) {
updatedAutoListeners.addObserver(o); updatedAutoListeners.addObserver(o);
@ -100,7 +123,7 @@ public abstract class UAVObject {
} }
} }
private CallbackListener updatedManualListeners = new CallbackListener(this); private final CallbackListener updatedManualListeners = new CallbackListener(this);
public void addUpdatedManualObserver(Observer o) { public void addUpdatedManualObserver(Observer o) {
synchronized(updatedManualListeners) { synchronized(updatedManualListeners) {
updatedManualListeners.addObserver(o); updatedManualListeners.addObserver(o);
@ -112,7 +135,7 @@ public abstract class UAVObject {
} }
} }
private CallbackListener updateRequestedListeners = new CallbackListener(this); private final CallbackListener updateRequestedListeners = new CallbackListener(this);
public void addUpdateRequestedObserver(Observer o) { public void addUpdateRequestedObserver(Observer o) {
synchronized(updateRequestedListeners) { synchronized(updateRequestedListeners) {
updateRequestedListeners.addObserver(o); updateRequestedListeners.addObserver(o);
@ -125,7 +148,7 @@ public abstract class UAVObject {
} }
public abstract boolean isMetadata(); public abstract boolean isMetadata();
/** /**
* Object update mode * Object update mode
*/ */
@ -172,10 +195,10 @@ public abstract class UAVObject {
/** Update period used by the telemetry module (only if telemetry mode is PERIODIC) */ /** Update period used by the telemetry module (only if telemetry mode is PERIODIC) */
public int flightTelemetryUpdatePeriod; public int flightTelemetryUpdatePeriod;
/** Update period used by the GCS (only if telemetry mode is PERIODIC) */ /** Update period used by the GCS (only if telemetry mode is PERIODIC) */
public int gcsTelemetryUpdatePeriod; public int gcsTelemetryUpdatePeriod;
/** Update period used by the GCS (only if telemetry mode is PERIODIC) */ /** Update period used by the GCS (only if telemetry mode is PERIODIC) */
public int loggingUpdatePeriod; public int loggingUpdatePeriod;
/** /**
@ -194,7 +217,7 @@ public abstract class UAVObject {
private void SET_BITS(int shift, int value, int mask) { private void SET_BITS(int shift, int value, int mask) {
this.flags = (this.flags & ~(mask << shift)) | (value << shift); this.flags = (this.flags & ~(mask << shift)) | (value << shift);
} }
/** /**
* Get the UAVObject metadata access member * Get the UAVObject metadata access member
* \return the access type * \return the access type
@ -219,7 +242,7 @@ public abstract class UAVObject {
* \return the GCS access type * \return the GCS access type
*/ */
public AccessMode GetGcsAccess() public AccessMode GetGcsAccess()
{ {
return AccessModeEnum((this.flags >> UAVOBJ_GCS_ACCESS_SHIFT) & 1); return AccessModeEnum((this.flags >> UAVOBJ_GCS_ACCESS_SHIFT) & 1);
} }
@ -382,7 +405,7 @@ public abstract class UAVObject {
/** /**
* Initialize objects' data fields * Initialize objects' data fields
* *
* @param fields * @param fields
* List of fields held by the object * List of fields held by the object
* @param data * @param data
@ -434,7 +457,7 @@ public abstract class UAVObject {
/** /**
* Get the description of the object * Get the description of the object
* *
* @return The description of the object * @return The description of the object
*/ */
public String getDescription() { public String getDescription() {
@ -443,7 +466,7 @@ public abstract class UAVObject {
/** /**
* Set the description of the object * Set the description of the object
* *
* @param The * @param The
* description of the object * description of the object
* @return * @return
@ -525,7 +548,7 @@ public abstract class UAVObject {
/** /**
* Get a specific field * Get a specific field
* *
* @throws Exception * @throws Exception
* @returns The field or NULL if not found * @returns The field or NULL if not found
*/ */
@ -543,7 +566,7 @@ public abstract class UAVObject {
/** /**
* Pack the object data into a byte array * Pack the object data into a byte array
* *
* @param dataOut * @param dataOut
* ByteBuffer to receive the data. * ByteBuffer to receive the data.
* @throws Exception * @throws Exception
@ -565,7 +588,7 @@ public abstract class UAVObject {
/** /**
* Unpack the object data from a byte array * Unpack the object data from a byte array
* *
* @param dataIn * @param dataIn
* The ByteBuffer to pull data from * The ByteBuffer to pull data from
* @throws Exception * @throws Exception
@ -582,11 +605,11 @@ public abstract class UAVObject {
UAVObjectField field = li.next(); UAVObjectField field = li.next();
numBytes += field.unpack(dataIn); numBytes += field.unpack(dataIn);
} }
// Trigger all the listeners for the unpack event // Trigger all the listeners for the unpack event
unpacked(); unpacked();
updated(false); updated(false);
return numBytes; return numBytes;
} }
@ -774,6 +797,7 @@ public abstract class UAVObject {
/** /**
* Java specific functions * Java specific functions
*/ */
@Override
public synchronized UAVObject clone() { public synchronized UAVObject clone() {
UAVObject newObj = clone(); UAVObject newObj = clone();
List<UAVObjectField> newFields = new ArrayList<UAVObjectField>(); List<UAVObjectField> newFields = new ArrayList<UAVObjectField>();

View File

@ -1,3 +1,26 @@
/**
******************************************************************************
* @file Telemetry.java
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
* @brief Implementation of all the UAVObjectFields.
* @see The GNU Public License (GPL) Version 3
*
*****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.openpilot.uavtalk; package org.openpilot.uavtalk;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
@ -6,7 +29,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
public class UAVObjectField { public class UAVObjectField {
public enum FieldType { INT8, INT16, INT32, UINT8, UINT16, UINT32, FLOAT32, ENUM, BITFIELD, STRING }; public enum FieldType { INT8, INT16, INT32, UINT8, UINT16, UINT32, FLOAT32, ENUM, BITFIELD, STRING };
public UAVObjectField(String name, String units, FieldType type, int numElements, List<String> options) { public UAVObjectField(String name, String units, FieldType type, int numElements, List<String> options) {
@ -17,26 +40,26 @@ public class UAVObjectField {
elementNames.add(String.valueOf(n)); elementNames.add(String.valueOf(n));
} }
// Initialize // Initialize
constructorInitialize(name, units, type, elementNames, options); constructorInitialize(name, units, type, elementNames, options);
} }
public UAVObjectField(String name, String units, FieldType type, List<String> elementNames, List<String> options) { public UAVObjectField(String name, String units, FieldType type, List<String> elementNames, List<String> options) {
constructorInitialize(name, units, type, elementNames, options); constructorInitialize(name, units, type, elementNames, options);
} }
public void initialize(UAVObject obj){ public void initialize(UAVObject obj){
this.obj = obj; this.obj = obj;
//clear(); //clear();
} }
public UAVObject getObject() { public UAVObject getObject() {
return obj; return obj;
} }
public FieldType getType() { public FieldType getType() {
return type; return type;
} }
public String getTypeAsString() { public String getTypeAsString() {
switch (type) switch (type)
{ {
@ -62,31 +85,31 @@ public class UAVObjectField {
return "string"; return "string";
default: default:
return ""; return "";
} }
} }
public String getName() { public String getName() {
return name; return name;
} }
public String getUnits() { public String getUnits() {
return units; return units;
} }
public int getNumElements() { public int getNumElements() {
return numElements; return numElements;
} }
public List<String> getElementNames() { public List<String> getElementNames() {
return elementNames; return elementNames;
} }
public List<String> getOptions() { public List<String> getOptions() {
return options; return options;
} }
/** /**
* This function copies this field from the internal storage of the parent object * This function copies this field from the internal storage of the parent object
* to a new ByteBuffer for UAVTalk. It also converts from the java standard (big endian) * to a new ByteBuffer for UAVTalk. It also converts from the java standard (big endian)
* to the arm/uavtalk standard (little endian) * to the arm/uavtalk standard (little endian)
* @param dataOut * @param dataOut
@ -98,7 +121,7 @@ public class UAVObjectField {
dataOut.order(ByteOrder.LITTLE_ENDIAN); dataOut.order(ByteOrder.LITTLE_ENDIAN);
switch (type) switch (type)
{ {
case INT8: case INT8:
for (int index = 0; index < numElements; ++index) { for (int index = 0; index < numElements; ++index) {
Integer val = (Integer) getValue(index); Integer val = (Integer) getValue(index);
dataOut.put(val.byteValue()); dataOut.put(val.byteValue());
@ -116,7 +139,7 @@ public class UAVObjectField {
dataOut.putInt(val); dataOut.putInt(val);
} }
break; break;
case UINT8: case UINT8:
// TODO: Deal properly with unsigned // TODO: Deal properly with unsigned
for (int index = 0; index < numElements; ++index) { for (int index = 0; index < numElements; ++index) {
Integer val = (Integer) getValue(index); Integer val = (Integer) getValue(index);
@ -144,7 +167,7 @@ public class UAVObjectField {
case ENUM: case ENUM:
List<Byte> l = (List<Byte>) data; List<Byte> l = (List<Byte>) data;
for (int index = 0; index < numElements; ++index) for (int index = 0; index < numElements; ++index)
dataOut.put((Byte) l.get(index)); dataOut.put(l.get(index));
break; break;
case BITFIELD: case BITFIELD:
for (int index = 0; index < numElements; ++index) { for (int index = 0; index < numElements; ++index) {
@ -156,9 +179,9 @@ public class UAVObjectField {
throw new Error("Strings not yet implemented"); throw new Error("Strings not yet implemented");
} }
// Done // Done
return getNumBytes(); return getNumBytes();
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public synchronized int unpack(ByteBuffer dataIn) { public synchronized int unpack(ByteBuffer dataIn) {
// Unpack each element from input buffer // Unpack each element from input buffer
@ -196,7 +219,7 @@ public class UAVObjectField {
{ {
List<Short> l = (List<Short>) this.data; List<Short> l = (List<Short>) this.data;
for (int index = 0 ; index < numElements; ++index) { for (int index = 0 ; index < numElements; ++index) {
int signedval = (int) dataIn.get(); // this sign extends it int signedval = dataIn.get(); // this sign extends it
int unsignedval = signedval & 0xff; // drop sign extension int unsignedval = signedval & 0xff; // drop sign extension
l.set(index, (short) unsignedval); l.set(index, (short) unsignedval);
} }
@ -206,7 +229,7 @@ public class UAVObjectField {
{ {
List<Integer> l = (List<Integer>) this.data; List<Integer> l = (List<Integer>) this.data;
for (int index = 0 ; index < numElements; ++index) { for (int index = 0 ; index < numElements; ++index) {
int signedval = (int) dataIn.getShort(); // this sign extends it int signedval = dataIn.getShort(); // this sign extends it
int unsignedval = signedval & 0xffff; // drop sign extension int unsignedval = signedval & 0xffff; // drop sign extension
l.set(index, unsignedval); l.set(index, unsignedval);
} }
@ -216,7 +239,7 @@ public class UAVObjectField {
{ {
List<Long> l = (List<Long>) this.data; List<Long> l = (List<Long>) this.data;
for (int index = 0 ; index < numElements; ++index) { for (int index = 0 ; index < numElements; ++index) {
long signedval = (long) dataIn.getInt(); // this sign extends it long signedval = dataIn.getInt(); // this sign extends it
long unsignedval = signedval & 0xffffffffL; // drop sign extension long unsignedval = signedval & 0xffffffffL; // drop sign extension
l.set(index, unsignedval); l.set(index, unsignedval);
} }
@ -235,7 +258,7 @@ public class UAVObjectField {
{ {
List<Short> l = (List<Short>) this.data; List<Short> l = (List<Short>) this.data;
for (int index = 0 ; index < numElements; ++index) { for (int index = 0 ; index < numElements; ++index) {
int signedval = (int) dataIn.get(); // this sign extends it int signedval = dataIn.get(); // this sign extends it
int unsignedval = signedval & 0xff; // drop sign extension int unsignedval = signedval & 0xff; // drop sign extension
l.set(index, (short) unsignedval); l.set(index, (short) unsignedval);
} }
@ -254,9 +277,9 @@ public class UAVObjectField {
//throw new Exception("Strings not handled"); //throw new Exception("Strings not handled");
} }
// Done // Done
return getNumBytes(); return getNumBytes();
} }
public Object getValue() { return getValue(0); }; public Object getValue() { return getValue(0); };
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public synchronized Object getValue(int index) { public synchronized Object getValue(int index) {
@ -265,7 +288,7 @@ public class UAVObjectField {
{ {
return null; return null;
} }
switch (type) switch (type)
{ {
case INT8: case INT8:
@ -287,7 +310,7 @@ public class UAVObjectField {
List<Byte> l = (List<Byte>) data; List<Byte> l = (List<Byte>) data;
Byte val = l.get(index); Byte val = l.get(index);
//if(val >= options.size() || val < 0) //if(val >= options.size() || val < 0)
// throw new Exception("Invalid value for" + name); // throw new Exception("Invalid value for" + name);
return options.get(val); return options.get(val);
@ -301,10 +324,10 @@ public class UAVObjectField {
} }
} }
// If this point is reached then we got an invalid type // If this point is reached then we got an invalid type
return null; return null;
} }
public void setValue(Object data) { setValue(data,0); } public void setValue(Object data) { setValue(data,0); }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public synchronized void setValue(Object data, int index) { public synchronized void setValue(Object data, int index) {
// Check that index is not out of bounds // Check that index is not out of bounds
@ -361,15 +384,15 @@ public class UAVObjectField {
break; break;
} }
case ENUM: case ENUM:
{ {
byte val; byte val;
try { try {
// Test if numeric constant passed in // Test if numeric constant passed in
val = ((Number) data).byteValue(); val = ((Number) data).byteValue();
} catch (Exception e) { } catch (Exception e) {
val = (byte) options.indexOf((String) data); val = (byte) options.indexOf(data);
} }
//if(val < 0) throw new Exception("Enumerated value not found"); //if(val < 0) throw new Exception("Enumerated value not found");
List<Byte> l = (List<Byte>) this.data; List<Byte> l = (List<Byte>) this.data;
l.set(index, val); l.set(index, val);
break; break;
@ -380,7 +403,7 @@ public class UAVObjectField {
l.set(index, bound(data).shortValue()); l.set(index, bound(data).shortValue());
break; break;
} }
case STRING: case STRING:
{ {
//throw new Exception("Sorry I haven't implemented strings yet"); //throw new Exception("Sorry I haven't implemented strings yet");
} }
@ -388,7 +411,7 @@ public class UAVObjectField {
//obj.updated(); //obj.updated();
} }
} }
public double getDouble() { return getDouble(0); }; public double getDouble() { return getDouble(0); };
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public double getDouble(int index) { public double getDouble(int index) {
@ -400,24 +423,24 @@ public class UAVObjectField {
} }
return ((Number) getValue(index)).doubleValue(); return ((Number) getValue(index)).doubleValue();
} }
public void setDouble(double value) { setDouble(value, 0); }; public void setDouble(double value) { setDouble(value, 0); };
public void setDouble(double value, int index) { public void setDouble(double value, int index) {
setValue(value, index); setValue(value, index);
} }
public int getDataOffset() { public int getDataOffset() {
return offset; return offset;
} }
public int getNumBytes() { public int getNumBytes() {
return numBytesPerElement * numElements; return numBytesPerElement * numElements;
} }
public int getNumBytesElement() { public int getNumBytesElement() {
return numBytesPerElement; return numBytesPerElement;
} }
public boolean isNumeric() { public boolean isNumeric() {
switch (type) switch (type)
{ {
@ -443,9 +466,9 @@ public class UAVObjectField {
return false; return false;
default: default:
return false; return false;
} }
} }
public boolean isText() { public boolean isText() {
switch (type) switch (type)
{ {
@ -471,9 +494,10 @@ public class UAVObjectField {
return true; return true;
default: default:
return false; return false;
} }
} }
@Override
public String toString() { public String toString() {
String sout = new String(); String sout = new String();
sout += name + ": "; sout += name + ": ";
@ -484,15 +508,15 @@ public class UAVObjectField {
else else
sout += " "; sout += " ";
} }
if (units.length() > 0) if (units.length() > 0)
sout += " (" + units + ")\n"; sout += " (" + units + ")\n";
else else
sout += "\n"; sout += "\n";
return sout; return sout;
} }
void fieldUpdated(UAVObjectField field) { void fieldUpdated(UAVObjectField field) {
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@ -555,7 +579,7 @@ public class UAVObjectField {
break; break;
} }
} }
public synchronized void constructorInitialize(String name, String units, FieldType type, List<String> elementNames, List<String> options) { public synchronized void constructorInitialize(String name, String units, FieldType type, List<String> elementNames, List<String> options) {
// Copy params // Copy params
this.name = name; this.name = name;
@ -572,43 +596,43 @@ public class UAVObjectField {
switch (type) switch (type)
{ {
case INT8: case INT8:
data = (Object) new ArrayList<Byte>(this.numElements); data = new ArrayList<Byte>(this.numElements);
numBytesPerElement = 1; numBytesPerElement = 1;
break; break;
case INT16: case INT16:
data = (Object) new ArrayList<Short>(this.numElements); data = new ArrayList<Short>(this.numElements);
numBytesPerElement = 2; numBytesPerElement = 2;
break; break;
case INT32: case INT32:
data = (Object) new ArrayList<Integer>(this.numElements); data = new ArrayList<Integer>(this.numElements);
numBytesPerElement = 4; numBytesPerElement = 4;
break; break;
case UINT8: case UINT8:
data = (Object) new ArrayList<Short>(this.numElements); data = new ArrayList<Short>(this.numElements);
numBytesPerElement = 1; numBytesPerElement = 1;
break; break;
case UINT16: case UINT16:
data = (Object) new ArrayList<Integer>(this.numElements); data = new ArrayList<Integer>(this.numElements);
numBytesPerElement = 2; numBytesPerElement = 2;
break; break;
case UINT32: case UINT32:
data = (Object) new ArrayList<Long>(this.numElements); data = new ArrayList<Long>(this.numElements);
numBytesPerElement = 4; numBytesPerElement = 4;
break; break;
case FLOAT32: case FLOAT32:
data = (Object) new ArrayList<Float>(this.numElements); data = new ArrayList<Float>(this.numElements);
numBytesPerElement = 4; numBytesPerElement = 4;
break; break;
case ENUM: case ENUM:
data = (Object) new ArrayList<Byte>(this.numElements); data = new ArrayList<Byte>(this.numElements);
numBytesPerElement = 1; numBytesPerElement = 1;
break; break;
case BITFIELD: case BITFIELD:
data = (Object) new ArrayList<Short>(this.numElements); data = new ArrayList<Short>(this.numElements);
numBytesPerElement = 1; numBytesPerElement = 1;
break; break;
case STRING: case STRING:
data = (Object) new ArrayList<String>(this.numElements); data = new ArrayList<String>(this.numElements);
numBytesPerElement = 1; numBytesPerElement = 1;
break; break;
default: default:
@ -616,7 +640,7 @@ public class UAVObjectField {
} }
clear(); clear();
} }
/** /**
* For numerical types bounds the data appropriately * For numerical types bounds the data appropriately
* @param val Can be any object, for numerical tries to cast to Number * @param val Can be any object, for numerical tries to cast to Number
@ -624,7 +648,7 @@ public class UAVObjectField {
* @note This is mostly needed because java has no unsigned integer * @note This is mostly needed because java has no unsigned integer
*/ */
protected Long bound (Object val) { protected Long bound (Object val) {
switch(type) { switch(type) {
case ENUM: case ENUM:
case STRING: case STRING:
@ -679,15 +703,15 @@ public class UAVObjectField {
return (long) 255; return (long) 255;
return num; return num;
} }
return num; return num;
} }
@Override @Override
public UAVObjectField clone() public UAVObjectField clone()
{ {
UAVObjectField newField = new UAVObjectField(new String(name), new String(units), type, UAVObjectField newField = new UAVObjectField(new String(name), new String(units), type,
new ArrayList<String>(elementNames), new ArrayList<String>(elementNames),
new ArrayList<String>(options)); new ArrayList<String>(options));
newField.initialize(obj); newField.initialize(obj);
newField.data = data; newField.data = data;

View File

@ -1,3 +1,28 @@
/**
******************************************************************************
* @file UAVObjectManager.java
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
* @brief Critical class. This is the data store for all UAVOs. Allows
* other objects to access and change this data. Takes care of
* propagating changes to the UAV.
* @see The GNU Public License (GPL) Version 3
*
*****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.openpilot.uavtalk; package org.openpilot.uavtalk;
import java.util.ArrayList; import java.util.ArrayList;
@ -8,19 +33,19 @@ import java.util.Observer;
public class UAVObjectManager { public class UAVObjectManager {
public class CallbackListener extends Observable { public class CallbackListener extends Observable {
public void event (UAVObject obj) { public void event (UAVObject obj) {
setChanged(); setChanged();
notifyObservers(obj); notifyObservers(obj);
} }
} }
private CallbackListener newInstance = new CallbackListener(); private final CallbackListener newInstance = new CallbackListener();
public void addNewInstanceObserver(Observer o) { public void addNewInstanceObserver(Observer o) {
synchronized(newInstance) { synchronized(newInstance) {
newInstance.addObserver(o); newInstance.addObserver(o);
} }
} }
private CallbackListener newObject = new CallbackListener(); private final CallbackListener newObject = new CallbackListener();
public void addNewObjectObserver(Observer o) { public void addNewObjectObserver(Observer o) {
synchronized(newObject) { synchronized(newObject) {
newObject.addObserver(o); newObject.addObserver(o);
@ -29,7 +54,7 @@ public class UAVObjectManager {
private final int MAX_INSTANCES = 10; private final int MAX_INSTANCES = 10;
// Use array list to store objects since rarely added or deleted // Use array list to store objects since rarely added or deleted
private List<List<UAVObject>> objects = new ArrayList<List<UAVObject>>(); private final List<List<UAVObject>> objects = new ArrayList<List<UAVObject>>();
public UAVObjectManager() public UAVObjectManager()
{ {
@ -41,7 +66,7 @@ public class UAVObjectManager {
* A new instance can be created directly by instantiating a new object or by calling clone() of * A new instance can be created directly by instantiating a new object or by calling clone() of
* an existing object. The object will be registered and will be properly initialized so that it can accept * an existing object. The object will be registered and will be properly initialized so that it can accept
* updates. * updates.
* @throws Exception * @throws Exception
*/ */
public synchronized boolean registerObject(UAVDataObject obj) throws Exception public synchronized boolean registerObject(UAVDataObject obj) throws Exception
{ {
@ -61,7 +86,7 @@ public class UAVObjectManager {
} }
// The object type has alredy been added, so now we need to initialize the new instance with the appropriate id // The object type has alredy been added, so now we need to initialize the new instance with the appropriate id
// There is a single metaobject for all object instances of this type, so no need to create a new one // There is a single metaobject for all object instances of this type, so no need to create a new one
// Get object type metaobject from existing instance // Get object type metaobject from existing instance
UAVDataObject refObj = (UAVDataObject) instList.get(0); UAVDataObject refObj = (UAVDataObject) instList.get(0);
if (refObj == null) if (refObj == null)
{ {
@ -74,7 +99,7 @@ public class UAVObjectManager {
return false; return false;
} }
// If InstID is zero then we find the next open instId and create it // If InstID is zero then we find the next open instId and create it
if (obj.getInstID() == 0) if (obj.getInstID() == 0)
{ {
// Assign the next available ID and initialize the object instance the nadd // Assign the next available ID and initialize the object instance the nadd
@ -183,13 +208,13 @@ public class UAVObjectManager {
// If no instances skip // If no instances skip
if(instList.size() == 0) if(instList.size() == 0)
continue; continue;
// If meta data skip // If meta data skip
if(instList.get(0).isMetadata()) if(instList.get(0).isMetadata())
continue; continue;
List<UAVDataObject> newInstList = new ArrayList<UAVDataObject>(); List<UAVDataObject> newInstList = new ArrayList<UAVDataObject>();
ListIterator<UAVObject> instIt = instList.listIterator(); ListIterator<UAVObject> instIt = instList.listIterator();
while(instIt.hasNext()) { while(instIt.hasNext()) {
newInstList.add((UAVDataObject) instIt.next()); newInstList.add((UAVDataObject) instIt.next());
} }
@ -216,13 +241,13 @@ public class UAVObjectManager {
// If no instances skip // If no instances skip
if(instList.size() == 0) if(instList.size() == 0)
continue; continue;
// If meta data skip // If meta data skip
if(!instList.get(0).isMetadata()) if(!instList.get(0).isMetadata())
continue; continue;
List<UAVMetaObject> newInstList = new ArrayList<UAVMetaObject>(); List<UAVMetaObject> newInstList = new ArrayList<UAVMetaObject>();
ListIterator<UAVObject> instIt = instList.listIterator(); ListIterator<UAVObject> instIt = instList.listIterator();
while(instIt.hasNext()) { while(instIt.hasNext()) {
newInstList.add((UAVMetaObject) instIt.next()); newInstList.add((UAVMetaObject) instIt.next());
} }
@ -232,17 +257,17 @@ public class UAVObjectManager {
return mObjects; return mObjects;
} }
/** /**
* Returns a specific object by name only, returns instance ID zero * Returns a specific object by name only, returns instance ID zero
* @param name The object name * @param name The object name
* @return The object or null if not found * @return The object or null if not found
*/ */
public UAVObject getObject(String name) public UAVObject getObject(String name)
{ {
return getObject(name, 0, 0); return getObject(name, 0, 0);
} }
/** /**
* Get a specific object given its name and instance ID * Get a specific object given its name and instance ID
* @returns The object is found or NULL if not * @returns The object is found or NULL if not
@ -257,11 +282,11 @@ public class UAVObjectManager {
* @param objId the object id * @param objId the object id
* @returns The object is found or NULL if not * @returns The object is found or NULL if not
*/ */
public UAVObject getObject(long objId) public UAVObject getObject(long objId)
{ {
return getObject(null, objId, 0); return getObject(null, objId, 0);
} }
/** /**
* Get a specific object given its object and instance ID * Get a specific object given its object and instance ID
* @returns The object is found or NULL if not * @returns The object is found or NULL if not
@ -293,7 +318,7 @@ public class UAVObjectManager {
} }
} }
} }
return null; return null;
} }
@ -327,8 +352,8 @@ public class UAVObjectManager {
return instList; return instList;
} }
} }
} }
return null; return null;
} }

View File

@ -1,3 +1,29 @@
/**
******************************************************************************
* @file UAVTalk.java
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
* @brief The protocol layer implementation of UAVTalk. Serializes objects
* for transmission (which is done in the object itself which is aware
* of byte packing) wraps that in the UAVTalk packet. Parses UAVTalk
* packets and updates the UAVObjectManager.
* @see The GNU Public License (GPL) Version 3
*
*****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.openpilot.uavtalk; package org.openpilot.uavtalk;
import java.io.IOException; import java.io.IOException;
@ -17,7 +43,7 @@ public class UAVTalk extends Observable {
public static boolean DEBUG = LOGLEVEL > 0; public static boolean DEBUG = LOGLEVEL > 0;
private Thread inputProcessingThread = null; private Thread inputProcessingThread = null;
/** /**
* A reference to the thread for processing the incoming stream. Currently this method is ONLY * A reference to the thread for processing the incoming stream. Currently this method is ONLY
* used for unit testing * used for unit testing
@ -26,6 +52,7 @@ public class UAVTalk extends Observable {
if (inputProcessingThread == null) if (inputProcessingThread == null)
inputProcessingThread = new Thread() { inputProcessingThread = new Thread() {
@Override
public void run() { public void run() {
while(true) { while(true) {
try { try {
@ -179,7 +206,7 @@ public class UAVTalk extends Observable {
/** /**
* Process any data in the queue * Process any data in the queue
* @throws IOException * @throws IOException
*/ */
public boolean processInputStream() throws IOException { public boolean processInputStream() throws IOException {
int val; int val;
@ -195,13 +222,13 @@ public class UAVTalk extends Observable {
return true; return true;
} }
/** /**
* Request an update for the specified object, on success the object data * Request an update for the specified object, on success the object data
* would have been updated by the GCS. \param[in] obj Object to update * would have been updated by the GCS. \param[in] obj Object to update
* \param[in] allInstances If set true then all instances will be updated * \param[in] allInstances If set true then all instances will be updated
* \return Success (true), Failure (false) * \return Success (true), Failure (false)
* @throws IOException * @throws IOException
*/ */
public boolean sendObjectRequest(UAVObject obj, boolean allInstances) throws IOException { public boolean sendObjectRequest(UAVObject obj, boolean allInstances) throws IOException {
// QMutexLocker locker(mutex); // QMutexLocker locker(mutex);
@ -213,7 +240,7 @@ public class UAVTalk extends Observable {
* Object to send \param[in] acked Selects if an ack is required \param[in] * Object to send \param[in] acked Selects if an ack is required \param[in]
* allInstances If set true then all instances will be updated \return * allInstances If set true then all instances will be updated \return
* Success (true), Failure (false) * Success (true), Failure (false)
* @throws IOException * @throws IOException
*/ */
public synchronized boolean sendObject(UAVObject obj, boolean acked, public synchronized boolean sendObject(UAVObject obj, boolean acked,
boolean allInstances) throws IOException { boolean allInstances) throws IOException {
@ -237,7 +264,7 @@ public class UAVTalk extends Observable {
* request object update TYPE_OBJ_ACK: send object with an ack \param[in] * request object update TYPE_OBJ_ACK: send object with an ack \param[in]
* allInstances If set true then all instances will be updated \return * allInstances If set true then all instances will be updated \return
* Success (true), Failure (false) * Success (true), Failure (false)
* @throws IOException * @throws IOException
*/ */
public boolean objectTransaction(UAVObject obj, int type, public boolean objectTransaction(UAVObject obj, int type,
boolean allInstances) throws IOException { boolean allInstances) throws IOException {
@ -260,7 +287,7 @@ public class UAVTalk extends Observable {
/** /**
* Process an byte from the telemetry stream. \param[in] rxbyte Received * Process an byte from the telemetry stream. \param[in] rxbyte Received
* byte \return Success (true), Failure (false) * byte \return Success (true), Failure (false)
* @throws IOException * @throws IOException
*/ */
public synchronized boolean processInputByte(int rxbyte) throws IOException { public synchronized boolean processInputByte(int rxbyte) throws IOException {
assert (objMngr != null); assert (objMngr != null);
@ -341,7 +368,7 @@ public class UAVTalk extends Observable {
// Search for object, if not found reset state machine // Search for object, if not found reset state machine
rxObjId = rxTmpBuffer.getInt(0); rxObjId = rxTmpBuffer.getInt(0);
// Because java treats ints as only signed we need to do this manually // Because java treats ints as only signed we need to do this manually
if (rxObjId < 0) if (rxObjId < 0)
rxObjId = 0x100000000l + rxObjId; rxObjId = 0x100000000l + rxObjId;
{ {
UAVObject rxObj = objMngr.getObject(rxObjId); UAVObject rxObj = objMngr.getObject(rxObjId);
@ -475,11 +502,11 @@ public class UAVTalk extends Observable {
* received object \param[in] instId The instance ID of UAVOBJ_ALL_INSTANCES * received object \param[in] instId The instance ID of UAVOBJ_ALL_INSTANCES
* for all instances. \param[in] data Data buffer \param[in] length Buffer * for all instances. \param[in] data Data buffer \param[in] length Buffer
* length \return Success (true), Failure (false) * length \return Success (true), Failure (false)
* @throws IOException * @throws IOException
*/ */
public boolean receiveObject(int type, long objId, long instId, public boolean receiveObject(int type, long objId, long instId,
ByteBuffer data) throws IOException { ByteBuffer data) throws IOException {
if (DEBUG) Log.d(TAG, "Received object ID: " + objId); if (DEBUG) Log.d(TAG, "Received object ID: " + objId);
assert (objMngr != null); assert (objMngr != null);
@ -622,12 +649,12 @@ public class UAVTalk extends Observable {
} }
/** /**
* Send an object through the telemetry link. * Send an object through the telemetry link.
* @param[in] obj Object to send * @param[in] obj Object to send
* @param[in] type Transaction type * @param[in] type Transaction type
* @param[in] allInstances True is all instances of the object are to be sent * @param[in] allInstances True is all instances of the object are to be sent
* @return Success (true), Failure (false) * @return Success (true), Failure (false)
* @throws IOException * @throws IOException
*/ */
public synchronized boolean transmitObject(UAVObject obj, int type, boolean allInstances) throws IOException { public synchronized boolean transmitObject(UAVObject obj, int type, boolean allInstances) throws IOException {
// If all instances are requested on a single instance object it is an // If all instances are requested on a single instance object it is an
@ -665,7 +692,7 @@ public class UAVTalk extends Observable {
/** /**
* Send an object through the telemetry link. * Send an object through the telemetry link.
* @throws IOException * @throws IOException
* @param[in] obj Object handle to send * @param[in] obj Object handle to send
* @param[in] type Transaction type \return Success (true), Failure (false) * @param[in] type Transaction type \return Success (true), Failure (false)
*/ */
@ -738,11 +765,11 @@ public class UAVTalk extends Observable {
/** /**
* Update the crc value with new data. * Update the crc value with new data.
* *
* Generated by pycrc v0.7.5, http://www.tty1.net/pycrc/ using the * Generated by pycrc v0.7.5, http://www.tty1.net/pycrc/ using the
* configuration: Width = 8 Poly = 0x07 XorIn = 0x00 ReflectIn = False * configuration: Width = 8 Poly = 0x07 XorIn = 0x00 ReflectIn = False
* XorOut = 0x00 ReflectOut = False Algorithm = table-driven * XorOut = 0x00 ReflectOut = False Algorithm = table-driven
* *
* \param crc The current crc value. \param data Pointer to a buffer of \a * \param crc The current crc value. \param data Pointer to a buffer of \a
* data_len bytes. \param length Number of bytes in the \a data buffer. * data_len bytes. \param length Number of bytes in the \a data buffer.
* \return The updated crc value. * \return The updated crc value.
@ -753,7 +780,7 @@ public class UAVTalk extends Observable {
int updateCRC(int crc, byte[] data, int length) { int updateCRC(int crc, byte[] data, int length) {
for (int i = 0; i < length; i++) for (int i = 0; i < length; i++)
crc = updateCRC(crc, (int) data[i]); crc = updateCRC(crc, data[i]);
return crc; return crc;
} }