From 04e0a193732a002d642e48fed71d3a1d2c574bd8 Mon Sep 17 00:00:00 2001 From: Shankari Date: Sat, 13 Apr 2024 23:33:44 -0700 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=A5=20=E2=99=BB=EF=B8=8F=20=20Convert?= =?UTF-8?q?=20the=20transitions=20to=20the=20ones=20supported=20by=20the?= =?UTF-8?q?=20plumbing?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Consistent with https://github.com/e-mission/e-mission-docs/issues/1062#issuecomment-2053881279 - removed the newly added transitions - made them consistent with the plumbed through values - simplified the tracking logic in `TripDiaryStateMachineService` - minor refactoring to pull the isFleet check into an instance variable that we can reuse without having to read it every time Testing done: Non-fleet case - Start sending location - Not seeing any locations - Manually exit geofence ``` 04-13 22:51:45.962 23297 23297 I TripDiaryStateMachineRcvr: TripDiaryStateMachineReciever onReceive(android.app.ReceiverRestrictedContext@a7c085e, Intent { act=local.transition.exited_geofence flg=0x10 pkg=edu.berkeley.eecs.emission cmp=edu.berkeley.eecs.emission/.cordova.tracker.location.TripDiaryStateMachineReceiver }) called 04-13 22:51:46.118 23297 23297 D TripDiaryStateMachineService: handleAction(local.state.waiting_for_trip_start, local.transition.exited_geofence) called 04-13 22:51:46.160 23297 23297 D TripDiaryStateMachineService: Geofence exit in non-fleet mode, starting location tracking ``` - Stop sending locations - Manually end trip ``` 04-13 22:54:41.792 23297 23297 D TripDiaryStateMachineService: handleAction(local.state.ongoing_trip, local.transition.stopped_moving) completed, waiting for async operations to complete ``` Fleet case - Start sending location - Not seeing any locations ``` $ grep LocationChangeIntentService /tmp/logcat.log | tail 04-13 22:54:32.555 23297 32018 D LocationChangeIntentService: FINALLY! Got location update, intent is Intent { cmp=edu.berkeley.eecs.emission/.cordova.tracker.location.LocationChangeIntentService (has extras) } ``` - Manually exit geofence ``` 04-13 23:07:58.760 23297 23297 D TripDiaryStateMachineService: handleAction(local.state.waiting_for_trip_start, local.transition.exited_geofence) called 04-13 23:07:58.798 23297 23297 D TripDiaryStateMachineService: Geofence exit in fleet mode, checking for beacons before starting location tracking 04-13 23:07:58.807 23297 23297 D TripDiaryStateMachineService: handleAction(local.state.waiting_for_trip_start, local.transition.exited_geofence) completed, waiting for async operations to complete $ grep LocationChangeIntentService /tmp/logcat.log | tail 04-13 22:54:32.555 23297 32018 D LocationChangeIntentService: FINALLY! Got location update, intent is Intent { cmp=edu.berkeley.eecs.emission/.cordova.tracker.location.LocationChangeIntentService (has extras) } ``` - Generate BLE event ``` 04-13 23:11:26.244 23297 23297 D TripDiaryStateMachineService: handleAction(local.state.waiting_for_trip_start, local.transition.ble_beacon_found) called 04-13 23:11:26.293 23297 23297 D TripDiaryStateMachineService: TripDiaryStateMachineReceiver handleTripStart(local.transition.ble_beacon_found) called 04-13 23:11:26.319 23297 23297 D TripDiaryStateMachineService: Found beacon in fleet mode, starting location tracking 04-13 23:11:26.387 23297 23297 D ActivityRecognitionActions: Starting activity recognition with interval = 30000 04-13 23:11:26.490 23297 23297 D TripDiaryStateMachineService: handleAction(local.state.waiting_for_trip_start, local.transition.ble_beacon_found) completed, waiting for async operations to complete 04-13 23:11:26.568 23297 23297 D TripDiaryStateMachineService: newState after handling action is local.state.ongoing_trip $ grep LocationChangeIntentService /tmp/logcat.log | tail 04-13 23:20:58.573 23297 14437 D LocationChangeIntentService: FINALLY! Got location update, intent is Intent { cmp=edu.berkeley.eecs.emission/.cordova.tracker.location.LocationChangeIntentService (has extras) } $ grep LocationChangeIntentService /tmp/logcat.log | tail 04-13 23:22:28.651 23297 15241 D LocationChangeIntentService: FINALLY! Got location update, intent is Intent { cmp=edu.berkeley.eecs.emission/.cordova.tracker.location.LocationChangeIntentService (has extras) } ``` - Stop sending locations - Manually end trip ``` 04-13 23:23:24.649 23297 23297 D TripDiaryStateMachineService: handleAction(local.state.ongoing_trip, local.transition.stopped_moving) called 04-13 23:23:24.921 23297 23297 D TripDiaryStateMachineService: newState after handling action is local.state.waiting_for_trip_start 04-13 23:23:24.958 23297 23297 D TripDiaryStateMachineService: newState saved in prefManager is local.state.waiting_for_trip_start 04-13 23:22:54.173 23297 23297 D LocationChangeIntentService: onDestroy called 04-13 23:22:54.173 23297 23297 D LocationChangeIntentService: onDestroy called 04-13 23:22:54.173 23297 23297 D LocationChangeIntentService: onDestroy called ``` --- res/android/statemachine.xml | 3 - src/android/bluetooth/BluetoothService.java | 9 +-- .../TripDiaryStateMachineService.java | 75 +++++++++++-------- 3 files changed, 43 insertions(+), 44 deletions(-) diff --git a/res/android/statemachine.xml b/res/android/statemachine.xml index dec6196..eeb5e9e 100644 --- a/res/android/statemachine.xml +++ b/res/android/statemachine.xml @@ -14,9 +14,6 @@ local.transition.ble_beacon_found local.transition.ble_beacon_lost local.transition.tracking_error - local.transition.checking_for_beacon - local.transition.beacon_found - local.transition.beacon_not_found diff --git a/src/android/bluetooth/BluetoothService.java b/src/android/bluetooth/BluetoothService.java index c10e815..1fd3cc2 100644 --- a/src/android/bluetooth/BluetoothService.java +++ b/src/android/bluetooth/BluetoothService.java @@ -39,9 +39,6 @@ public int onStartCommand(Intent intent, int flags, int startId) { boolean bluetoothPermissions = SensorControlChecks.checkBluetoothScanningPermissions(this); if (!bluetoothPermissions) { - // If we aren't allowed, just say we found no beacons - Log.d(this, TAG, "Wanted to scan, but no bluetooth permissions!"); - this.sendBroadcast(new ExplicitIntent(this, R.string.transition_beacon_not_found)); return 1; } @@ -68,12 +65,8 @@ private void isInRange() { if (scanned.size() > 0) { Log.d(this, TAG, "Found something!"); Log.d(this, TAG, scanned.toString()); - this.sendBroadcast(new ExplicitIntent(this, R.string.transition_beacon_found)); - } else { - Log.d(this, TAG, "Did not find anything!"); - this.sendBroadcast(new ExplicitIntent(this, R.string.transition_beacon_not_found)); + this.sendBroadcast(new ExplicitIntent(this, R.string.transition_ble_beacon_found)); } - onDestroy(); } diff --git a/src/android/location/TripDiaryStateMachineService.java b/src/android/location/TripDiaryStateMachineService.java index fd230d7..cfde9d8 100644 --- a/src/android/location/TripDiaryStateMachineService.java +++ b/src/android/location/TripDiaryStateMachineService.java @@ -50,6 +50,7 @@ public class TripDiaryStateMachineService extends Service { private SharedPreferences mPrefs = null; private ForegroundServiceComm mComm = null; private JSONObject config; + private boolean isFleet = false; public TripDiaryStateMachineService() { super(); @@ -65,8 +66,11 @@ public void onCreate() { try { JSONObject c = (JSONObject) UserCacheFactory.getUserCache(this).getDocument("config/app_ui_config", false); config = c; + isFleet = (config != null && config.has("tracking") && config.getJSONObject("tracking").getBoolean("bluetooth_only")); } catch (JSONException e) { Log.d(this, TAG, "Error reading config! " + e); + // TODO: Need to figure out what to do about the fleet flag when the config is invalid + // Original implementation by @louisg1337 had isFleet = true in that case (location tracking would not stop) } } @@ -173,20 +177,7 @@ private void handleAction(Context ctxt, String currState, String actionString) { " skipping delete"); } - if (actionString.equals(ctxt.getString(R.string.transition_checking_for_beacon))) { - Log.d(this, TAG, "Checking for beacons!"); - // Start up the bluetooth service to check for beacons - Intent foregroundStartBluetooth = new Intent(ctxt, TripDiaryStateMachineForegroundService.class); - foregroundStartBluetooth.setAction("foreground_start_bluetooth"); - ctxt.startService(foregroundStartBluetooth); - } else if (actionString.equals(ctxt.getString(R.string.transition_beacon_found))) { - Log.d(this, TAG, "Beacons found, start the trip!"); - // Can now send to handleTripStart - handleTripStart(ctxt, actionString); - } else if (actionString.equals(ctxt.getString(R.string.transition_beacon_not_found))) { - Log.d(this, TAG, "Beacons not found, do nothing!"); - // For now we won't do anything if no beacon exists. Further thought is needed for edge cases where this may not work. - } else if (actionString.equals(ctxt.getString(R.string.transition_initialize))) { + if (actionString.equals(ctxt.getString(R.string.transition_initialize))) { handleStart(ctxt, actionString); } else if (currState.equals(ctxt.getString(R.string.state_start))) { handleStart(ctxt, actionString); @@ -259,27 +250,45 @@ private void handleStart(final Context ctxt, String actionString) { public void handleTripStart(Context ctxt, final String actionString) { Log.d(this, TAG, "TripDiaryStateMachineReceiver handleTripStart(" + actionString + ") called"); - if (actionString.equals(ctxt.getString(R.string.transition_exited_geofence)) || actionString.equals(ctxt.getString(R.string.transition_beacon_found)) ) { - - // Handle new bluetooth functionality. IF we have found a beacon, continue with starting the trip. - // If we are just normally exiting the geofence AND fleet mode, then transition to checking for beacons. - if (actionString.equals(ctxt.getString(R.string.transition_beacon_found))){ - Log.d(this, TAG, "In handleTripStart, beacon has been found so continue."); - } else { - // If we are in fleet mode, redirect to scan for beacons - try { - if (config != null && config.has("tracking") && config.getJSONObject("tracking").getBoolean("bluetooth_only")){ - Log.d(this, TAG, "Detected exited_geofence, but are in fleet mode so redirect to check for beacons!"); - - // Transition to checking for beacon state - ctxt.sendBroadcast(new ExplicitIntent(ctxt, R.string.transition_checking_for_beacon)); - return; - } - } catch (JSONException e) { - Log.d(this, TAG, "Error trying to read config to check for beacons."); + /* + * The logic here is simple. + * If we get a geofence exit, we have started moving. Since we are + * currently only addressing the uncommon case, we will check to see if + * we find a beacon. If so, we start location tracking. If not, we don't. + */ + + if (actionString.equals(ctxt.getString(R.string.transition_exited_geofence)) || actionString.equals(ctxt.getString(R.string.transition_ble_beacon_found))) { + // Since we only start bluetooth scanning after geofence exit now, + // we will never get a ble_beacon_found before the geofence exit + if (actionString.equals(ctxt.getString(R.string.transition_exited_geofence))) { + // we have a geofence exit, so we have started moving + if (isFleet) { + // fleet version, so we start ranging for bluetooth + Log.d(this, TAG, "Geofence exit in fleet mode, checking for beacons before starting location tracking"); + // Start up the bluetooth service to check for beacons + Intent foregroundStartBluetooth = new Intent(ctxt, TripDiaryStateMachineForegroundService.class); + foregroundStartBluetooth.setAction("foreground_start_bluetooth"); + ctxt.startService(foregroundStartBluetooth); + return; + } else { + Log.d(this, TAG, "Geofence exit in non-fleet mode, starting location tracking"); + } + } + + if (actionString.equals(ctxt.getString(R.string.transition_ble_beacon_found))) { + // we have found a BLE beacon. we only start ranging for BLE beacons in fleet mode + // so we should be in fleet mode here + if (isFleet) { + Log.d(this, TAG, "Found beacon in fleet mode, starting location tracking"); + } else { + Log.e(this, TAG, "Found beacon in non-fleet mode, not sure why this happened, starting location tracking anyway"); } } + // we will get here as long as we don't return, so all the "starting location tracking" will work properly + // but this is ugly + // TODO: Pull this out to a separate function and call the function from the if/then blocks + // Delete geofence // we cannot add null elements to the token list. // the LocationTracking start action can now return null @@ -337,7 +346,7 @@ public void handleTripStart(Context ctxt, final String actionString) { if (ConfigManager.getConfig(fCtxt).isSimulateUserInteraction()) { NotificationHelper.createNotification(fCtxt, STATE_IN_NUMBERS, null, fCtxt.getString(R.string.failed_moving_new_state,newState)); - } // both branches have called setState or are waiting for sth else + } // both branches have called setState or are waiting for sth else }); // listener end return; // handled the transition, returning }