Skip to content

Commit c116aee

Browse files
committed
Add flysight tool
1 parent 9647125 commit c116aee

File tree

20 files changed

+509
-38
lines changed

20 files changed

+509
-38
lines changed

app/src/main/AndroidManifest.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,9 @@
8585
<activity
8686
android:name=".views.tracks.TrackRemoteActivity"
8787
android:label="@string/app_name"/>
88+
<activity
89+
android:name=".views.FlysightActivity"
90+
android:label="@string/action_flysight"/>
8891
<activity
8992
android:name=".views.SettingsActivity"
9093
android:label="@string/title_activity_settings"/>
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
package com.platypii.baseline.views;
2+
3+
import com.platypii.baseline.Permissions;
4+
import com.platypii.baseline.R;
5+
import com.platypii.baseline.Services;
6+
import com.platypii.baseline.bluetooth.BluetoothState;
7+
import com.platypii.baseline.databinding.ActivityFlysightBinding;
8+
import com.platypii.baseline.events.BluetoothEvent;
9+
import com.platypii.baseline.measurements.MLocation;
10+
import com.platypii.baseline.util.Convert;
11+
import com.platypii.baseline.util.Numbers;
12+
import com.platypii.baseline.util.PubSub.Subscriber;
13+
14+
import android.os.Bundle;
15+
import android.os.Handler;
16+
import androidx.annotation.NonNull;
17+
import androidx.annotation.Nullable;
18+
import java.util.Locale;
19+
import org.greenrobot.eventbus.EventBus;
20+
import org.greenrobot.eventbus.Subscribe;
21+
import org.greenrobot.eventbus.ThreadMode;
22+
23+
public class FlysightActivity extends BaseActivity implements Subscriber<MLocation> {
24+
25+
private ActivityFlysightBinding binding;
26+
27+
// Periodic UI updates
28+
private final Handler handler = new Handler();
29+
private final int updateInterval = 100; // in milliseconds
30+
@Nullable
31+
private Runnable updateRunnable;
32+
33+
@Override
34+
protected void onCreate(Bundle savedInstanceState) {
35+
super.onCreate(savedInstanceState);
36+
binding = ActivityFlysightBinding.inflate(getLayoutInflater());
37+
setContentView(binding.getRoot());
38+
}
39+
40+
@Override
41+
protected void onResume() {
42+
super.onResume();
43+
44+
// Start GPS updates
45+
Services.location.locationUpdates.subscribeMain(this);
46+
updateGPS();
47+
48+
// Start event updates
49+
EventBus.getDefault().register(this);
50+
51+
// Start BLE scanning
52+
if (Services.bluetooth.ble.bluetoothState == BluetoothState.BT_STOPPED) {
53+
Services.bluetooth.ble.start(this);
54+
}
55+
56+
// Periodic UI updates
57+
updateRunnable = new Runnable() {
58+
public void run() {
59+
update();
60+
handler.postDelayed(this, updateInterval);
61+
}
62+
};
63+
handler.post(updateRunnable);
64+
update();
65+
}
66+
67+
@Override
68+
protected void onPause() {
69+
super.onPause();
70+
handler.removeCallbacks(updateRunnable);
71+
updateRunnable = null;
72+
EventBus.getDefault().unregister(this);
73+
Services.location.locationUpdates.unsubscribeMain(this);
74+
}
75+
76+
private void updateGPS() {
77+
final MLocation loc = Services.location.lastLoc;
78+
// TODO: Only from flysight
79+
if (loc != null && Services.bluetooth.preferences.preferenceEnabled) {
80+
if (Numbers.isReal(loc.latitude) && Numbers.isReal(loc.latitude)) {
81+
String ll = String.format(Locale.getDefault(), "%.6f, %.6f", loc.latitude, loc.longitude);
82+
if (Numbers.isReal(loc.altitude_gps)) {
83+
ll += ", " + Convert.distance(loc.altitude_gps, 2, true);
84+
}
85+
if (Numbers.isReal(loc.groundSpeed())) {
86+
ll += ", " + Convert.speed(loc.groundSpeed(), 2, true);
87+
}
88+
binding.flysightGpsLabel.setText(ll);
89+
} else {
90+
binding.flysightGpsLabel.setText("");
91+
}
92+
} else {
93+
binding.flysightGpsLabel.setText("");
94+
}
95+
}
96+
97+
/**
98+
* Updates the UI that refresh continuously, such as sample rates
99+
*/
100+
private void update() {
101+
// Check phone permissions
102+
binding.btPhoneStatus.setText("Phone OK");
103+
binding.btPhoneStatus.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.status_green, 0, 0);
104+
if (!Services.bluetooth.preferences.preferenceEnabled) {
105+
// Check android location permission
106+
if (!Permissions.hasLocationPermissions(this)) {
107+
binding.btPhoneStatus.setText("Permission required");
108+
binding.btPhoneStatus.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.status_red, 0, 0);
109+
} else if (!Permissions.isLocationServiceEnabled(this)) {
110+
binding.btPhoneStatus.setText("Location disabled");
111+
binding.btPhoneStatus.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.status_red, 0, 0);
112+
}
113+
} else {
114+
// Check bluetooth permissions
115+
if (!Permissions.hasBluetoothPermissions(this)) {
116+
binding.btPhoneStatus.setText("Permission required");
117+
binding.btPhoneStatus.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.status_red, 0, 0);
118+
}
119+
}
120+
// Bluetooth status
121+
if (Services.bluetooth.preferences.preferenceEnabled) {
122+
// FlySight selected for GPS
123+
binding.btGpsStatus.setText(Services.bluetooth.getStatusMessage(this));
124+
if (Services.bluetooth.getState() == BluetoothState.BT_CONNECTED) {
125+
binding.btGpsStatus.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.status_green, 0, 0);
126+
} else {
127+
binding.btGpsStatus.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.status_red, 0, 0);
128+
}
129+
// Satellite signal status
130+
final long lastFixDuration = Services.location.lastFixDuration();
131+
if (lastFixDuration < 0) {
132+
binding.btSatStatus.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.status_red, 0, 0);
133+
binding.btSatStatus.setText("No fix");
134+
} else if (lastFixDuration > 5000) {
135+
binding.btSatStatus.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.status_red, 0, 0);
136+
binding.btSatStatus.setText("No fix");
137+
} else if (lastFixDuration > 1100) {
138+
binding.btSatStatus.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.status_yellow, 0, 0);
139+
binding.btSatStatus.setText("Last fix " + lastFixDuration / 1000L + "s"); // TODO: Periodic updater for last fix
140+
} else {
141+
final int hz = (int)(Services.location.refreshRate() + 0.5f);
142+
// 1 hz is not enough
143+
if (hz >= 2) {
144+
binding.btSatStatus.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.status_green, 0, 0);
145+
} else {
146+
binding.btSatStatus.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.status_yellow, 0, 0);
147+
}
148+
binding.btSatStatus.setText(String.format(Locale.getDefault(), "%d Hz", hz));
149+
}
150+
} else {
151+
// FlySight not selected for GPS
152+
binding.btGpsStatus.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.status_red, 0, 0);
153+
binding.btGpsStatus.setText("FS not selected");
154+
binding.btSatStatus.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.status_red, 0, 0);
155+
binding.btSatStatus.setText("FS GPS off");
156+
}
157+
}
158+
159+
@Override
160+
protected void onDestroy() {
161+
super.onDestroy();
162+
Services.sensors.gravity.setMaxSize(0);
163+
Services.sensors.rotation.setMaxSize(0);
164+
}
165+
166+
// Listeners
167+
@Override
168+
public void apply(@NonNull MLocation loc) {
169+
updateGPS();
170+
}
171+
172+
/**
173+
* Listen for altitude updates
174+
*/
175+
@Subscribe(threadMode = ThreadMode.MAIN)
176+
public void onBluetoothEvent(BluetoothEvent event) {
177+
updateGPS();
178+
}
179+
180+
}

