Monday, September 23, 2013

Bluetooth 4 LE Mobile Rest client on iOS 7/Android 4 with abackendJAX-RS JPA 2 Java cloud service on Oracle WebLogic 12c

Bluetooth 4 LE Mobile Rest client on iOS 7/Android 4.3 with a backend JAX-RS JPA 2 Java cloud service on Oracle WebLogic 12c

The following post details my ongoing work in getting a mobile client [iOS 7 enabled iPhone 4s] to upload external biometric data from a Bluetooth 4.0 LE device such as the MIO watch or the Wahoo chest strap to a cloud based [Oracle WebLogic 12c] service.  I will also upload all available device data such as acceleration, rotation, gravity, light, humidity, temperature, magnetic fields, longitude/latitude, heading and altitude.

JAX-RS Testing

Here is a nearly ready for Apple submission - iPhone 5 based prototype that reads from two heart rate monitors simultaneously.  The data is uploaded real time to my Oracle Cloud data center where the two rates are correlated and used to eliminate heart rate spikes specific to a single device - for redundancy




BOM (Bill of Materials): 

- A Bluetooth 4.0 LE/Smart compatible device like the Apple iPhone 4s, 5 or 5c or the iPad mini 2nd gen
   or an Android 4.3+ device like the Samsung Galaxy S4 or Google Nexus 5
   or a BlackBerry 10 device like the Q10 or Z10
