Skip to content

Commit

Permalink
🗃️ Plumb through an initial version of the native classes for the Blu…
Browse files Browse the repository at this point in the history
…etooth code

The data format is very similar to the beacon object in iOS.

We consciously patterned the object to be similar to `CLBeacon` since the
alt-beacon library for android is an effort to be compatible with iOS to the
extent possible.

Our only changes are to change the fields in iOS to be more easily serializable
e-mission/e-mission-docs#1062 (comment)
e-mission/e-mission-docs#1062 (comment)

Testing done:
After adding a hack to read/write messages on every ble_found transition,
e-mission/e-mission-phone#1144 (comment)
was able to verify that both read and write worked properly

Android:

```
sqlite> select * from userCache where type == "sensor-data";
1713026512.887||America/Los_Angeles|sensor-data|background/battery||{"android_health":"GOOD","android_plugged":"UNKNOWN","android_technology":"Li-ion","android_temperature":250,"android_voltage":250,"battery_level_pct":100.0,"battery_status":4,"ts":1.713026512887E9}
```

```
04-13 09:45:21.365 18332 18332 I TripDiaryStateMachineRcvr: TripDiaryStateMachineReciever onReceive(android.app.ReceiverRestrictedContext@9e3bd75, Intent { act=local.transition.ble_beacon_found flg=0x10 pkg=edu.berkeley.eecs.emission cmp=edu.berkeley.eecs.emission/.cordova.tracker.location.TripDiaryStateMachineReceiver }) called
04-13 09:45:21.385 18332 18332 I TripDiaryStateMachineService: Service created. Initializing one-time variables!
04-13 09:45:21.396 18332 18332 D TripDiaryStateMachineService: service started with flags = 0 startId = 1 action = local.transition.ble_beacon_found
04-13 09:45:21.404 18332 18332 D TripDiaryStateMachineService: after reading from the prefs, the current state is local.state.waiting_for_trip_start
04-13 09:45:21.424 18332 18332 D BuiltinUserCache: Added value for key statemachine/transition at time 1.713026721405E9
04-13 09:45:21.432 18332 18332 D TripDiaryStateMachineService: handleAction(local.state.waiting_for_trip_start, local.transition.ble_beacon_found) called
04-13 09:45:21.448 18332 18332 D BuiltinUserCache: Added value for key background/battery at time 1.713026721433E9
04-13 09:45:21.464 18332 18332 D BuiltinUserCache: Added value for key background/bluetooth_ble at time 1.713026721449E9
04-13 09:45:21.479 18332 18332 D BuiltinUserCache: Added value for key background/bluetooth_ble at time 1.713026721465E9
04-13 09:45:21.493 18332 18332 D BuiltinUserCache: Added value for key background/bluetooth_ble at time 1.71302672148E9
04-13 09:45:21.520 18332 18332 D BuiltinUserCache: Added value for key background/bluetooth_ble at time 1.713026721493E9
04-13 09:45:21.532 18332 18332 D BuiltinUserCache: Added value for key background/bluetooth_ble at time 1.71302672152E9
04-13 09:45:21.546 18332 18332 D BuiltinUserCache: Added value for key background/bluetooth_ble at time 1.713026721533E9
04-13 09:45:21.548 18332 18332 I System.out: [BLE native] Found 5 entries
04-13 09:45:21.548 18332 18332 I System.out: [BLE native] First entry is edu.berkeley.eecs.emission.cordova.tracker.wrapper.BluetoothBLE@afc8f12 last entry is edu.berkeley.eecs.emission.cordova.tracker.wrapper.BluetoothBLE@b0c96e3
04-13 09:45:21.548 18332 18332 I System.out: [BLE native] while handling transition local.transition.ble_beacon_found
```