app/src/main/java/com/platypii/baseline/views/MainActivity.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ protected void onCreate(Bundle savedInstanceState) {
5757
binding.nav.setOnClickListener(this::clickNav);
5858
binding.tracks.setOnClickListener(this::clickTracks);
5959
binding.profiles.setOnClickListener(this::clickLasers);
60+
binding.flysight.setOnClickListener(this::clickFlysight);
6061
binding.settings.setOnClickListener(this::clickSettings);
6162
}
6263

@@ -186,6 +187,11 @@ public void clickLasers(View v) {
186187
startActivity(new Intent(this, LaserActivity.class));
187188
}
188189

190+
public void clickFlysight(View v) {
191+
firebaseAnalytics.logEvent("click_flysight", null);
192+
startActivity(new Intent(this, FlysightActivity.class));
193+
}
194+
189195
public void clickSettings(View v) {
190196
firebaseAnalytics.logEvent("click_settings", null);
191197
startActivity(new Intent(this, SettingsActivity.class));

app/src/main/java/com/platypii/baseline/views/bluetooth/BluetoothActivity.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,10 @@ private void updateViews() {
9191
binding.btSatStatus.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.status_yellow, 0, 0);
9292
binding.btSatStatus.setText("Last fix " + lastFixDuration / 1000L + "s"); // TODO: Periodic updater for last fix
9393
} else {
94-
final int sats = Services.location.lastLoc.satellitesUsed;
94+
int sats = -1;
95+
if (Services.location.lastLoc != null) {
96+
sats = Services.location.lastLoc.satellitesUsed;
97+
}
9598
final int hz = (int)(Services.location.refreshRate() + 0.5f);
9699
// 1 hz is not enough
97100
if (hz >= 2) {

app/src/main/java/com/platypii/baseline/views/bluetooth/BluetoothAdapter.java

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package com.platypii.baseline.views.bluetooth;
22

3-
import android.os.Build;
43
import com.platypii.baseline.R;
54
import com.platypii.baseline.Services;
65
import com.platypii.baseline.bluetooth.BluetoothItem;
@@ -23,12 +22,9 @@ class BluetoothAdapter extends BaseAdapter {
2322

2423
private final LayoutInflater inflater;
2524

26-
private final String internalGps;
27-
2825
BluetoothAdapter(@NonNull Context context, @NonNull List<BluetoothItem> devices) {
2926
this.devices = devices;
3027
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
31-
internalGps = context.getString(R.string.internal_gps);
3228
}
3329

3430
@Override
@@ -42,20 +38,18 @@ public View getView(int position, @Nullable View convertView, @NonNull ViewGroup
4238
final TextView addressView = convertView.findViewById(R.id.bluetooth_id);
4339
final ImageView checkedView = convertView.findViewById(R.id.bluetooth_checked);
4440

45-
if (position == 0) {
41+
// Bluetooth GPS device
42+
final BluetoothItem device = devices.get(position);
43+
nameView.setText(device.name);
44+
addressView.setText(device.address);
45+
if (device.internal) {
4646
// Internal phone GPS
47-
nameView.setText(internalGps);
48-
addressView.setText(Build.MANUFACTURER + " " + Build.MODEL);
4947
if (!Services.bluetooth.preferences.preferenceEnabled) {
5048
checkedView.setVisibility(View.VISIBLE);
5149
} else {
5250
checkedView.setVisibility(View.GONE);
5351
}
5452
} else {
55-
// Bluetooth GPS device
56-
final BluetoothItem device = devices.get(position - 1);
57-
nameView.setText(device.name);
58-
addressView.setText(device.address);
5953
if (device.name.contains("GPS") || device.name.startsWith("FlySight") || device.name.startsWith("Mohawk")) {
6054
nameView.setTextColor(0xffeeeeee);
6155
} else {
@@ -73,12 +67,12 @@ public View getView(int position, @Nullable View convertView, @NonNull ViewGroup
7367

7468
@Override
7569
public int getCount() {
76-
return devices.size() + 1;
70+
return devices.size();
7771
}
7872

7973
@Override
8074
public Object getItem(int position) {
81-
return position == 0 ? null : devices.get(position - 1);
75+
return devices.get(position);
8276
}
8377

8478
@Override

app/src/main/java/com/platypii/baseline/views/bluetooth/BluetoothDeviceListFragment.java

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.platypii.baseline.views.bluetooth;
22

3+
import com.platypii.baseline.R;
34
import com.platypii.baseline.Services;
45
import com.platypii.baseline.bluetooth.BluetoothDeviceComparator;
56
import com.platypii.baseline.bluetooth.BluetoothItem;
@@ -9,6 +10,7 @@
910

1011
import android.app.Activity;
1112
import android.bluetooth.BluetoothDevice;
13+
import android.os.Build;
1214
import android.os.Bundle;
1315
import android.util.Log;
1416
import android.view.LayoutInflater;
@@ -33,26 +35,37 @@ public class BluetoothDeviceListFragment extends ListFragment {
3335
private final Set<BluetoothItem> deviceSet = new HashSet<>();
3436
@Nullable
3537
private BluetoothAdapter bluetoothAdapter;
38+
private String internalGps = "Phone GPS"; // cached "Phone GPS" string from context
3639

3740
@Nullable
3841
@Override
3942
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
4043
// Set list adapter
4144
final Activity activity = getActivity();
4245
if (activity != null) {
46+
internalGps = activity.getString(R.string.internal_gps);
4347
bluetoothAdapter = new BluetoothAdapter(activity, devices);
4448
setListAdapter(bluetoothAdapter);
4549
}
4650
return super.onCreateView(inflater, container, savedInstanceState);
4751
}
4852

53+
protected Set<BluetoothItem> getDeviceList() {
54+
final Set<BluetoothItem> devices = new HashSet<>();
55+
for (BluetoothDevice device : Services.bluetooth.getBondedDevices()) {
56+
devices.add(new BluetoothItem(device));
57+
}
58+
// Add internal phone gps
59+
final String phoneName = Build.MANUFACTURER + " " + Build.MODEL;
60+
deviceSet.add(new BluetoothItem(internalGps, phoneName, false, true));
61+
return devices;
62+
}
63+
4964
private void updateDeviceList() {
5065
devices.clear();
5166
deviceSet.clear();
5267
try {
53-
for (BluetoothDevice device : Services.bluetooth.getBondedDevices()) {
54-
deviceSet.add(new BluetoothItem(device));
55-
}
68+
deviceSet.addAll(getDeviceList());
5669
} catch (SecurityException e) {
5770
Log.e(TAG, "Error getting device list", e);
5871
}
@@ -68,15 +81,15 @@ public void onListItemClick(@NonNull ListView l, @NonNull View v, int position,
6881
final BluetoothItem device = (BluetoothItem) l.getItemAtPosition(position);
6982
final Activity activity = getActivity();
7083
if (activity != null) {
71-
if (device != null) {
84+
if (!device.internal) {
7285
Log.i(TAG, "Bluetooth device selected " + device.name);
7386

7487
if (!device.address.equals(Services.bluetooth.preferences.preferenceDeviceId)) {
7588
// Changed bluetooth device, reset state
7689
Services.location.locationProviderBluetooth.reset();
7790
}
7891

79-
// Save device preference
92+
// Save bluetooth device and enable bluetooth
8093
Services.bluetooth.preferences.save(activity, true, device.address, device.name, device.ble);
8194
// Update ui
8295
EventBus.getDefault().post(new BluetoothEvent());
@@ -90,7 +103,7 @@ public void onListItemClick(@NonNull ListView l, @NonNull View v, int position,
90103
Analytics.logEvent(activity, "bluetooth_selected", bundle);
91104
} else {
92105
Log.i(TAG, "Internal GPS selected");
93-
// Save device preference
106+
// Clear bluetooth device and disable bluetooth
94107
Services.bluetooth.preferences.save(activity, false, null, null, false);
95108
// Update ui
96109
EventBus.getDefault().post(new BluetoothEvent());

0 commit comments

Comments
 (0)