- a biometric device that emits low power Bluetooth 4.0 data like the Kickstarter LED pulse watch - MIO Alpha or more reliable wahoo chest strap which conforms to the Bluetooth Heart Rate Profile
- a cloud based data center service like Oracle WebLogic 12c or Cloudbees or even GAE that includes both a Java EE (preferably JPA 2 based backend with integrated Database like Oracle Database 11g.
- a local development version of Oracle WebLogic 12 with integrated OEPE Eclipse Kepler Java EE IDE
http://www.oracle.com/technetwork/middleware/weblogic/downloads/wls-main-097127.html
oepe-12.1.2.1-kepler-installer-win32.exe


Features

F1: Device independence or coverage (Android 4.3+ or Android 4.2.2 (Samsung), Blackberry 10, iOS 7 and optionally PhoneGap3/Webkit
F2: Sensor capture (device local) of positional, magnetic, acceleration, gravitational, rotational, light, pressure, humidity, sound data
F3: Sensor capture (device remote) of Bluetooth 4 LE (Smart) biometric data
F3.1: Multiple remote BT 4.0 capture (IE: Mio Alpha watch + Wahoo chest)
F4: Sensor display (device local and remote web monitoring)
F5: Sensor persistence (device local and online/offline remote data center)

Requirements

R1: Mobile sensor data capture
R2: Mobile data upload to data center
R3: Mobile data viewing
R4: Realtime local device based data analysis
R5: Realtime web based data analysis
R6: Mobile based data storage/caching
R7: Volumetrics: Time and Space performance analysis (best,average,worst)
R8: Resiliency: handle network timeout, unavailability through caching and concurrency
R9:

Architecture

Front end clients


Back end as a service (BaaS)


Development

We will be using the Core Bluetooth API introduced in iOS5 but targeting iOS7 just released in Sept 2013.
We will also be using Android 4.2.2 with the proprietary Samsung BLE API until I get get Android 4.3 on it containing generic BLE support.

Design Issues


DI1:  Handling network outages

DI2: Database for Backend
We will be using postgreSQL as the database backend.




Experimental Results

UUID, characteristics and data for the MIO Alpha bluetooth watch.

2013-09-26 21:48:54.395 Biometric[289:60b] CoreBluetooth[WARNING] <CBCentralManager: 0x16e994f0> is disabling duplicate filtering, but is using the default queue (main thread) for delegate events
2013-09-26 21:48:54.795 Biometric[289:60b] Connecting to peripheral <CBPeripheral: 0x16db2580 identifier = 398D853C-FE6D-A669-0E72-4A19D103CF0D, Name = "MIO GLOBAL", state = disconnected>
2013-09-26 21:48:55.501 Biometric[289:60b] Service found with UUID: Unknown (<6c721826 5bf14f64 9170381c 08ec57ee>)
2013-09-26 21:48:55.503 Biometric[289:60b] Service found with UUID: Device Information
2013-09-26 21:48:55.508 Biometric[289:60b] Service found with UUID: Unknown (<180d>)
2013-09-26 21:48:55.515 Biometric[289:60b] Discovered characteristic <CBCharacteristic: 0x16dc8020> UUID: Unknown (<6c722a0a 5bf14f64 9170381c 08ec57ee>)
2013-09-26 21:48:55.520 Biometric[289:60b] Discovered characteristic <CBCharacteristic: 0x16dd0850> UUID: Unknown (<6c722a0b 5bf14f64 9170381c 08ec57ee>)
2013-09-26 21:48:55.524 Biometric[289:60b] Discovered characteristic <CBCharacteristic: 0x16dc0460> UUID: Serial Number String
2013-09-26 21:48:55.527 Biometric[289:60b] Discovered characteristic <CBCharacteristic: 0x16ddb060> UUID: Manufacturer Name String
2013-09-26 21:48:55.530 Biometric[289:60b] Discovered characteristic <CBCharacteristic: 0x16dd23f0> UUID: System ID
2013-09-26 21:48:55.533 Biometric[289:60b] Discovered characteristic <CBCharacteristic: 0x16dd0df0> UUID: Firmware Revision String
2013-09-26 21:48:55.536 Biometric[289:60b] Discovered characteristic <CBCharacteristic: 0x16dca2b0> UUID: Hardware Revision String
2013-09-26 21:48:55.539 Biometric[289:60b] Discovered characteristic <CBCharacteristic: 0x16dd1280> UUID: Model Number String
2013-09-26 21:48:55.543 Biometric[289:60b] Discovered characteristic <CBCharacteristic: 0x16db5300> UUID: Software Revision String
2013-09-26 21:48:55.547 Biometric[289:60b] Discovered characteristic <CBCharacteristic: 0x16ea3f70> UUID: Unknown (<2a37>)
2013-09-26 21:48:55.551 Biometric[289:60b] Discovered characteristic <CBCharacteristic: 0x16ea3c70> UUID: Unknown (<2a38>)
2013-09-26 21:48:55.557 Biometric[289:60b] size: 4 value:<04030201>
2013-09-26 21:48:55.617 Biometric[289:60b] size: 4 value:<00000002
2013-09-26 21:48:55.677 Biometric[289:60b] size: 8 value:<30303030 46333344> 0000F33D
2013-09-26 21:48:55.737 Biometric[289:60b] size: 10 value:<4d494f20 474c4f42 414c> MIO GLOBAL
2013-09-26 21:48:55.797 Biometric[289:60b] size: 10 value:<3df30000 d86433d9 c9e9> (null)
2013-09-26 21:48:55.857 Biometric[289:60b] size: 5 value:<30322e30 33> 02.03
2013-09-26 21:48:55.917 Biometric[289:60b] size: 5 value:<30333233 38> 03238
2013-09-26 21:48:55.977 Biometric[289:60b] size: 10 value:<414c5048 41203533 5000> ALPHA 53P
2013-09-26 21:48:56.037 Biometric[289:60b] size: 8 value:<30312e30 392e3035> 01.09.05
2013-09-26 21:48:56.097 Biometric[289:60b] size: 4 value:<10367204> 6r

2013-09-26 21:48:56.157 Biometric[289:60b] size: 1 value:<02> 

Found the heart rate characteristic via the BLE specification site
https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.heart_rate_measurement.xml
It turns out the rate is encoded in the 2A37 characteristic


After fixing my callback I now see the embedded heart rate value in 2A37

2013-10-01 15:42:42.929 Biometric[536:60b] size: 4 value:<104b3303> K3 75
2013-10-01 15:42:43.926 Biometric[536:60b] size: 4 value:<104c2803> L( 76
2013-10-01 15:42:44.924 Biometric[536:60b] size: 4 value:<104d1e03> M 77
2013-10-01 15:42:45.921 Biometric[536:60b] size: 6 value:<104d1e03 1e03> M 77
2013-10-01 15:42:46.919 Biometric[536:60b] size: 4 value:<104d1e03> M 77
2013-10-01 15:42:47.916 Biometric[536:60b] size: 4 value:<104d1e03> M 77
2013-10-01 15:42:48.913 Biometric[536:60b] size: 6 value:<104d1e03 1e03> M 77
2013-10-01 15:42:49.911 Biometric[536:60b] size: 4 value:<104c2803> L( 76
2013-10-01 15:42:50.909 Biometric[536:60b] size: 4 value:<104c2803> L( 76

Setup

Android 4.2.2/4.3 on Samsung Galaxy S4 - deprecated

2014 Jan (use Android 4.4 on a Google Nexus instead)
Start with the blog entry below to enable your phone for development
http://stackoverflow.com/questions/16256048/eclipse-android-sdk-cannot-see-new-samsung-galaxy-s4-device-via-a-usb-connection
http://www.samsung.com/us/support/owners/product/SGH-I747MBBATT
You don't need KIES
http://www.samsung.com/in/support/usefulsoftware/KIES/JSP
http://www.androidcentral.com/how-get-developer-settings-galaxy-s4

study the API for Samsung BLE until Android 4.3 is enabled in Feb 2014 with standardized LE 4.0
http://developer.samsung.com/ble

References 

1) iOS6 Programming: Pushing the Limits, Rob Napier and Mugunth Kumar 2013, CH14: REST for the Weary, p.243
2) Bluetooth Smart Devices Technology website
3) https://developer.bluetooth.org/Pages/default.aspx
4) http://weblog.invasivecode.com/post/39707371281/core-bluetooth-for-ios-6-core-bluetooth-was
5) http://oleb.net/blog/2013/04/starting-bluetooth-low-energy-development-ios/
6) http://adcdownload.apple.com//wwdc_2012/wwdc_2012_session_pdfs/session_705__advanced_core_bluetooth.pdf
7)
Pro JPA 2.1 2nd edition by Mike Keith and Merrick Schincariol available at Apress, Amazon or partially at Google Books.