```
sqlite> select * from userCache where type == "sensor-data";
1713026512.887||America/Los_Angeles|sensor-data|background/battery||{"android_health":"GOOD","android_plugged":"UNKNOWN","android_technology":"Li-ion","android_temperature":250,"android_voltage":250,"battery_level_pct":100.0,"battery_status":4,"ts":1.713026512887E9}
1713026710.433||America/Los_Angeles|sensor-data|background/battery||{"android_health":"GOOD","android_plugged":"UNKNOWN","android_technology":"Li-ion","android_temperature":250,"android_voltage":250,"battery_level_pct":100.0,"battery_status":4,"ts":1.713026710432E9}
1713026712.809||America/Los_Angeles|sensor-data|background/battery||{"android_health":"GOOD","android_plugged":"UNKNOWN","android_technology":"Li-ion","android_temperature":250,"android_voltage":250,"battery_level_pct":100.0,"battery_status":4,"ts":1.713026712808E9}
1713026721.433||America/Los_Angeles|sensor-data|background/battery||{"android_health":"GOOD","android_plugged":"UNKNOWN","android_technology":"Li-ion","android_temperature":250,"android_voltage":250,"battery_level_pct":100.0,"battery_status":4,"ts":1.713026721433E9}
1713026721.449||America/Los_Angeles|sensor-data|background/bluetooth_ble||{"accuracy":100.0,"eventType":"REGION_ENTER","major":4538,"minor":1256,"proximity":"ProximityNear","rssi":10,"ts":1.713026721E9,"uuid":"0e27c613-ff78-486c-b523-950776777d16"}
1713026721.465||America/Los_Angeles|sensor-data|background/bluetooth_ble||{"accuracy":100.0,"eventType":"RANGE_UPDATE","major":4538,"minor":1256,"proximity":"ProximityNear","rssi":10,"ts":1.713026721E9,"uuid":"d8635e19-4133-493c-b2fd-c04fdd920c6a"}
1713026721.48||America/Los_Angeles|sensor-data|background/bluetooth_ble||{"accuracy":100.0,"eventType":"RANGE_UPDATE","major":4538,"minor":1256,"proximity":"ProximityNear","rssi":10,"ts":1.713026721E9,"uuid":"5efe9e8b-ce30-4417-80e3-79ce9ff53ca9"}
1713026721.493||America/Los_Angeles|sensor-data|background/bluetooth_ble||{"accuracy":100.0,"eventType":"RANGE_UPDATE","major":4538,"minor":1256,"proximity":"ProximityNear","rssi":10,"ts":1.713026721E9,"uuid":"d9283862-2926-4a0c-b377-0e80718e6525"}
1713026721.52||America/Los_Angeles|sensor-data|background/bluetooth_ble||{"accuracy":100.0,"eventType":"RANGE_UPDATE","major":4538,"minor":1256,"proximity":"ProximityNear","rssi":10,"ts":1.713026721E9,"uuid":"cef2f3df-30c5-49d5-8707-2f234530ef18"}
1713026721.533||America/Los_Angeles|sensor-data|background/bluetooth_ble||{"accuracy":100.0,"eventType":"RANGE_UPDATE","major":4538,"minor":1256,"proximity":"ProximityNear","rssi":10,"ts":1.713026721E9,"uuid":"326876e5-9869-407d-976c-2de438bec330"}
1713026800.123||America/Los_Angeles|sensor-data|background/battery||{"android_health":"GOOD","android_plugged":"UNKNOWN","android_technology":"Li-ion","android_temperature":250,"android_voltage":250,"battery_level_pct":100.0,"battery_status":4,"ts":1.713026800121E9}
1713026800.788||America/Los_Angeles|sensor-data|background/battery||{"android_health":"GOOD","android_plugged":"UNKNOWN","android_technology":"Li-ion","android_temperature":250,"android_voltage":250,"battery_level_pct":100.0,"battery_status":4,"ts":1.713026800788E9}
```

iOS

