diff options
6 files changed, 256 insertions, 245 deletions
| diff --git a/altosdroid/res/values/strings.xml b/altosdroid/res/values/strings.xml index 0384b9b8..6ea9fec2 100644 --- a/altosdroid/res/values/strings.xml +++ b/altosdroid/res/values/strings.xml @@ -22,7 +22,7 @@  	<!-- AltosDroid -->  	<string name="bt_not_enabled">Bluetooth was not enabled.</string>  	<string name="title_connecting">connecting…</string> -	<string name="title_connected_to">connected: </string> +	<string name="title_connected_to">connected</string>  	<string name="title_not_connected">not connected</string>  	<!-- Options Menu --> diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java index 4a1fc371..51ef5e94 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java @@ -146,16 +146,18 @@ public class AltosBluetooth extends AltosLink {  	}  	public void save_frequency() { -		AltosPreferences.set_frequency(serial, frequency); +		AltosPreferences.set_frequency(0, frequency);  	}  	public void save_telemetry_rate() { -		AltosPreferences.set_telemetry_rate(serial, telemetry_rate); +		AltosPreferences.set_telemetry_rate(0, telemetry_rate);  	}  	private synchronized void wait_connected() throws InterruptedException, IOException {  		if (input == null) { +			if (D) Log.d(TAG, "wait_connected...");  			wait(); +			if (D) Log.d(TAG, "wait_connected done");  			if (input == null) throw new IOException();  		}  	} diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java index db1ca691..d276798e 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java @@ -60,20 +60,18 @@ public class AltosDroid extends FragmentActivity {  	static final boolean D = true;  	// Message types received by our Handler -	public static final int MSG_STATE_CHANGE    = 1; -	public static final int MSG_TELEMETRY       = 2; -	public static final int MSG_UPDATE_AGE      = 3; -	public static final int MSG_LOCATION	    = 4; -	public static final int MSG_CRC_ERROR	    = 5; -	public static final int MSG_FREQUENCY       = 6; -	public static final int MSG_TELEMETRY_RATE  = 7; + +	public static final int MSG_STATE           = 1; +	public static final int MSG_UPDATE_AGE      = 2;  	// Intent request codes -	private static final int REQUEST_CONNECT_DEVICE = 1; -	private static final int REQUEST_ENABLE_BT      = 2; +	public static final int REQUEST_CONNECT_DEVICE = 1; +	public static final int REQUEST_ENABLE_BT      = 2;  	public static FragmentManager	fm; +	private BluetoothAdapter mBluetoothAdapter = null; +  	// Layout Views  	private TextView mTitle; @@ -100,20 +98,14 @@ public class AltosDroid extends FragmentActivity {  	int             tabHeight;  	// Timer and Saved flight state for Age calculation -	private Timer timer = new Timer(); +	private Timer timer;  	AltosState saved_state; -	Location saved_location;  	// Service  	private boolean mIsBound   = false;  	private Messenger mService = null;  	final Messenger mMessenger = new Messenger(new IncomingHandler(this)); -	// TeleBT Config data -	private AltosConfigData mConfigData = null; -	// Local Bluetooth adapter -	private BluetoothAdapter mBluetoothAdapter = null; -  	// Text to Speech  	private AltosVoice mAltosVoice = null; @@ -125,44 +117,21 @@ public class AltosDroid extends FragmentActivity {  		@Override  		public void handleMessage(Message msg) {  			AltosDroid ad = mAltosDroid.get(); +  			switch (msg.what) { -			case MSG_STATE_CHANGE: -				if(D) Log.d(TAG, "MSG_STATE_CHANGE: " + msg.arg1); -				switch (msg.arg1) { -				case TelemetryService.STATE_CONNECTED: -					ad.set_config_data((AltosConfigData) msg.obj); -					break; -				case TelemetryService.STATE_CONNECTING: -					ad.mTitle.setText(R.string.title_connecting); -					break; -				case TelemetryService.STATE_READY: -				case TelemetryService.STATE_NONE: -					ad.mConfigData = null; -					ad.mTitle.setText(R.string.title_not_connected); -					String	active_device = AltosDroidPreferences.active_device(); -					if (active_device != null) -						ad.connectDevice(active_device); -					break; +			case MSG_STATE: +				if(D) Log.d(TAG, "MSG_STATE"); +				TelemetryState telemetry_state = (TelemetryState) msg.obj; +				if (telemetry_state == null) { +					Log.d(TAG, "telemetry_state null!"); +					return;  				} -				break; -			case MSG_TELEMETRY: -				ad.update_ui((AltosState) msg.obj); -				break; -			case MSG_LOCATION: -				ad.set_location((Location) msg.obj); -				break; -			case MSG_CRC_ERROR: + +				ad.update_state(telemetry_state);  				break;  			case MSG_UPDATE_AGE: -				if (ad.saved_state != null) { -					ad.mAgeView.setText(String.format("%d", (System.currentTimeMillis() - ad.saved_state.received_time + 500) / 1000)); -				} -				break; -			case MSG_FREQUENCY: -				ad.set_frequency((Double) msg.obj); -				break; -			case MSG_TELEMETRY_RATE: -				ad.set_telemetry_rate((Integer) msg.obj); +				if(D) Log.d(TAG, "MSG_UPDATE_AGE"); +				ad.update_age();  				break;  			}  		} @@ -218,37 +187,52 @@ public class AltosDroid extends FragmentActivity {  		mTabs.remove(mTab);  	} -	void set_location(Location location) { -		saved_location = location; -		Log.d(TAG, "set_location"); -		update_ui(saved_state); -	} - -	void set_title() { -		if (mConfigData != null) { -			String str = String.format("S/N %d %6.3f MHz", mConfigData.serial, frequency); - -			if (telemetry_rate != AltosLib.ao_telemetry_rate_38400) -				str = str.concat(String.format(" %d bps", AltosLib.ao_telemetry_rate_values[telemetry_rate])); -			mTitle.setText(str); +	void update_title(TelemetryState telemetry_state) { +		switch (telemetry_state.connect) { +		case TelemetryState.CONNECT_CONNECTED: +			if (telemetry_state.config != null) { +				String str = String.format("S/N %d %6.3f MHz", telemetry_state.config.serial, +							   telemetry_state.frequency); +				if (telemetry_state.telemetry_rate != AltosLib.ao_telemetry_rate_38400) +					str = str.concat(String.format(" %d bps", +								       AltosLib.ao_telemetry_rate_values[telemetry_state.telemetry_rate])); +				mTitle.setText(str); +			} else { +				mTitle.setText(R.string.title_connected_to); +			} +			break; +		case TelemetryState.CONNECT_CONNECTING: +			mTitle.setText(R.string.title_connecting); +			break; +		case TelemetryState.CONNECT_READY: +		case TelemetryState.CONNECT_NONE: +			mTitle.setText(R.string.title_not_connected); +			break;  		}  	} -	void set_frequency(double frequency) { -		if (D) Log.d(TAG, String.format("AltosDroid: set_frequency %f\n", frequency)); -		this.frequency = frequency; -		set_title(); +	void start_timer() { +		if (timer == null) { +			timer = new Timer(); +			timer.scheduleAtFixedRate(new TimerTask(){ public void run() {onTimerTick();}}, 1000L, 1000L); +		}  	} -	void set_telemetry_rate(int telemetry_rate) { -		if (D) Log.d(TAG, String.format("AltosDroid: set_telemetry_rate %d\n", telemetry_rate)); -		this.telemetry_rate = telemetry_rate; -		set_title(); +	void stop_timer() { +		if (timer != null) { +			timer.cancel(); +			timer.purge(); +			timer = null; +		}  	} -	void set_config_data(AltosConfigData config_data) { -		mConfigData = config_data; -		set_title(); +	void update_state(TelemetryState telemetry_state) { +		update_title(telemetry_state); +		update_ui(telemetry_state.state, telemetry_state.location); +		if (telemetry_state.connect == TelemetryState.CONNECT_CONNECTED) +			start_timer(); +		else +			stop_timer();  	}  	boolean same_string(String a, String b) { @@ -263,52 +247,73 @@ public class AltosDroid extends FragmentActivity {  		}  	} -	void update_ui(AltosState state) { +	void update_age() { +		if (saved_state != null) +			mAgeView.setText(String.format("%d", (System.currentTimeMillis() - saved_state.received_time + 500) / 1000)); +	} + +	void update_ui(AltosState state, Location location) {  		Log.d(TAG, "update_ui");  		int prev_state = AltosLib.ao_flight_invalid; +		AltosGreatCircle from_receiver = null; +  		if (saved_state != null)  			prev_state = saved_state.state;  		if (state != null) {  			Log.d(TAG, String.format("prev state %d new state  %d\n", prev_state, state.state)); -			if (prev_state != state.state) { -				String currentTab = mTabHost.getCurrentTabTag(); -				Log.d(TAG, "switch state"); -				switch (state.state) { -				case AltosLib.ao_flight_boost: -					if (currentTab.equals("pad")) mTabHost.setCurrentTabByTag("ascent"); -					break; -				case AltosLib.ao_flight_drogue: -					if (currentTab.equals("ascent")) mTabHost.setCurrentTabByTag("descent"); -					break; -				case AltosLib.ao_flight_landed: -					if (currentTab.equals("descent")) mTabHost.setCurrentTabByTag("landed"); -					break; -				case AltosLib.ao_flight_stateless: -					if (currentTab.equals("pad")) mTabHost.setCurrentTabByTag("descent"); -					break; +			if (state.state == AltosLib.ao_flight_stateless) { +				boolean	prev_locked = false; +				boolean locked = false; + +				if(state.gps != null) +					locked = state.gps.locked; +				if (saved_state != null && saved_state.gps != null) +					prev_locked = saved_state.gps.locked; +				if (prev_locked != locked) { +					String currentTab = mTabHost.getCurrentTabTag(); +					if (locked) { +						if (currentTab.equals("pad")) mTabHost.setCurrentTabByTag("descent"); +					} else { +						if (currentTab.equals("descent")) mTabHost.setCurrentTabByTag("pad"); +					} +				} +			} else { +				if (prev_state != state.state) { +					String currentTab = mTabHost.getCurrentTabTag(); +					Log.d(TAG, "switch state"); +					switch (state.state) { +					case AltosLib.ao_flight_boost: +						if (currentTab.equals("pad")) mTabHost.setCurrentTabByTag("ascent"); +						break; +					case AltosLib.ao_flight_drogue: +						if (currentTab.equals("ascent")) mTabHost.setCurrentTabByTag("descent"); +						break; +					case AltosLib.ao_flight_landed: +						if (currentTab.equals("descent")) mTabHost.setCurrentTabByTag("landed"); +						break; +					case AltosLib.ao_flight_stateless: +						if (currentTab.equals("pad")) mTabHost.setCurrentTabByTag("descent"); +						break; +					}  				}  			} -		} - -		AltosGreatCircle from_receiver = null; -		if (state != null && saved_location != null && state.gps != null && state.gps.locked) { -			double altitude = 0; -			if (saved_location.hasAltitude()) -				altitude = saved_location.getAltitude(); -			from_receiver = new AltosGreatCircle(saved_location.getLatitude(), -							     saved_location.getLongitude(), -							     altitude, -							     state.gps.lat, -							     state.gps.lon, -							     state.gps.alt); -		} +			if (location != null && state.gps != null && state.gps.locked) { +				double altitude = 0; +				if (location.hasAltitude()) +					altitude = location.getAltitude(); +				from_receiver = new AltosGreatCircle(location.getLatitude(), +								     location.getLongitude(), +								     altitude, +								     state.gps.lat, +								     state.gps.lon, +								     state.gps.alt); +			} -		if (state != null) {  			if (saved_state == null || !same_string(saved_state.callsign, state.callsign)) {  				Log.d(TAG, "update callsign");  				mCallsignView.setText(state.callsign); @@ -337,10 +342,10 @@ public class AltosDroid extends FragmentActivity {  		}  		for (AltosDroidTab mTab : mTabs) -			mTab.update_ui(state, from_receiver, saved_location, mTab == mTabsAdapter.currentItem()); +			mTab.update_ui(state, from_receiver, location, mTab == mTabsAdapter.currentItem());  		if (state != null) -			mAltosVoice.tell(state); +			mAltosVoice.tell(state, from_receiver);  		saved_state = state;  	} @@ -382,8 +387,6 @@ public class AltosDroid extends FragmentActivity {  		super.onCreate(savedInstanceState);  		if(D) Log.e(TAG, "+++ ON CREATE +++"); -		fm = getSupportFragmentManager(); -  		// Get local Bluetooth adapter  		mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); @@ -391,11 +394,9 @@ public class AltosDroid extends FragmentActivity {  		if (mBluetoothAdapter == null) {  			Toast.makeText(this, "Bluetooth is not available", Toast.LENGTH_LONG).show();  			finish(); -			return;  		} -		// Initialise preferences -		AltosDroidPreferences.init(this); +		fm = getSupportFragmentManager();  		// Set up the window layout  		requestWindowFeature(Window.FEATURE_CUSTOM_TITLE); @@ -438,7 +439,6 @@ public class AltosDroid extends FragmentActivity {  		for (int i = 0; i < 5; i++)  			mTabHost.getTabWidget().getChildAt(i).getLayoutParams().height = tabHeight; -  		// Set up the custom title  		mTitle = (TextView) findViewById(R.id.title_left_text);  		mTitle.setText(R.string.app_name); @@ -458,8 +458,6 @@ public class AltosDroid extends FragmentActivity {  		mStateView     = (TextView) findViewById(R.id.state_value);  		mAgeView       = (TextView) findViewById(R.id.age_value); -		timer.scheduleAtFixedRate(new TimerTask(){ public void run() {onTimerTick();}}, 1000L, 100L); -  		mAltosVoice = new AltosVoice(this);  	} @@ -468,14 +466,14 @@ public class AltosDroid extends FragmentActivity {  		super.onStart();  		if(D) Log.e(TAG, "++ ON START ++"); +		// Start Telemetry Service +		startService(new Intent(AltosDroid.this, TelemetryService.class)); +  		if (!mBluetoothAdapter.isEnabled()) {  			Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); -			startActivityForResult(enableIntent, REQUEST_ENABLE_BT); +			startActivityForResult(enableIntent, AltosDroid.REQUEST_ENABLE_BT);  		} -		// Start Telemetry Service -		startService(new Intent(AltosDroid.this, TelemetryService.class)); -  		doBindService();  	} @@ -506,6 +504,7 @@ public class AltosDroid extends FragmentActivity {  		if(D) Log.e(TAG, "--- ON DESTROY ---");  		if (mAltosVoice != null) mAltosVoice.stop(); +		stop_timer();  	}  	public void onActivityResult(int requestCode, int resultCode, Intent data) { @@ -534,12 +533,10 @@ public class AltosDroid extends FragmentActivity {  	}  	private void connectDevice(String address) { -		// Get the BLuetoothDevice object -		BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);  		// Attempt to connect to the device  		try { -			if (D) Log.d(TAG, "Connecting to " + device.getName()); -			mService.send(Message.obtain(null, TelemetryService.MSG_CONNECT, device)); +			if (D) Log.d(TAG, "Connecting to " + address); +			mService.send(Message.obtain(null, TelemetryService.MSG_CONNECT, address));  		} catch (RemoteException e) {  		}  	} @@ -547,7 +544,6 @@ public class AltosDroid extends FragmentActivity {  	private void connectDevice(Intent data) {  		// Get the device MAC address  		String address = data.getExtras().getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS); -		AltosDroidPreferences.set_active_device(address);  		connectDevice(address);  	} diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosVoice.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosVoice.java index b05913b6..b8def367 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosVoice.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosVoice.java @@ -58,7 +58,7 @@ public class AltosVoice {  		}  	} -	public void tell(AltosState state) { +	public void tell(AltosState state, AltosGreatCircle from_receiver) {  		if (!tts_enabled) return;  		boolean	spoke = false; @@ -88,13 +88,14 @@ public class AltosVoice {  		}  		old_state = state;  		if (idle_thread != null) -			idle_thread.notice(state, spoke); +			idle_thread.notice(state, from_receiver, spoke);  	}  	class IdleThread extends Thread {  		boolean	           started;  		private AltosState state; +		private AltosGreatCircle from_receiver;  		int                reported_landing;  		int                report_interval;  		long               report_time; @@ -112,25 +113,26 @@ public class AltosVoice {  				return;  			} -			/* If the rocket isn't on the pad, then report height */ -			if (((AltosLib.ao_flight_drogue <= state.state && +			/* If the rocket isn't on the pad, then report location */ +			if ((AltosLib.ao_flight_drogue <= state.state &&  			      state.state < AltosLib.ao_flight_landed) || -			     state.state == AltosLib.ao_flight_stateless) && -			    state.range >= 0) +			     state.state == AltosLib.ao_flight_stateless)  			{ -				if (state.from_pad != null) { +				AltosGreatCircle	position; + +				if (from_receiver != null) +					position = from_receiver; +				else +					position = state.from_pad; + +				if (position != null) {  					speak(String.format("Height %d, bearing %s %d, elevation %d, range %d.\n",  							    (int) (state.height() + 0.5), -							    state.from_pad.bearing_words( +							    position.bearing_words(  								    AltosGreatCircle.BEARING_VOICE), -							    (int) (state.from_pad.bearing + 0.5), -							    (int) (state.elevation + 0.5), -							    (int) (state.range + 0.5))); -				} else { -					speak(String.format("Height %d, elevation %d, range %d.\n", -							    (int) (state.height() + 0.5), -							    (int) (state.elevation + 0.5), -							    (int) (state.range + 0.5))); +							    (int) (position.bearing + 0.5), +							    (int) (position.elevation + 0.5), +							    (int) (position.range + 0.5)));  				}  			} else if (state.state > AltosLib.ao_flight_pad) {  				if (state.height() != AltosLib.MISSING) @@ -186,9 +188,10 @@ public class AltosVoice {  			}  		} -		public synchronized void notice(AltosState new_state, boolean spoken) { +		public synchronized void notice(AltosState new_state, AltosGreatCircle new_from_receiver, boolean spoken) {  			AltosState old_state = state;  			state = new_state; +			from_receiver = new_from_receiver;  			if (!started && state.state > AltosLib.ao_flight_pad) {  				started = true;  				start(); diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryReader.java b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryReader.java index bec51851..971c3e80 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryReader.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryReader.java @@ -31,6 +31,7 @@ import org.altusmetrum.altoslib_5.*;  public class TelemetryReader extends Thread {  	private static final String TAG = "TelemetryReader"; +	private static final boolean D = true;  	int         crc_errors; @@ -44,12 +45,6 @@ public class TelemetryReader extends Thread {  	LinkedBlockingQueue<AltosLine> telemQueue;  	public AltosState read() throws ParseException, AltosCRCException, InterruptedException, IOException { -		if (stacked != null) { -			state = stacked.read(); -			if (state != null) -				return state; -			stacked = null; -		}  		AltosLine l = telemQueue.take();  		if (l.line == null)  			throw new IOException("IO error"); @@ -78,6 +73,26 @@ public class TelemetryReader extends Thread {  		AltosState  state = null;  		try { +			if (D) Log.d(TAG, "starting reader"); +			while (stacked != null) { +				AltosState	stacked_state = null; +				try { +					stacked_state = stacked.read(); +				} catch (ParseException pe) { +					continue; +				} catch (AltosCRCException ce) { +					continue; +				} +				if (stacked_state != null) +					state = stacked_state; +				else +					stacked = null; +			} +			if (state != null) { +				if (D) Log.d(TAG, "Send initial state"); +				handler.obtainMessage(TelemetryService.MSG_TELEMETRY, state).sendToTarget(); +			} +			if (D) Log.d(TAG, "starting loop");  			while (telemQueue != null) {  				try {  					state = read(); @@ -97,6 +112,7 @@ public class TelemetryReader extends Thread {  	}  	public TelemetryReader (AltosLink in_link, Handler in_handler, AltosFlightReader in_stacked) { +		if (D) Log.d(TAG, "connected TelemetryReader create started");  		link    = in_link;  		handler = in_handler;  		stacked = in_stacked; @@ -104,15 +120,9 @@ public class TelemetryReader extends Thread {  		state = null;  		telemQueue = new LinkedBlockingQueue<AltosLine>();  		link.add_monitor(telemQueue); -		try { -			link.set_radio_frequency(AltosPreferences.frequency(link.serial)); -			link.set_telemetry(AltosLib.ao_telemetry_standard); -			link.set_telemetry_rate(AltosPreferences.telemetry_rate(link.serial)); -		} catch (InterruptedException ee) { -			close(); -		} catch (TimeoutException te) { -			close(); -		} +		link.set_telemetry(AltosLib.ao_telemetry_standard); + +		if (D) Log.d(TAG, "connected TelemetryReader created");  	}  	private static AltosFlightReader existing_data(AltosLink link) { diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java index 8e5c7903..52fc976a 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java @@ -28,6 +28,7 @@ import android.app.Notification;  import android.app.PendingIntent;  import android.app.Service;  import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothAdapter;  import android.content.Intent;  import android.content.Context;  import android.os.Bundle; @@ -63,11 +64,6 @@ public class TelemetryService extends Service implements LocationListener {  	static final int MSG_CRC_ERROR	       = 9;  	static final int MSG_SETBAUD	       = 10; -	public static final int STATE_NONE       = 0; -	public static final int STATE_READY      = 1; -	public static final int STATE_CONNECTING = 2; -	public static final int STATE_CONNECTED  = 3; -  	// Unique Identification Number for the Notification.  	// We use it on Notification start, and to cancel it.  	private int NOTIFICATION = R.string.telemetry_service_label; @@ -81,21 +77,17 @@ public class TelemetryService extends Service implements LocationListener {  	final Messenger mMessenger = new Messenger(mHandler); // Target we publish for clients to send messages to IncomingHandler.  	// Name of the connected device -	private BluetoothDevice device           = null; +	String address;  	private AltosBluetooth  mAltosBluetooth  = null; -	private AltosConfigData mConfigData      = null;  	private TelemetryReader mTelemetryReader = null;  	private TelemetryLogger mTelemetryLogger = null; +	// Local Bluetooth adapter +	private BluetoothAdapter mBluetoothAdapter = null; -	// internally track state of bluetooth connection -	private int state = STATE_NONE; +	private TelemetryState	telemetry_state;  	// Last data seen; send to UI when it starts -	private AltosState last_state; -	private Location last_location; -	private int last_crc_errors; -  	// Handler of incoming messages from clients.  	static class IncomingHandler extends Handler {  		private final WeakReference<TelemetryService> service; @@ -109,16 +101,8 @@ public class TelemetryService extends Service implements LocationListener {  				s.mClients.add(msg.replyTo);  				try {  					// Now we try to send the freshly connected UI any relavant information about what -					// we're talking to - Basically state and Config Data. -					msg.replyTo.send(Message.obtain(null, AltosDroid.MSG_STATE_CHANGE, s.state, -1, s.mConfigData)); -					// We also send any recent telemetry or location data that's cached -					if (s.last_state      != null) msg.replyTo.send(Message.obtain(null, AltosDroid.MSG_TELEMETRY, s.last_state     )); -					if (s.last_location   != null) msg.replyTo.send(Message.obtain(null, AltosDroid.MSG_LOCATION , s.last_location  )); -					if (s.last_crc_errors != 0   ) msg.replyTo.send(Message.obtain(null, AltosDroid.MSG_CRC_ERROR, s.last_crc_errors)); -					if (s.state == STATE_CONNECTED) { -						msg.replyTo.send(s.frequency_message()); -						msg.replyTo.send(s.telemetry_rate_message()); -					} +					// we're talking to +					msg.replyTo.send(s.message());  				} catch (RemoteException e) {  					s.mClients.remove(msg.replyTo);  				} @@ -130,8 +114,9 @@ public class TelemetryService extends Service implements LocationListener {  				break;  			case MSG_CONNECT:  				if (D) Log.d(TAG, "Connect command received"); -				s.device = (BluetoothDevice) msg.obj; -				s.startAltosBluetooth(); +				String address = (String) msg.obj; +				AltosDroidPreferences.set_active_device(address); +				s.startAltosBluetooth(address);  				break;  			case MSG_CONNECTED:  				if (D) Log.d(TAG, "Connected to device"); @@ -142,43 +127,46 @@ public class TelemetryService extends Service implements LocationListener {  				break;  			case MSG_CONNECT_FAILED:  				if (D) Log.d(TAG, "Connection failed... retrying"); -				s.startAltosBluetooth(); +				if (s.address != null) +					s.startAltosBluetooth(s.address);  				break;  			case MSG_DISCONNECTED:  				Log.d(TAG, "MSG_DISCONNECTED"); -				// Only do the following if we haven't been shutdown elsewhere.. -				if (s.device != null) { -					if (D) Log.d(TAG, "Disconnected from " + s.device.getName()); -					s.stopAltosBluetooth(); -				} +				s.stopAltosBluetooth();  				break;  			case MSG_TELEMETRY:  				// forward telemetry messages -				s.last_state = (AltosState) msg.obj; -				s.sendMessageToClients(Message.obtain(null, AltosDroid.MSG_TELEMETRY, msg.obj)); +				s.telemetry_state.state = (AltosState) msg.obj; +				if (D) Log.d(TAG, "MSG_TELEMETRY"); +				s.sendMessageToClients();  				break;  			case MSG_CRC_ERROR:  				// forward crc error messages -				s.last_crc_errors = (Integer) msg.obj; -				s.sendMessageToClients(Message.obtain(null, AltosDroid.MSG_CRC_ERROR, msg.obj)); +				s.telemetry_state.crc_errors = (Integer) msg.obj; +				if (D) Log.d(TAG, "MSG_CRC_ERROR"); +				s.sendMessageToClients();  				break;  			case MSG_SETFREQUENCY: -				if (s.state == STATE_CONNECTED) { +				if (D) Log.d(TAG, "MSG_SETFREQUENCY"); +				s.telemetry_state.frequency = (Double) msg.obj; +				if (s.telemetry_state.connect == TelemetryState.CONNECT_CONNECTED) {  					try { -						s.mAltosBluetooth.set_radio_frequency((Double) msg.obj); +						s.mAltosBluetooth.set_radio_frequency(s.telemetry_state.frequency);  						s.mAltosBluetooth.save_frequency(); -						s.sendMessageToClients(s.frequency_message());  					} catch (InterruptedException e) {  					} catch (TimeoutException e) {  					}  				} +				s.sendMessageToClients();  				break;  			case MSG_SETBAUD: -				if (s.state == STATE_CONNECTED) { -					s.mAltosBluetooth.set_telemetry_rate((Integer) msg.obj); +				if (D) Log.d(TAG, "MSG_SETBAUD"); +				s.telemetry_state.telemetry_rate = (Integer) msg.obj; +				if (s.telemetry_state.connect == TelemetryState.CONNECT_CONNECTED) { +					s.mAltosBluetooth.set_telemetry_rate(s.telemetry_state.telemetry_rate);  					s.mAltosBluetooth.save_telemetry_rate(); -					s.sendMessageToClients(s.telemetry_rate_message());  				} +				s.sendMessageToClients();  				break;  			default:  				super.handleMessage(msg); @@ -186,9 +174,18 @@ public class TelemetryService extends Service implements LocationListener {  		}  	} -	private void sendMessageToClients(Message m) { +	private Message message() { +		if (telemetry_state == null) +			Log.d(TAG, "telemetry_state null!"); +		return Message.obtain(null, AltosDroid.MSG_STATE, telemetry_state); +	} + +	private void sendMessageToClients() { +		Message m = message(); +		if (D) Log.d(TAG, String.format("Send message to %d clients", mClients.size()));  		for (int i=mClients.size()-1; i>=0; i--) {  			try { +				if (D) Log.d(TAG, String.format("Send message to client %d", i));  				mClients.get(i).send(m);  			} catch (RemoteException e) {  				mClients.remove(i); @@ -196,19 +193,9 @@ public class TelemetryService extends Service implements LocationListener {  		}  	} -	private Message frequency_message() { -		if (D) Log.d(TAG, String.format("frequency_message %f\n", mAltosBluetooth.frequency())); -		return Message.obtain(null, AltosDroid.MSG_FREQUENCY, mAltosBluetooth.frequency()); -	} - -	private Message telemetry_rate_message() { -		if (D) Log.d(TAG, String.format("telemetry_rate_message %d\n", mAltosBluetooth.telemetry_rate())); -		return Message.obtain(null, AltosDroid.MSG_TELEMETRY_RATE, mAltosBluetooth.telemetry_rate()); -	} -  	private void stopAltosBluetooth() {  		if (D) Log.d(TAG, "stopAltosBluetooth(): begin"); -		setState(STATE_READY); +		telemetry_state.connect = TelemetryState.CONNECT_READY;  		if (mTelemetryReader != null) {  			if (D) Log.d(TAG, "stopAltosBluetooth(): stopping TelemetryReader");  			mTelemetryReader.interrupt(); @@ -228,18 +215,21 @@ public class TelemetryService extends Service implements LocationListener {  			mAltosBluetooth.close();  			mAltosBluetooth = null;  		} -		device = null; -		mConfigData = null; +		telemetry_state.config = null; +		if (D) Log.d(TAG, "stopAltosBluetooth(): send message to clients"); +		sendMessageToClients();  	} -	private void startAltosBluetooth() { -		if (device == null) { -			return; -		} +	private void startAltosBluetooth(String address) { +		// Get the BLuetoothDevice object +		BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address); + +		this.address = address;  		if (mAltosBluetooth == null) {  			if (D) Log.d(TAG, String.format("startAltosBluetooth(): Connecting to %s (%s)", device.getName(), device.getAddress()));  			mAltosBluetooth = new AltosBluetooth(device, mHandler); -			setState(STATE_CONNECTING); +			telemetry_state.connect = TelemetryState.CONNECT_CONNECTING; +			sendMessageToClients();  		} else {  			// This is a bit of a hack - if it appears we're still connected, we treat this as a restart.  			// So, to give a suitable delay to teardown/bringup, we just schedule a resend of a message @@ -247,30 +237,19 @@ public class TelemetryService extends Service implements LocationListener {  			// ... then we tear down the existing connection.  			// We do it this way around so that we don't lose a reference to the device when this method  			// is called on reception of MSG_CONNECT_FAILED in the handler above. -			mHandler.sendMessageDelayed(Message.obtain(null, MSG_CONNECT, device), 3000); +			mHandler.sendMessageDelayed(Message.obtain(null, MSG_CONNECT, address), 3000);  			stopAltosBluetooth();  		}  	} -	private synchronized void setState(int s) { -		if (D) Log.d(TAG, "setState(): " + state + " -> " + s); -		state = s; - -		// This shouldn't be required - mConfigData should be null for any non-connected -		// state, but to be safe and to reduce message size -		AltosConfigData acd = (state == STATE_CONNECTED) ? mConfigData : null; - -		sendMessageToClients(Message.obtain(null, AltosDroid.MSG_STATE_CHANGE, state, -1, acd)); -	} -  	private void connected() throws InterruptedException { +		if (D) Log.d(TAG, "connected top");  		try {  			if (mAltosBluetooth == null)  				throw new InterruptedException("no bluetooth"); -			mConfigData = mAltosBluetooth.config_data(); -			if (D) Log.d(TAG, "send frequency/rate messages\n"); -			sendMessageToClients(frequency_message()); -			sendMessageToClients(telemetry_rate_message()); +			telemetry_state.config = mAltosBluetooth.config_data(); +			mAltosBluetooth.set_radio_frequency(telemetry_state.frequency); +			mAltosBluetooth.set_telemetry_rate(telemetry_state.telemetry_rate);  		} catch (TimeoutException e) {  			// If this timed out, then we really want to retry it, but  			// probably safer to just retry the connection from scratch. @@ -278,21 +257,25 @@ public class TelemetryService extends Service implements LocationListener {  			return;  		} -		setState(STATE_CONNECTED); +		if (D) Log.d(TAG, "connected bluetooth configured"); +		telemetry_state.connect = TelemetryState.CONNECT_CONNECTED;  		mTelemetryReader = new TelemetryReader(mAltosBluetooth, mHandler);  		mTelemetryReader.start(); +		if (D) Log.d(TAG, "connected TelemetryReader started"); +  		mTelemetryLogger = new TelemetryLogger(this, mAltosBluetooth); -		sendMessageToClients(frequency_message()); -		sendMessageToClients(telemetry_rate_message()); +		if (D) Log.d(TAG, "Notify UI of connection"); + +		sendMessageToClients();  	}  	private void onTimerTick() {  		if (D) Log.d(TAG, "Timer wakeup");  		try { -			if (mClients.size() <= 0 && state != STATE_CONNECTED) { +			if (mClients.size() <= 0 && telemetry_state.connect != TelemetryState.CONNECT_CONNECTED) {  				stopSelf();  			}  		} catch (Throwable t) { @@ -303,19 +286,35 @@ public class TelemetryService extends Service implements LocationListener {  	@Override  	public void onCreate() { +		// Get local Bluetooth adapter +		mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); + +		// If the adapter is null, then Bluetooth is not supported +		if (mBluetoothAdapter == null) { +			Toast.makeText(this, "Bluetooth is not available", Toast.LENGTH_LONG).show(); +		} + +		// Initialise preferences +		AltosDroidPreferences.init(this); + +		telemetry_state = new TelemetryState(); +  		// Create a reference to the NotificationManager so that we can update our notifcation text later  		//mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); -		setState(STATE_READY); +		telemetry_state.connect = TelemetryState.CONNECT_READY;  		// Start our timer - first event in 10 seconds, then every 10 seconds after that.  		timer.scheduleAtFixedRate(new TimerTask(){ public void run() {onTimerTick();}}, 10000L, 10000L);  		// Listen for GPS and Network position updates  		LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE); -		 +  		locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 1, this); -//		locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this); + +		String address = AltosDroidPreferences.active_device(); +		if (address != null) +			startAltosBluetooth(address);  	}  	@Override @@ -371,8 +370,9 @@ public class TelemetryService extends Service implements LocationListener {  	public void onLocationChanged(Location location) { -		last_location = location; -		sendMessageToClients(Message.obtain(null, AltosDroid.MSG_LOCATION, location)); +		telemetry_state.location = location; +		if (D) Log.d(TAG, "location changed"); +		sendMessageToClients();  	}  	public void onStatusChanged(String provider, int status, Bundle extras) { | 
