oliexdev / openScale

Open-source weight and body metrics tracker, with support for Bluetooth scales
GNU General Public License v3.0
1.68k stars 292 forks source link

Support request for Chipsea based Body Fat analyzers #496

Open MetalGearSolidNerd opened 4 years ago

MetalGearSolidNerd commented 4 years ago

Hi, It would be great if support for Chipsea based weight scales and body fat analyzers can be added to OpenScale. These chipsets are used in multiple bluetooth enabled weight scales and there is a common app to get the data from sensors - OKOK International

I was able to find a reference ble-lib implementation here

I also converted the document (bluetooth protocol) on the link to english which I am attaching here for your reference

Core Sea Bluetooth Scale Cloud Edition Communication Protocol v0.3.pdf

Let me know if the above is sufficient or should I also provide all the logs and data as per the reverse engineering instructions on the wiki.

Thank you.

oliexdev commented 4 years ago

Yes please provide all logs and data according to the openScale wiki. The pdf is only a small part of the protocol. The calculation is done in the .so library which needs to be reverse engineered.

MetalGearSolidNerd commented 4 years ago

I returned the body fat analyzer due to some issues and will not be able to provide requested data. Sorry about that, please close this issue if required.

VarshaVijayvargiya commented 4 years ago

@MetalGearSolidNerd : Let me know what issue you found in android. I don't found any issue , let me know there is any problem with your reference sdk which you found: here

Your reference help me alot to get weight data.

inzanity commented 4 years ago

There's relevant log and data in #410, it seems to be a chipsea based scale using the "OKOK protocol". As suggested by the doc, the scale does not actually do any calculation, it only provides weight and 1 or 2 resistance values (depending on model).

From logcat with a "EB8217": 09-09 10:09:22.034 29649 29816 I CsBtUtil_v11: 0xca,0x20,0x0b,0x00,0x00,0x00,0x00,0x01,0x01,0xeb,0x03,0xb6,0x13,0x8a,0xec,0xed,0x67,0x37,0x1b,0x50,0x8c,

yields 09-09 10:09:22.035 29649 29816 I CsBtUtil_v11: chipseaBroadcastFrame{version=32, deviceType=2, cmdId=1, weight=95.0, productId=0, mac='ED:67:37:1B:50:8C', procotalType='OKOK', scaleWeight='95.0', scaleProperty=1, measureSeqNo=235, r1=500.2}

The eb is the sequence number, following 03 b6 is weight10 and 13 8a is r1 10.

The calculations in the lib probably also use auxiliary data like height and age.

milindnaik007 commented 3 years ago

Found something not sure if this is of help. OKOK Protocol.pdf

inzanity commented 3 years ago

It could help with older scales, but at least my EB8217 and the BL-26L01 use version 0x20 (2.0?) of the protocol, whereas the provided spec is v1.1. (0x11)

leomeneguzzi commented 3 years ago

There's relevant log and data in #410, it seems to be a chipsea based scale using the "OKOK protocol". As suggested by the doc, the scale does not actually do any calculation, it only provides weight and 1 or 2 resistance values (depending on model).

Hi everyone, I'm new to these terms about scales, so sorry for the dumb question. But this means that scales using "OKOK protocol" don't give all the usual information to calculate bioimpedance?

inzanity commented 3 years ago

Studied this one a bit more, and with the help of the 1.1 spec and some additional data:

The rest is simply the MAC of the device.

This is constantly broadcasted as advertisement messages in Manufacturer specific data until the device turns off. As far as I've seen, the device name in the messages is always ADV.

ag88 commented 3 years ago

hi can you add support for the older chipsea / OKOK 1.1 scale as well? ref: that old 1.1 OKOK protocol specs https://github.com/oliexdev/openScale/files/5224454/OKOK.Protocol.pdf this data is captured on my scale

then i used this app https://play.google.com/store/apps/details?id=uk.co.alt236.btlescan

a capture of the broadcast captured looked as follows

DEVICE INFO

Device Name:

Device address: 08:B2:1E:15:6E:DB

Device Class: Unknown, Unknown (class=0)
Major Class: Misc

Services: No known services

Bonding State: Unbonded

RSSI INFO

First Timestamp: 2021 -06-05T08:35:43.589 UTC
First RSSI: -63db

Last Timestamp: 2021-06-05T08:35:44.712 UTC
Last RSSI: -62db

Running Average RSSI: -61.0db

SCAN RECORD

[02, 01, 06, 1A, FF, CA, 11, 0F, 00,
01, 02, F2, 58, 21, 33, 2E, 00, 00, 00,
00, 00, 00, 00, 41, C8, B2, 1E, 15, 6E,
DB, 03, 03, F0, FF, 0C, 09, 43, 68, 69,
70, 73, 65, 61, 2D, 42, 4C, 45, 00, 00,
00, 00, 00, 00, 00, 00, 00, 00, 00,
00, 00, 00, 00]

RAW AD RECORDS

#1Flags

Length: 1

As UTF-8: ' '

As Chars: "=K'

As Array: '[06]'

#255 Manufacturer Specific Data

Length: 25

AS UTF-8: '9 9X13. AV né'

As Chars: ' 1% ‘1"vai'xX ! 3 . "UL"UL"UL"UL"UL"UL"ULAE|H “s"AKnJ '

AsArray: '[CA, 11, 0F, 00, 01, 02, F2, 58, 21,
33, 2E, 00, 00, 00, 00, 00, 00, 00, 41,
C8, B2, 1E, 15, 6E, DB]'

#3 Complete list of 16-bit UUIDs available

Length: 2
As UTF-8: '??'
As Chars: '??'

As Array: '[F0, FF]'

#9 Name (Complete)

Length: 11

As UTF-8: 'Chipsea—BLE'
As Chars: 'Chipsea-BLE'

AsArray: '[43, 68, 69, 70, 73, 65, 61, 2D,
42, 4C, 45]'
ag88 commented 3 years ago

apparently the device name is bundled as part of the broadcast payload as the 'last' field as Chipsea-BLE

in decoding against the spec https://github.com/oliexdev/openScale/files/5224454/OKOK.Protocol.pdf the payload fragment that starts with 'CA' is as follows index data description
1 CA Start byte, magic identifier
2 11 Protocol version number, V1.1
3 0F Domain data length
4 00 00 not locked, 01 locked
5 01 Device type, Bluetooth body grease scale
6 02 weight byte MSB
7 F2 weight byte LSB
8-11 58, 21, 33, 2E product ID
12 00 body properties
13 00 hold back / reserved
14 00 hold back / reserved
15 00 hold back / reserved
16 00 hold back / reserved
17 00 hold back / reserved
18 00 hold back / reserved
19 41 check code
19-24 C8, B2, 1E, 15, 6E, DB unknown data not in spec

intepretation of 'body properties' field

Bit4-3 Unit selection
00 = KG (default)
01 = Jin
10 = LB
11 = ST:LB
Bit 2-1
Decimal digit selection
00 = 1 decimal(default)
01 = 0 decimal
10 = 2 decimal

hope this helps, thanks much !

inzanity commented 3 years ago

Getting the same level of support as for 2.0 currently (i.e. weight only) should be quite trivial, just adding another manufacturer data id 0x11ca and choosing parsing method based on the received identifier.

However, while getting the body composition data out of a 1.1 scale does not require reverse engineering the algorithms, it does require two-way communication with the scale, sending it age, sex and height information (as well as previous weight, so the scale can guess who is on it), and possibly also doing the choice of which user if multiple fit in the weight bracket.

ag88 commented 3 years ago