```
$ sqlite3 /Users/kshankar/Library/Developer/CoreSimulator/Devices/42B6F8A1-A925-4CAD-A48A-4835D69595ED/data/Containers/Data/Application/13D8F42C-921C-4754-9420-89C4350CE63F/Library/LocalDatabase/userCacheDB
SQLite version 3.39.5 2022-10-14 20:58:05
Enter ".help" for usage hints.
sqlite> select * from userCache where type == "sensor-data";
sqlite>
```

```
2024-04-13 09:34:56.566596-0700 emission[17352:9891606] In TripDiaryStateMachine, received transition T_BLE_BEACON_FOUND in state STATE_ONGOING_TRIP
2024-04-13 09:34:56.566796-0700 emission[17352:9891606] DEBUG: In TripDiaryStateMachine, received transition T_BLE_BEACON_FOUND in state STATE_ONGOING_TRIP
2024-04-13 09:34:56.568786-0700 emission[17352:9891606] data has 92 bytes, str has size 92
2024-04-13 09:34:56.570995-0700 emission[17352:9891606] data has 69 bytes, str has size 69
2024-04-13 09:35:12.781616-0700 emission[17352:9891606] data has 177 bytes, str has size 177
2024-04-13 09:35:12.784409-0700 emission[17352:9891606] data has 176 bytes, str has size 176
2024-04-13 09:35:12.786659-0700 emission[17352:9891606] data has 177 bytes, str has size 177
2024-04-13 09:35:12.789160-0700 emission[17352:9891606] data has 177 bytes, str has size 177
2024-04-13 09:35:12.791407-0700 emission[17352:9891606] data has 176 bytes, str has size 176
2024-04-13 09:35:12.793945-0700 emission[17352:9891606] data has 177 bytes, str has size 177
2024-04-13 09:35:17.900501-0700 emission[17352:9891606] [BLE native] Found 5 entries
2024-04-13 09:35:17.900666-0700 emission[17352:9891606] [BLE native] First entry is <BluetoothBLE: 0x6000010b8c80>, last entry is <BluetoothBLE: 0x6000010ba3f0>
2024-04-13 09:35:17.900773-0700 emission[17352:9891606] [BLE native] while handling transition T_BLE_BEACON_FOUND
2024-04-13 09:35:20.434450-0700 emission[17352:9891606] Got unexpected transition T_BLE_BEACON_FOUND in state STATE_ONGOING_TRIP, ignoring
```

```
sqlite> select * from userCache where type == "sensor-data";
1713026112.78185||America/Los_Angeles|sensor-data|background/bluetooth_ble||{"major":4538,"minor":1256,"rssi":10,"eventType":"REGION_ENTER","ts":1713026111.2200561,"uuid":"35355A74-E587-4F09-B114-D6718E925DC0","proximity":"ProximityNear","accuracy":100}
1713026112.78457||America/Los_Angeles|sensor-data|background/bluetooth_ble||{"major":4538,"minor":1256,"rssi":10,"eventType":"RANGE_UPDATE","ts":1713026112.784344,"uuid":"3448C47C-BE3B-40B8-A11F-4BD3CC1C2F63","proximity":"ProximityNear","accuracy":100}
1713026112.78698||America/Los_Angeles|sensor-data|background/bluetooth_ble||{"major":4538,"minor":1256,"rssi":10,"eventType":"RANGE_UPDATE","ts":1713026112.7865958,"uuid":"A2778875-CDF8-4AA8-A2E1-0639C9B4B159","proximity":"ProximityNear","accuracy":100}
1713026112.78947||America/Los_Angeles|sensor-data|background/bluetooth_ble||{"major":4538,"minor":1256,"rssi":10,"eventType":"RANGE_UPDATE","ts":1713026112.7891002,"uuid":"EE5129DA-6D64-4B25-BA68-3FB3D0FE6BD6","proximity":"ProximityNear","accuracy":100}
1713026112.79173||America/Los_Angeles|sensor-data|background/bluetooth_ble||{"major":4538,"minor":1256,"rssi":10,"eventType":"RANGE_UPDATE","ts":1713026112.791352,"uuid":"5B6A86F3-BE4D-498E-A3FD-0CAB6039914E","proximity":"ProximityNear","accuracy":100}
1713026112.7941||America/Los_Angeles|sensor-data|background/bluetooth_ble||{"major":4538,"minor":1256,"rssi":10,"eventType":"RANGE_UPDATE","ts":1713026112.7938981,"uuid":"71E73F8E-4138-4346-8E5F-D05E045A6D69","proximity":"ProximityNear","accuracy":100}
```
  • Loading branch information
