diff --git a/app/src/main/java/com/platypus/android/server/Controller.java b/app/src/main/java/com/platypus/android/server/Controller.java
index 0d4d9fa..03f7202 100644
--- a/app/src/main/java/com/platypus/android/server/Controller.java
+++ b/app/src/main/java/com/platypus/android/server/Controller.java
@@ -57,6 +57,7 @@ public void onReceive(Context context, Intent intent) {
private ParcelFileDescriptor mUsbDescriptor = null;
private FileInputStream mUsbInputStream = null;
private FileOutputStream mUsbOutputStream = null;
+
/**
* Listen for disconnection events for accessory and close connection if we were using it.
*/
diff --git a/app/src/main/java/com/platypus/android/server/LauncherFragment.java b/app/src/main/java/com/platypus/android/server/LauncherFragment.java
index d37dd6a..a779aab 100644
--- a/app/src/main/java/com/platypus/android/server/LauncherFragment.java
+++ b/app/src/main/java/com/platypus/android/server/LauncherFragment.java
@@ -2,14 +2,17 @@
import android.app.ActivityManager;
import android.app.Fragment;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
+import android.os.IBinder;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.LayoutInflater;
@@ -24,6 +27,9 @@
import com.platypus.android.server.gui.SwipeOnlySwitch;
+import org.json.JSONException;
+import org.json.JSONObject;
+
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
@@ -42,12 +48,33 @@ public class LauncherFragment extends Fragment
private static final String TAG = LauncherFragment.class.getSimpleName();
+ // bind the VehicleService so we can send sensor type JSON commands
+ // https://developer.android.com/guide/components/bound-services.html
+ VehicleService mService;
+ boolean mBound = false;
+ private ServiceConnection mConnection = new ServiceConnection() {
+ @Override
+ public void onServiceConnected(ComponentName className, IBinder service) {
+ Log.d(TAG, "LauncherFragment: onServiceConnected() called...");
+ VehicleService.LocalBinder binder = (VehicleService.LocalBinder) service;
+ mService = binder.getService();
+ mBound = true;
+ sendSensorsJSON();
+ }
+ @Override
+ public void onServiceDisconnected(ComponentName arg0) {
+ Log.d(TAG, "LauncherFragment: onServiceDisconnected() called...");
+ mBound= false;
+ }
+ };
+
final Handler mHandler = new Handler();
protected TextView mHomeText;
protected TextView mIpAddressText;
protected Switch mLaunchSwitch;
protected Button mSetHomeButton;
+ protected Button mSetSensorsButton;
protected ImageView mVehicleImage;
protected LocationManager mLocationManager;
/**
@@ -60,10 +87,14 @@ public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
mLaunchSwitch.setEnabled(false);
if (!isVehicleServiceRunning()) {
// If the service is not running, start it.
- getActivity().startService(new Intent(getActivity(), VehicleService.class));
+ Log.d(TAG, "LauncherFragment: slider listener called...");
+ Intent intent = new Intent(getActivity(), VehicleService.class);
+ getActivity().startService(intent);
+ getActivity().bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
Log.i(TAG, "Vehicle service started.");
} else {
// If the service is running, stop it.
+ getActivity().unbindService(mConnection);
getActivity().stopService(new Intent(getActivity(), VehicleService.class));
Log.i(TAG, "Vehicle service stopped.");
}
@@ -97,6 +128,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container,
mIpAddressText = (TextView) view.findViewById(R.id.ip_address_text);
mLaunchSwitch = (SwipeOnlySwitch) view.findViewById(R.id.launcher_launch_switch);
mSetHomeButton = (Button) view.findViewById(R.id.launcher_home_button);
+ mSetSensorsButton = (Button) view.findViewById(R.id.launcher_sensors_button);
mVehicleImage = (ImageView) view.findViewById(R.id.launcher_vehicle_image);
// Add listener for starting/stopping vehicle service.
@@ -105,6 +137,9 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container,
// Add listener for home button click.
mSetHomeButton.setOnLongClickListener(new SetHomeListener());
+ // Add listener for sensors update button click
+ mSetSensorsButton.setOnLongClickListener(new UpdateSensorsListener());
+
return view;
}
@@ -244,6 +279,91 @@ public void updateServerAddress() {
String port = sharedPreferences.getString("pref_server_port", "11411");
mIpAddressText.setText(getLocalIpAddress() + ":" + port);
}
+
+ /**
+ * Listens for long-click events on "Update Sensors" button and updates sensor types
+ */
+ class UpdateSensorsListener implements View.OnLongClickListener {
+ @Override
+ public boolean onLongClick(View v) {
+ sendSensorsJSON();
+ return true;
+ }
+ }
+ void sendSensorsJSON()
+ {
+ Log.d(TAG, "LauncherFragment: sendSensorsJSON() called...");
+
+ if (mBound)
+ {
+ JSONObject sensors_JSON = generateSensorsJSON();
+ Log.d(TAG, " sensor JSON: ");
+ Log.d(TAG, sensors_JSON.toString());
+ mService.send(sensors_JSON);
+ mService.getServer().reset_expected_sensors(); // reset sensor type checks
+ }
+ else
+ {
+ Log.w(TAG, " mBound = false, sending nothing");
+ }
+ }
+ JSONObject generateSensorsJSON()
+ {
+ JSONObject sensors_JSON = new JSONObject();
+ for (int i = 1; i < 4; i++)
+ {
+ insertSensorJSON(i, sensors_JSON);
+ }
+ return sensors_JSON;
+ }
+ void insertSensorJSON(int sensorID, JSONObject sensors_JSON)
+ {
+ SharedPreferences sharedPreferences =
+ PreferenceManager.getDefaultSharedPreferences(getActivity());
+ String sensor_array_name = "pref_sensor_" + Integer.toString(sensorID) + "_type";
+ try
+ {
+ switch (sharedPreferences.getString(sensor_array_name, "NONE"))
+ {
+ case "NONE":
+ sensors_JSON.put(String.format("i%d", sensorID), "None");
+ break;
+ case "ATLAS_DO":
+ sensors_JSON.put(String.format("i%d", sensorID), "AtlasDO");
+ break;
+ case "ATLAS_PH":
+ sensors_JSON.put(String.format("i%d", sensorID), "AtlasPH");
+ break;
+ case "ES2":
+ sensors_JSON.put(String.format("i%d", sensorID), "ES2");
+ break;
+ case "HDS":
+ sensors_JSON.put(String.format("i%d", sensorID), "HDS");
+ break;
+ case "ADAFRUIT_GPS":
+ sensors_JSON.put(String.format("i%d", sensorID), "AdaGPS");
+ break;
+ case "AHRS_PLUS":
+ sensors_JSON.put(String.format("i%d", sensorID), "AHRSp");
+ break;
+ case "BLUEBOX":
+ sensors_JSON.put(String.format("i%d", sensorID), "BlueBox");
+ break;
+ case "WINCH":
+ sensors_JSON.put(String.format("i%d", sensorID), "Winch");
+ break;
+ case "SAMPLER":
+ sensors_JSON.put(String.format("i%d", sensorID), "Sampler");
+ break;
+ default:
+ break;
+ }
+ }
+ catch (JSONException e)
+ {
+ Log.w(TAG, "Failed to serialize sensor type.", e);
+ }
+ }
/**
* Listens for long-click events on "Set Home" button and updates home location.
diff --git a/app/src/main/java/com/platypus/android/server/VehicleServerImpl.java b/app/src/main/java/com/platypus/android/server/VehicleServerImpl.java
index a35c832..225d4dd 100644
--- a/app/src/main/java/com/platypus/android/server/VehicleServerImpl.java
+++ b/app/src/main/java/com/platypus/android/server/VehicleServerImpl.java
@@ -1,8 +1,12 @@
package com.platypus.android.server;
+import android.app.NotificationManager;
import android.content.Context;
import android.content.SharedPreferences;
+import android.media.RingtoneManager;
+import android.net.Uri;
import android.preference.PreferenceManager;
+import android.support.v4.app.NotificationCompat;
import android.util.Log;
import com.platypus.crw.AbstractVehicleServer;
@@ -105,6 +109,53 @@ public class VehicleServerImpl extends AbstractVehicleServer {
// Last known temperature and EC values for sensor compensation
private double _lastTemp = 20.0; // Deg C
private double _lastEC = 0.0; // uS/cm
+
+ //Define Notification Manager
+ NotificationManager notificationManager;
+ //Define sound URI
+ Uri soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
+
+ boolean[] received_expected_sensor_type = {false, false, false};
+ public void reset_expected_sensors()
+ {
+ for (int i = 0; i < 3; i++)
+ {
+ received_expected_sensor_type[i] = false;
+ }
+ }
+
+ private final Timer _sensorTypeTimer = new Timer();
+ private TimerTask expect_sensor_type_task = new TimerTask() {
+ @Override
+ public void run() {
+ for (int i = 0; i < 3; i++)
+ {
+ try {
+ Thread.sleep(1000); // sleep for all sensor slots, even if empty
+ } catch(InterruptedException ex) {
+ Thread.currentThread().interrupt();
+ }
+ if (!received_expected_sensor_type[i])
+ {
+ String sensor_array_name = "pref_sensor_" + Integer.toString(i+1) + "_type";
+ String expected_type = mPrefs.getString(sensor_array_name, "NONE");
+ if (expected_type.equals("NONE"))
+ {
+ continue;
+ }
+ String message = "s" + (i+1) + " expects " + expected_type + " not received yet";
+ Log.w(TAG, message);
+ NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(_context)
+ .setSmallIcon(R.drawable.camera_icon) //just some random icon placeholder
+ .setContentTitle("Sensor Warning")
+ .setContentText(message)
+ .setSound(soundUri); //This sets the sound to play
+ notificationManager.notify(0, mBuilder.build());
+ }
+ }
+ }
+ };
+
/**
* Internal update function called at regular intervals to process command
* and control events.
@@ -224,6 +275,9 @@ protected VehicleServerImpl(Context context, VehicleLogger logger, Controller co
// Connect to the Shared Preferences for this process.
mPrefs = PreferenceManager.getDefaultSharedPreferences(_context);
+ notificationManager = (NotificationManager) _context.getSystemService(Context.NOTIFICATION_SERVICE);
+ _sensorTypeTimer.scheduleAtFixedRate(expect_sensor_type_task, 0, 100);
+
// Load PID values from SharedPreferences.
// Use hard-coded defaults if not specified.
r_PID[0] = mPrefs.getFloat("gain_rP", 1.0f);
@@ -404,9 +458,40 @@ protected void onCommand(JSONObject cmd) {
} else if (name.startsWith("s")) {
int sensor = name.charAt(1) - 48;
+ // check sensor type expected in the preferences
+ String sensor_array_name = "pref_sensor_" + Integer.toString(sensor) + "_type";
+ String expected_type = mPrefs.getString(sensor_array_name, "NONE");
+
// Hacks to send sensor information
if (value.has("type")) {
String type = value.getString("type");
+
+ // check if received type matches expected type
+ if (!type.equalsIgnoreCase("battery")) {
+ if (type.equalsIgnoreCase(expected_type)) {
+ received_expected_sensor_type[sensor - 1] = true;
+ /*
+ String message = "s" + sensor + ": expected = " + expected_type + " received = " + type;
+ Log.w(TAG, message);
+ NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(_context)
+ .setSmallIcon(R.drawable.camera_icon) //just some random icon placeholder
+ .setContentTitle("Sensor Success")
+ .setContentText(message)
+ .setSound(soundUri); //This sets the sound to play
+ notificationManager.notify(0, mBuilder.build());
+ */
+ } else {
+ String message = "s" + sensor + ": expected = " + expected_type + " received = " + type;
+ Log.w(TAG, message);
+ NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(_context)
+ .setSmallIcon(R.drawable.camera_icon) //just some random icon placeholder
+ .setContentTitle("Sensor Warning")
+ .setContentText(message)
+ .setSound(soundUri); //This sets the sound to play
+ notificationManager.notify(0, mBuilder.build());
+ }
+ }
+
SensorData reading = new SensorData();
if (type.equalsIgnoreCase("es2")) {
diff --git a/app/src/main/java/com/platypus/android/server/VehicleService.java b/app/src/main/java/com/platypus/android/server/VehicleService.java
index 1009539..9e2a5b4 100644
--- a/app/src/main/java/com/platypus/android/server/VehicleService.java
+++ b/app/src/main/java/com/platypus/android/server/VehicleService.java
@@ -17,6 +17,7 @@
import android.location.LocationManager;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiManager.WifiLock;
+import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.Debug;
@@ -41,7 +42,9 @@
import org.jscience.geography.coordinates.LatLong;
import org.jscience.geography.coordinates.UTM;
import org.jscience.geography.coordinates.crs.ReferenceEllipsoid;
+import org.json.JSONObject;
+import java.io.IOException;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.measure.unit.NonSI;
@@ -75,6 +78,43 @@ public class VehicleService extends Service {
// Reference to vehicle controller;
private Controller mController;
+ public void send(JSONObject jsonObject)
+ {
+ Log.d(TAG, "VehicleService.send() called...");
+ if (mController != null)
+ {
+ try
+ {
+ if (mController.isConnected())
+ {
+ Log.d(TAG, " sending this JSON: ");
+ Log.d(TAG, jsonObject.toString());
+ mController.send(jsonObject);
+ }
+ else
+ {
+ Log.w(TAG, " mController is NOT connected");
+ }
+ }
+ catch (IOException e)
+ {
+ Log.w(TAG, "Failed to send command.", e);
+ }
+ }
+ else
+ {
+ Log.w(TAG, " mController is null");
+ }
+ }
+
+
+ public class LocalBinder extends Binder {
+ VehicleService getService() {
+ Log.d(TAG, "VehicleService: binding in process...");
+ return VehicleService.this;
+ }
+ }
+ private final IBinder mBinder = new LocalBinder();
// Objects implementing actual functionality
private VehicleServerImpl _vehicleServerImpl;
@@ -507,10 +547,9 @@ public void onFailure(@NonNull Exception e) {
super.onDestroy();
}
- @Nullable
@Override
public IBinder onBind(Intent intent) {
- return null;
+ return mBinder;
}
public void sendNotification(CharSequence text) {
diff --git a/app/src/main/res/layout/fragment_launcher.xml b/app/src/main/res/layout/fragment_launcher.xml
index d018b06..a6d6177 100644
--- a/app/src/main/res/layout/fragment_launcher.xml
+++ b/app/src/main/res/layout/fragment_launcher.xml
@@ -93,4 +93,13 @@
android:singleLine="true"
android:text="@string/launcher_swipe_right_text_content" />
+
+
diff --git a/app/src/main/res/values/strings_preferences.xml b/app/src/main/res/values/strings_preferences.xml
index 7ffde51..799b6e8 100644
--- a/app/src/main/res/values/strings_preferences.xml
+++ b/app/src/main/res/values/strings_preferences.xml
@@ -52,4 +52,76 @@
- DIFFERENTIAL
- VECTORED
+
+ - None
+ - Atlas DO
+ - Atlas pH
+ - ES2
+ - Lowrance HDS
+ - Adafruit GPS
+ - AHRS+
+ - BlueBox
+ - Winch
+ - Sampler
+
+
+ - NONE
+ - ATLAS_DO
+ - ATLAS_PH
+ - ES2
+ - HDS
+ - ADAFRUIT_GPS
+ - AHRS_PLUS
+ - BLUEBOX
+ - WINCH
+ - SAMPLER
+
+
+ - None
+ - Atlas DO
+ - Atlas pH
+ - ES2
+ - Lowrance HDS
+ - Adafruit GPS
+ - AHRS+
+ - BlueBox
+ - Winch
+ - Sampler
+
+
+ - NONE
+ - ATLAS_DO
+ - ATLAS_PH
+ - ES2
+ - HDS
+ - ADAFRUIT_GPS
+ - AHRS_PLUS
+ - BLUEBOX
+ - WINCH
+ - SAMPLER
+
+
+ - None
+ - Atlas DO
+ - Atlas pH
+ - ES2
+ - Lowrance HDS
+ - Adafruit GPS
+ - AHRS+
+ - BlueBox
+ - Winch
+ - Sampler
+
+
+ - NONE
+ - ATLAS_DO
+ - ATLAS_PH
+ - ES2
+ - HDS
+ - ADAFRUIT_GPS
+ - AHRS_PLUS
+ - BLUEBOX
+ - WINCH
+ - SAMPLER
+
diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml
index 8c37e18..827a41d 100644
--- a/app/src/main/res/xml/preferences.xml
+++ b/app/src/main/res/xml/preferences.xml
@@ -85,5 +85,31 @@
android:key="pref_vehicle_type"
android:title="@string/pref_vehicle_type_title"
android:summary="@string/pref_vehicle_type_summary" />
+
+
+
+
+