log

20131026: IOS 7 upload of heart rate via NSURLConnection

The IOS class NSURLConnection works about the same as the Java/Android HttpUrlConnection class and if easy to use.  I hardcoded the url and appended the heart rate from the 2a37 characteristic to test.

- (void) httpPushToDataCenter { NSMutableString *url = [[NSMutableString alloc ]init ]; [url appendString: cloudURLString]; [url appendString: @"&u=201310272&pr=ios"]; [url appendString: @"&hr="]; NSString *rateString = [NSString stringWithFormat:@"%hu", self.heartRate]; [url appendString: rateString]; NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString: url ] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0]; NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
I see the following on the Oracle data center
select IDENT_ID,TSSTOP,HEART from GPS_RECORD where userid=201310272

IDENT_IDTSSTOPHEART
1630901138280629409571
1630951138280629531971
1631001138280629633671
1631051138280629734271
1631101138280629831872
1631151138280629930771
1631201138280630031071
1631251138280630132571
1631301138280630287371
1631351138280630387172

20131027: Hiding the iOS keyboard for textviews

Apple has a bit of an issue surrounding closing the popup keyboard (Android gives you a done key).  It is the responsibility of the app to close the keyboard somehow - usually by clicking on empty app real estate or by assigning an action to another view.  Here I use the read-only text field for the heart rate to close any open keyboard.

- (IBAction)rateDown:(id)sender { [[self view] endEditing:YES]; }


20131029: Connecting to a WAHOO chest heart rate monitor

This HR monitor works well in an office/gym environment but it cuts out periodically in the field when rollerblading (unlike the MIO Alpha wrist HR monitor) - especially in temperatures down to +3 deg C.

However, my iOS 7 app picks up the monitor no problem - the issue now is I need to track both HR monitors simultaneously to get a better overall number.