shankari committed Apr 13, 2024
1 parent 9f8bb9f commit 4220302
Show file tree
Hide file tree
Showing 7 changed files with 184 additions and 5 deletions.
7 changes: 6 additions & 1 deletion plugin.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<plugin xmlns="http://www.phonegap.com/ns/plugins/1.0"
id="cordova-plugin-em-datacollection"
version="1.8.3">
version="1.8.4">

<name>DataCollection</name>
<description>Background data collection FTW! This is the part that I really
Expand Down Expand Up @@ -80,6 +80,8 @@
<action android:name="local.transition.stopped_moving"></action>
<action android:name="local.transition.stop_tracking"></action>
<action android:name="local.transition.start_tracking"></action>
<action android:name="local.transition.ble_beacon_found"></action>
<action android:name="local.transition.ble_beacon_lost"></action>
<action android:name="local.transition.tracking_error"></action>
</intent-filter>
</receiver>
Expand Down Expand Up @@ -169,6 +171,7 @@
<source-file src="src/android/wrapper/Transition.java" target-dir="src/edu/berkeley/eecs/emission/cordova/tracker/wrapper"/>
<source-file src="src/android/wrapper/LocationTrackingConfig.java" target-dir="src/edu/berkeley/eecs/emission/cordova/tracker/wrapper"/>
<source-file src="src/android/wrapper/Battery.java" target-dir="src/edu/berkeley/eecs/emission/cordova/tracker/wrapper"/>
<source-file src="src/android/wrapper/BluetoothBLE.java" target-dir="src/edu/berkeley/eecs/emission/cordova/tracker/wrapper"/>
<source-file src="src/android/wrapper/ConsentConfig.java" target-dir="src/edu/berkeley/eecs/emission/cordova/tracker/wrapper"/>
<source-file src="src/android/wrapper/Timer.java" target-dir="src/edu/berkeley/eecs/emission/cordova/tracker/wrapper"/>
<source-file src="src/android/wrapper/StatsEvent.java" target-dir="src/edu/berkeley/eecs/emission/cordova/tracker/wrapper"/>
Expand Down Expand Up @@ -247,6 +250,7 @@
<header-file src="src/ios/Wrapper/Transition.h" target-dir="Wrapper"/>
<header-file src="src/ios/Wrapper/LocationTrackingConfig.h" target-dir="Wrapper"/>
<header-file src="src/ios/Wrapper/Battery.h" target-dir="Wrapper"/>
<header-file src="src/ios/Wrapper/BluetoothBLE.h" target-dir="Wrapper"/>
<header-file src="src/ios/Wrapper/ConsentConfig.h" target-dir="Wrapper"/>
<header-file src="src/ios/Wrapper/Timer.h" target-dir="Wrapper"/>
<header-file src="src/ios/Wrapper/StatsEvent.h" target-dir="Wrapper"/>
Expand All @@ -269,6 +273,7 @@
<source-file src="src/ios/Wrapper/Transition.m" target-dir="Wrapper"/>
<source-file src="src/ios/Wrapper/LocationTrackingConfig.m" target-dir="Wrapper"/>
<source-file src="src/ios/Wrapper/Battery.m" target-dir="Wrapper"/>
<source-file src="src/ios/Wrapper/BluetoothBLE.m" target-dir="Wrapper"/>
<source-file src="src/ios/Wrapper/ConsentConfig.m" target-dir="Wrapper"/>
<source-file src="src/ios/Wrapper/Timer.m" target-dir="Wrapper"/>
<source-file src="src/ios/Wrapper/StatsEvent.m" target-dir="Wrapper"/>
Expand Down
4 changes: 2 additions & 2 deletions res/android/statemachine.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
<string name="transition_stopped_moving">local.transition.stopped_moving</string>
<string name="transition_stop_tracking">local.transition.stop_tracking</string>
<string name="transition_start_tracking">local.transition.start_tracking</string>
<string name="ble_beacon_found">local.transition.ble_beacon_found</string>
<string name="ble_beacon_lost">local.transition.ble_beacon_lost</string>
<string name="transition_ble_beacon_found">local.transition.ble_beacon_found</string>
<string name="transition_ble_beacon_lost">local.transition.ble_beacon_lost</string>
<string name="transition_tracking_error">local.transition.tracking_error</string>
<!-- <string name="transition_actions_started">local.transition.actions_started</string>
<string name="transition_actions_complete">local.transition.actions_complete</string> -->
Expand Down
4 changes: 2 additions & 2 deletions src/android/DataCollectionPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -214,8 +214,8 @@ private static Map<String, String> getTransitionMap(Context ctxt) {
retVal.put("STOPPED_MOVING", ctxt.getString(R.string.transition_stopped_moving));
retVal.put("STOP_TRACKING", ctxt.getString(R.string.transition_stop_tracking));
retVal.put("START_TRACKING", ctxt.getString(R.string.transition_start_tracking));
retVal.put("BLE_BEACON_FOUND", ctxt.getString(R.string.ble_beacon_found));
retVal.put("BLE_BEACON_LOST", ctxt.getString(R.string.ble_beacon_lost));
retVal.put("BLE_BEACON_FOUND", ctxt.getString(R.string.transition_ble_beacon_found));
retVal.put("BLE_BEACON_LOST", ctxt.getString(R.string.transition_ble_beacon_lost));
return retVal;
}