i'd guess we can ignore body composition for now, the interesting data is simply the weight which is found in the advertisement packet. apparently, decoding the device name requires decoding the advertising payload. i'm not familiar with BT LE, i just happen to see the decoded scan data from the Bluetooth LE scanner app.
As I observed, this scale works by starting the broadcast shortly after i stand on the scale and it turns off BLE after a short delay. my guess is like 30 secs. hence, i'd need to connect the moment after weighing which i'd guess is simply to scan for the broadcasts within that delay period. Hence, it'd likely not store history as well. mutual exclusion is achieved, by having 1 scale active at a time, my guess is there'd be a confusion if there are multiple scales used. a way to tell scales apart may be the device address, but this can be alleviated simply managing time based mutual exclusion. e.g. a user can use either of many scales one at a time and ensuring BLE goes off on the other after the delay

inzanity commented 3 years ago

Created PR #738 with a guesswork implementation, but as I have no access to correct hw, I cannot really test it. Also I'm not sure if the bit0 of the body type field should be checked to be 1 to only see the final weight, not catch any intermediate measurement.

ag88 commented 3 years ago

thanks ! i'd try to install a next release and test it. for now my guess is we can assume default kg and one decimal points till someone tells that it's incorrect. we can factor that in as well, but i'd guess 00 (default) is probably there in most scales.

for 'locked' and 'not locked' we'd 'ignore' it. if the user thinks it is 'wrong', delete the last record, weigh again and 'connect' again to sync. on the scale display, it blinks when weight is stable. and the user can always verify the record against that seen on the scale. it is one record at a time after all. edit: i did some experiments i stand on the scale and wait for the display to flash (weight stable), then use the ble scanner app to check the broadcast packet https://play.google.com/store/apps/details?id=uk.co.alt236.btlescan i did that including scanning multiple times, i noted that even if the display flash, indicating a stable weight, byte 4 which is supposed to indicate 'not locked' 0 or 'locked' 1 :
remains as '0' (not locked) , but the weight value in the broadcast payload matches that i see on the scale. hence, i'd guess we'd ignore that 4th 'locked' / 'not locked' byte till someone says it works (an alternative, more complicated way is to take multiple scans and monitor convergence, but i'd guess we'd do that as 'enhancements' ;)

ag88 commented 3 years ago

as i read the specs, maybe there are other data in the 'connected' mode, but for now we'd make do with just extracting data from the broadcasts which is purely the current weight data.

ag88 commented 2 years ago

hi all, just feedback, I tested openScale 2.4.0 release on my ChipSea based OKOK 1.1 scale https://github.com/oliexdev/openScale/releases/tag/v2.4.0 And it works ! Thanks all. The key is one need to connect BLE while standing on the scale and when a stable weight is displayed on the LCD. This won't retrieve any history and only the weight as received in the BLE broadcast is recorded.

This has been implemented in PR and is available from v2.4.0 https://github.com/oliexdev/openScale/pull/738

arisada commented 6 months ago

Hi,

I'm trying to add support for a cheap noname smart scale I bought on Amazon last year. It looks like an OKOK 2.0 scale but it's slightly different. I did packet capture and reverse engineered the APK. Weirdly enough, this fomat is internally called OKOKBroadcast. private void okokBroadcasetV2Parser(byte[] bArr, String str) { (not a typo)

I reverse engineered this binary format from the APK:

Byte type    description
0    uint8   c0 for OkOkV2Broadcast
1    int8    Measure sequence number if cmd != 0
2,3  uint16  weight
4,5  uint16  impedance
6,7  uint16  productid
8    int8    cmd
9-15 6xint8  MAC address

cmd & 1 -> contains weight data
cmd & 0x0e -> divisor
cmd & 0x30 -> unit (kg, lb)

I started implementing it in OpenScale but there are two blocking issues:

I don't have enough experience with BLE to judge if this is an extreme implementation or if it's totally out of specs. I also never connected it to the vendor-supplied APK because it requires cloud authentication before doing anything. Would you think the app would initialize it properly on first use ? I'm joining a capture from nRF Connect which shows the same device sending 4 separate measurements.

Screenshot_2024-03-13-23-46-38-165-edit_no nordicsemi android mcp

Screenshot_2024-03-13-23-47-08-415_no nordicsemi android mcp