2013-10-30 12:37:55.760 Biometric[806:60b] Setup
2013-10-30 12:37:55.798 Biometric[806:60b] Connecting to peripheral <CBPeripheral: 0x15557710 identifier = 4A90672B-EC3A-BEC2-5833-AD5A559DEE87, Name = "Wahoo HRM v2.1", state = disconnected>
2013-10-30 12:37:59.064 Biometric[806:60b] Connected to peripheral <CBPeripheral: 0x15557710 identifier = 4A90672B-EC3A-BEC2-5833-AD5A559DEE87, Name = "Wahoo HRM v2.1", state = connected>
2013-10-30 12:37:59.367 Biometric[806:60b] Service found with UUID: Device Information
2013-10-30 12:37:59.370 Biometric[806:60b] Service found with UUID: Unknown (<180d>)
2013-10-30 12:37:59.373 Biometric[806:60b] Service found with UUID: Battery
2013-10-30 12:37:59.375 Biometric[806:60b] Discovered characteristic <CBCharacteristic: 0x156531b0> UUID: Serial Number String
2013-10-30 12:37:59.377 Biometric[806:60b] Discovered characteristic <CBCharacteristic: 0x15647ce0> UUID: Manufacturer Name String
2013-10-30 12:37:59.378 Biometric[806:60b] Discovered characteristic <CBCharacteristic: 0x15647eb0> UUID: System ID
2013-10-30 12:37:59.380 Biometric[806:60b] Discovered characteristic <CBCharacteristic: 0x15652800> UUID: Firmware Revision String
2013-10-30 12:37:59.381 Biometric[806:60b] Discovered characteristic <CBCharacteristic: 0x156528c0> UUID: Hardware Revision String
2013-10-30 12:37:59.384 Biometric[806:60b] Discovered characteristic <CBCharacteristic: 0x15630ae0> UUID: Unknown (<2a37>)
2013-10-30 12:37:59.386 Biometric[806:60b] Discovered characteristic <CBCharacteristic: 0x15645240> UUID: Unknown (<2a38>)
2013-10-30 12:37:59.388 Biometric[806:60b] Discovered characteristic <CBCharacteristic: 0x15652ec0> UUID: Battery Level
2013-10-30 12:37:59.390 Biometric[806:60b] Discovered characteristic <CBCharacteristic: 0x15652150> UUID: Unknown (<2a1b>)
2013-10-30 12:37:59.392 Biometric[806:60b] Discovered characteristic <CBCharacteristic: 0x15652910> UUID: Unknown (<2a1a>)
2013-10-30 12:37:59.427 Biometric[806:60b] size: 6 value:<14439f03 9f03> C 67
2013-10-30 12:37:59.428 Biometric[806:60b] Sending: https://obrienscience-obrienlabs.*r?action=setGps&u=20131027&pr=ios&hr=67
2013-10-30 12:37:59.540 Biometric[806:60b] Notification began on <CBCharacteristic: 0x15630ae0>
2013-10-30 12:37:59.607 Biometric[806:60b] size: 6 value:<14439f03 9f03> C 67
2013-10-30 12:37:59.608 Biometric[806:60b] Sending: https://obrienscience-obrienlabs.*r?action=setGps&u=20131027&pr=ios&hr=67
2013-10-30 12:38:00.447 Biometric[806:60b] size: 16 value:<1442a403 a403a303 a3038b03 7c037603> B¤¤££|v 66

20131102: issues with Oracle WebLogic 12c response time on sub-second inserts using EclipseLink 2.3
I need to optimize the insert code as currently if I run 2 clients - an iOS7 app uploading heart rate data and an Android 4.2.2 app uploading everything else (all 27 data points) - both running every second - I get some network timeouts.
I also need to implement device side caching in period where the response time is reduced.
Here is an illustration of a field test while I was rolerblading - you will see some period where the Bluetooth 4 connection dropped to the Mio or Wahoo heart rate monitor.