Expand Down
2 changes: 2 additions & 0 deletions src/android/location/TripDiaryStateMachineReceiver.java
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ public void onReceive(Context context, Intent intent) {
context.getString(R.string.transition_stopped_moving),
context.getString(R.string.transition_stop_tracking),
context.getString(R.string.transition_start_tracking),
context.getString(R.string.transition_ble_beacon_found),
context.getString(R.string.transition_ble_beacon_lost),
context.getString(R.string.transition_tracking_error)
}));

Expand Down
94 changes: 94 additions & 0 deletions src/android/wrapper/BluetoothBLE.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package edu.berkeley.eecs.emission.cordova.tracker.wrapper;

import java.util.UUID;

/**
* Created by shankari on 3/30/24.
*/
public class BluetoothBLE {
public String getEventType() {
return eventType;
}

/* Not sure if we need to return the UUID, major and minor
since we will only get callbacks for the registered UUID
and we don't need to check the major or minor in native code
only that it is **our** beacon. Let's hold off on them for now.
**/

/* We do need to use proximity in the FSM to avoid spurious exits (e.g. a
* personal car parked next to a fleet car may still see a region enter,
* but we don't want to track the trip because the proximity is "far".
*/
public String getProximity() {
return proximity;
}

public double getTs() {
return ts;
}

// Similarly, we store the accuracy and the rssi for the record, but the
// underlying API already converts it to a proximity value, so we use that
// instead

private String eventType;
private String uuid;
private int major;
private int minor;
private String proximity;
private double accuracy;
private int rssi;

private double ts;
// Should we put newState in here as well?
// If so, we will need to change the location of the save

private BluetoothBLE() {}

public static BluetoothBLE initRegionEnter(String uuid, double ts) {
BluetoothBLE enterEvent = new BluetoothBLE();
enterEvent.eventType = "REGION_ENTER";
enterEvent.uuid = uuid;
enterEvent.ts = ts;
return enterEvent;
}

public static BluetoothBLE initRegionExit(String uuid, double ts) {
BluetoothBLE exitEvent = new BluetoothBLE();
exitEvent.eventType = "REGION_EXIT";
exitEvent.uuid = uuid;
exitEvent.ts = ts;
return exitEvent;
}

public static BluetoothBLE initRangeUpdate(String uuid, double ts,
int major, int minor,
String proximity, double accuracy, int rssi) {
BluetoothBLE rangeEvent = new BluetoothBLE();
rangeEvent.eventType = "RANGE_UPDATE";
rangeEvent.uuid = uuid;
rangeEvent.ts = ts;

rangeEvent.major = major;
rangeEvent.minor = minor;
rangeEvent.proximity = proximity;
rangeEvent.accuracy = accuracy;
rangeEvent.rssi = rssi;
return rangeEvent;
}

public static BluetoothBLE initFakeWithEventType(String eventType) {
BluetoothBLE fakeEvent = new BluetoothBLE();
fakeEvent.uuid = UUID.randomUUID().toString();
fakeEvent.major = 4538;
fakeEvent.minor = 1256;
fakeEvent.proximity = "ProximityNear";
fakeEvent.accuracy = 100;
fakeEvent.rssi = 10;

fakeEvent.eventType = eventType;
fakeEvent.ts = System.currentTimeMillis() / 1000; // time is in seconds for us
return fakeEvent;
}
}
28 changes: 28 additions & 0 deletions src/ios/Wrapper/BluetoothBLE.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//
// Transition.h
// CFC_Tracker
//
// Created by Kalyanaraman Shankari on 10/27/15.
// Copyright © 2015 Kalyanaraman Shankari. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>

