manekinekko / angular-web-bluetooth

The missing Web Bluetooth module for Angular
https://manekinekko.github.io/angular-web-bluetooth/
MIT License
195 stars 56 forks source link

Number format from BLE scale #68

Closed nikmartin closed 4 years ago

nikmartin commented 4 years ago

I have a scale that I'm trying to read from. When connecting to it via nrfConnect, and reading the value from the device's weight service/characteristic, I get this in the log:


V   19:03:51.236    Reading descriptor 00002904-0000-1000-8000-00805f9b34fb
D   19:03:51.236    gatt.readDescriptor(00002904-0000-1000-8000-00805f9b34fb)
I   19:03:51.612    Read Response received from descr. 00002904-0000-1000-8000-00805f9b34fb, value: (0x) 10-FA-02-27-00-00-00
A   19:03:51.612    "Format: signed 32-bit integer
Exponent: -6
Unit: mass (kilogram)
Namespace: Reserved for future use (0)
Description: 0" received

This somehow tells nrfConnect that the values in characteristic 1bc50002 are to be interpreted as kG, in the format of a Int32 with an exponent of -6 Then, if I read the weight, I get:

V   19:05:48.854    Reading characteristic 1bc50002-0200-0aa5-e311-24cb004a98c5
D   19:05:48.854    gatt.readCharacteristic(1bc50002-0200-0aa5-e311-24cb004a98c5)
I   19:05:49.112    Read Response received from 1bc50002-0200-0aa5-e311-24cb004a98c5, value: (0x) E3-2C-00-00
A   19:05:49.112    "0.011491 kg" received

V   19:06:34.036    Reading characteristic 1bc50002-0200-0aa5-e311-24cb004a98c5
D   19:06:34.036    gatt.readCharacteristic(1bc50002-0200-0aa5-e311-24cb004a98c5)
I   19:06:34.287    Read Response received from 1bc50002-0200-0aa5-e311-24cb004a98c5, value: (0x) 75-E8-FF-FF
A   19:06:34.287    "-0.006027 kg" received

So, I used the battery level example, and put together this code to read from the scale:

static GATT_PRIMARY_SERVICE = '1bc50001-0200-0aa5-e311-24cb004a98c5';
static GATT_CHARACTERISTIC_WEIGHT = '1bc50002-0200-0aa5-e311-24cb004a98c5';

value() {
      return this.ble.discover$({
        acceptAllDevices: true,
        optionalServices: [WeightService.GATT_PRIMARY_SERVICE]
      })
      .pipe(

        // 2) get that service
        mergeMap((gatt: BluetoothRemoteGATTServer) => {
          // gatt.connect();
          return this.ble.getPrimaryService$(gatt, WeightService.GATT_PRIMARY_SERVICE);
        }),

        // 3) get a specific characteristic on that service
        mergeMap((primaryService: BluetoothRemoteGATTService) => {
          return this.ble.getCharacteristic$(primaryService, WeightService.GATT_CHARACTERISTIC_WEIGHT);
        }),

        // 4) ask for the value of that characteristic (will return a DataView)
        mergeMap((characteristic: BluetoothRemoteGATTCharacteristic) => {
          return this.ble.readValue$(characteristic);
        }),

        // 5) on that DataView, get the right value
        map((value: DataView) => {

          console.log(value);
          return value.getInt32(0);
        }
        )
      );
  }

and in the DataView, I get values like: Uint8[35, 234, 255, 255]

Which correspond with the same values from nrfConnect when the scale is empty.

My question is how do I convert this data into a weight using the information from the device that the values are '32 bit integer with an exponent of -6 and the format is mass (kg)' I played around with the data from nRFConnect (0x) 75-E8-FF-FF === -0.006027kg and am unable to figure anything out.

nikmartin commented 4 years ago

I think I was overthinking this, because when I woke up this morning, it hit me:

return value.getInt32(0, true) * Math.pow(10, -6);

I need to get a signed int from the DataView, then multiply it by 10^-6