I store and retrieve all my heart rate and other biometric data from the oracle cloud instance.
Reference rollerblade peak intervals
10 min exercise on treadmill - day 1


I had a major issue at 22 min after not running for 4 days - a 20 BPM spike from 158 to 178 and had to stop after 2 min.  I took the Mavik ACE inhibitor pill a bit earlier at 1800 - which was 2.5 hours before the run - when the full effects of the blood pressure lowering medication to kick in.  Later 30 min after the end of the run my BP was very low at 115/84/76 where it normally would be 145/105/80 before I started taking the ACE inhibitor 4 weeks ago. at 2330 I had a slight tight feeling around my heart.



In 7 seconds I went from 153 to 173 - a 20 BPM change around 22 min

1385084885943 1.002 149 151
1385084886944 1.001 151 151
1385084887904 0.96 153 152
1385084888959 1.055 156 153
1385084889914 0.955 156 153
1385084890893 0.979 156 157
1385084891867 0.974 165 160
1385084892920 1.053 172 160
1385084893928 1.008 174 168
1385084894903 0.975 174 171
1385084895941 1.038 174 171
1385084896903 0.962 174 173
1385084897928 1.025 176 174
1385084898938 1.01 178 175
1385084899897 0.959 178 176
1385084900919 1.022 178 176
1385084901924 1.005 176 176
Ms since 1970,diff, polar HR, mio HR

Connecting to two Heart Rate monitors for redundancy

The MIO Alpha watch has spikes of up to 200% where it will go from 80 BPM to 160 and return within a couple seconds.  These spikes can be filtered out in software.  There are also smaller spikes of 15-20 BPM that last up to 20 seconds that are hard to determine if they are due to the MIO HR watch itself or the wearer (an extra heartbeat confuses the multiplexed LED sensor?) - to workaround this my HR monitor/upload app can connect to two devices simultaneously - the heart rate values are both sent to the data center.
Here for example I am connected to the MIO Alpha Heart Rate watch and the Wahoo 2.1 Heart Rate chest strap.

Enabling the iOS Magnetometer in Xcode 5

You need to add "magnetometer" to the required device capabilities list in the plist file.

Adding CoreGraphics to an iOS UIView

Using color coded buttons with the current sensor value is good for a static snapshot but some historical context is required.  You add graphics capability under the standard views by subclassing UIView and assigning this subclass to your ViewController.  You must override the following callback.

- (void)drawRect:(CGRect)rect {
  CGContextRef g = UIGraphicsGetCurrentContext();
}

Adding Core Data persistence in iOS 7


Results
2014-05-25 00:24:28.809 Biometric[269:60b] <Device: 0x1780b9860> (entity: Device; id: 0xd000000000040000 <x-coredata://F02B5272-245D-4A76-94D9-3EB8EB92CD64/Device/p1> ; data: {
    id = iphone5;

})

20131129: Google Bluetooth 4.0 BLE API support in 4.3

Samsung pushed the Android 4.3- API18 update yesterday to the Galaxy S4 - therefore I can use standard Bluetooth 4.0 LE Heart Rate Profile spec code.  Since I got a Google Nexus 5 phone with Android 4.4 API19 - I now have 2 phones with spec BLE.



TODO

webservice
rest service
configurable length queue for http requests - each with a success/fail callback
option for local persistence
queue if fed by default from local persistence
refactor for key/value pair for each data point


local ui:


web ui:

2 comments:

Mirna said...

This things are awesome, but i don't know if this biometric system its helpful for us because they have know our finger print so there is no way back to the privacy, but i still like difference between operating system i like more the ios 7

Michael O'Brien said...

Mirna, my app is completely anonymous. I don't use the fingerprint reader on the iphone 5s. I use either an iphone 4s or 5 and connect via Bluetooth 4 LE to a pulse watch or chest monitor to get the heart rate. For all other accelerometer, gravity, gyroscope, GPS, heading etc I get these from the phone. Everything will go to the data center either readtime, batched or offline via WIFI. I assign a timestamp user id and will store data for 24 hours for free.

Total Pageviews

Followers