@interface BluetoothBLE : NSObject

- (instancetype)initWithCLBeacon:(CLBeacon *)beacon andEventType:(NSString *) eventType;
- (instancetype)initFakeWithEventType:(NSString *)eventType;

// fields from CLBeacon, modified to be easy to serialize and restore
@property NSString* uuid;
@property NSInteger major;
@property NSInteger minor;
@property NSString* proximity;
@property CLLocationAccuracy accuracy;
@property NSInteger rssi;
@property NSString* eventType;
@property double ts;

+ (NSString*) proximityToString:(CLProximity) proximityObj;
@end
50 changes: 50 additions & 0 deletions src/ios/Wrapper/BluetoothBLE.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
//
// Transition.m
// CFC_Tracker
//
// Created by Kalyanaraman Shankari on 10/27/15.
// Copyright © 2015 Kalyanaraman Shankari. All rights reserved.
//

#import "BluetoothBLE.h"
#import "DataUtils.h"

@implementation BluetoothBLE

-(id) initWithCLBeacon:(CLBeacon*) beacon andEventType:(NSString*) eventType {
self = [super init];
self.uuid = beacon.UUID;
self.major = beacon.major.integerValue;
self.minor = beacon.minor.integerValue;
self.proximity = [BluetoothBLE proximityToString:beacon.proximity];
self.accuracy = beacon.accuracy;
self.rssi = beacon.rssi;

self.eventType = eventType;
self.ts = [DataUtils dateToTs:beacon.timestamp];
return self;
}

-(id) initFakeWithEventType:(NSString*) eventType {
self = [super init];
self.uuid = [NSUUID UUID].UUIDString;
self.major = 4538;
self.minor = 1256;
self.proximity = [BluetoothBLE proximityToString:CLProximityNear];
self.accuracy = 100;
self.rssi = 10;

self.eventType = eventType;
self.ts = [DataUtils dateToTs:[NSDate now]];
return self;
}

+ (NSString*) proximityToString:(CLProximity) proximityObj {
if (proximityObj == CLProximityImmediate) { return @"ProximityImmediate"; };
if (proximityObj == CLProximityNear) { return @"ProximityNear"; };
if (proximityObj == CLProximityFar) { return @"ProximityFar"; };
return @"ProximityUnknown";
}


@end

0 comments on commit 4220302

Please sign in to comment.