DeviceConnect / DeviceConnect-Android

Device Connect Plug-In for Android
MIT License
52 stars 22 forks source link

HeartRate BLE not correctly implemented and not fully exposed to Health interface #163

Open ssandon opened 8 years ago

ssandon commented 8 years ago

On Polar H7 the HeartRate measurement doesn't works.

According to https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.heart_rate_measurement.xml It seems that Energy and HeartRate are interverted.

Other issues is that Health Profile is not fully exposed (cannot request RR-interval for exemple). Other things, battery should be exposed as service.

Following, code with correct bitmask.

private void notifyHeartRateMeasurement(final BluetoothGatt gatt,
            final BluetoothGattCharacteristic characteristic) {
        int heartRate = 0;
        int energyExpended = 0;
        double rrInterval = 0;
        int offset = 1;

        byte[] buf = characteristic.getValue();

        if (buf.length > 1) {
            // Heart Rate Value Format bit
            if ((buf[0] & 0x01) != 0) {
                Integer v = characteristic.getIntValue(FORMAT_UINT16, offset);
                if (v != null) {
                    heartRate = v;
                }
                offset += 2;
            } else {
                Integer v = characteristic.getIntValue(FORMAT_UINT8, offset);
                if (v != null) {
                    heartRate = v;
                }
                offset += 1;
            }

            // Sensor Contact Status bits
            if ((buf[0] & 0x06) != 0) {
                // MEMO: not implements yet
            }

            // Energy Expended Status bit
            if ((buf[0] & 0x08) != 0) {
                Integer v = characteristic.getIntValue(FORMAT_UINT16, offset);
                if (v != null) {
                    energyExpended = v;
                }
                offset += 2;
            }

            // RR-Interval bit
            Integer v = characteristic.getIntValue(FORMAT_UINT16, offset);
            if (v != null) {
                rrInterval = ((float) v / 1024.0) * 1000.0;
            }

        }

        mLogger.warning("@@@@@@ HEART RATE[" + heartRate + ", "
                + energyExpended + ", " + rrInterval + "]");

        BluetoothDevice device = gatt.getDevice();
        if (mListener != null) {
            mListener.onReceivedData(device, heartRate, energyExpended, rrInterval);
        }
    }
Onuzimoyr commented 8 years ago

Thanks for the sample code.

On Polar H7 the HeartRate measurement doesn't works.

Currently we don't have Polar H7, but tested heartrate measurement with 2 devices, EPSON PS-100 and MIO FUSE, then finally it worked with both. We would once show you a procedure for test as following, and like to hear some more details of failure from you.

+++ PROCEDURE +++

  1. Download https://github.com/DeviceConnect/DeviceConnect-Docs/blob/master/Bin/demoWebSite.zip into local of smartphone you using. (e.g. /sdcard/Download)
  2. Unzip the archive
  3. Go to directory "/apk/"
  4. Install Device Connect Manager by "dConnectManager.apk"
  5. Install HeartRate measurement Plugin by "dConnectDeviceHeartRate.apk"
  6. Uncheck "Local OAuth" and "Origin" in Device Connect Manager if they are checked
  7. Register a heartrate device in plugin setting in Device Connect Manager
  8. Start the Manager
  9. Access file:////index.html with Firefox
  10. Tap "Launch UI-App" >> "Search Device" >> Registered Device >> "health" >> "Heart Rate"
  11. Do command "Get Heart Rate"

It seems that Energy and HeartRate are interverted. Other issues is that Health Profile is not fully exposed (cannot request RR-interval for exemple). Other things, battery should be exposed as service.

Current sample code is just experimentally made which is uploaded on GitHub. We would appreciate you to refer to the code when you make a plugin of heartrate measurement function. (If you made a plugin with Device WebAPI, we would happy if you can show us a demonstration movie or slide show ;)

Besides we would like to annouce you that we have contributed API specification relating to healthcare (you can see documents in http://en.device-webapi.org/link.html#oma-draft) to Open Mobile Alliance, and it is now under review in the Alliance.

ssandon commented 8 years ago

Hi,

Sorry I was not enough precise on my description.

HeartRate value is ok, but it could be wrong in certain case (UINT8 or UINT16 reading).

However on the current implementation and according to Bluetooth BLE HeartRate GATT Characteristics, the notifyHeartRateMeasurement method has several bugs due to wrong bit-masking. The decoding is then completely flawed.

For example : Energy Expanded and RR-Interval values are swapped.

Is this code current GotAPI reference implementation ?

Regards

Onuzimoyr commented 8 years ago

Thanks for more explanation.

HeartRate value is ok, but it could be wrong in certain case (UINT8 or UINT16 reading).

Understood your point on heartrate that plugin seems to deal with the value as UINT8 even though H7 sends the value as UINT16. (If above understanding is wrong, please kindly correct.)

Masking portion was revised, and the revised one was pushed onto GitHub. Thank you for the issue.

Is this code current GotAPI reference implementation ?

All codes are published on GitHub are just samples so that developers can make apps or plugins more easily when using Device WebAPI.

Onuzimoyr commented 7 years ago

@ssandon The fixed was merged on https://github.com/DeviceConnect/DeviceConnect-Android/pull/164. If there is no other issue, I will close this.

Thank you for your pointing out.