Skip to content

Instantly share code, notes, and snippets.

@thebabush
Created March 28, 2020 19:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save thebabush/7c0c4582880114bfa0edadef0cd281fe to your computer and use it in GitHub Desktop.
Save thebabush/7c0c4582880114bfa0edadef0cd281fe to your computer and use it in GitHub Desktop.
Vigorun Python Example
#!/usr/bin/env python3
import pygatt
"""
adc <= 1000
age <= 120
heigth <= 269
weight <= 220
"""
SEX_MALE = 1
SEX_FEMALE = 2
AGE = 16
HEIGHT = 203
SEX = SEX_MALE
BFR_AGE_K = [0.467, 0.676]
BFR_ADC_K = [173870.0, 120090.0]
BFR_K0 = [430.0, 376.0]
BFR_BMI_ADC_K = [5.56421e7, 5.06791e7]
def calc_bfr(age, sex, bmi, adc):
"""
Body fat ratio.
"""
adjusted_bmi = bmi * 10
sex = int(sex == SEX_MALE)
bfr = BFR_AGE_K[sex] * age + BFR_ADC_K[sex] / adc + BFR_K0[sex] - BFR_BMI_ADC_K[sex] / (adjusted_bmi * adc);
bfr /= 10
if bfr <= 4.0:
bfr = 4.0
elif bfr >= 60.0:
bfr = 60.0
return bfr
def calc_rom(weight, height_cm, sex, age, adc):
"""
Rate of muscle.
"""
# convert to meters
height = height_cm / 100.0
if age < 10:
return 5.0
if age <= 15:
if sex == SEX_FEMALE:
k_a = adc
k_b = (adc * 0.0001555 + 0.0448) * weight
k_c = 0.0225
k_d = (adc * -0.032 + 55.76) * height
k_e = -44.41
elif sex == SEX_MALE:
k_a = adc
k_b = (adc * 0.0001262 + 0.2196) * weight
k_c = 0.018
k_d = (adc * -0.031 + 49.64) * height + age * 0.52
k_e = -46.5
else:
raise Exception('Sorry')
else:
k_a = adc
if sex == SEX_FEMALE:
k_b = (adc * 0.0001555 + 0.0448) * weight
k_c = 0.026
k_d = (adc * -0.032 + 55.76) * height
k_e = -45.51
elif sex == SEX_MALE:
k_b = (adc * 0.0001262 + 0.2196) * weight
k_c = 0.018
k_d = (adc * -0.031 + 49.64) * height
k_e = -36.12
else:
raise Exception('Sorry')
rom = k_a * k_c + k_b + k_d + k_e
return max(min(rom, 75.0), 15.0)
report = {}
def handle_data(handle, data):
if len(data) != 8:
return
if data[0] != 0xAC:
return
chksum = sum(data[2:7]) & 0xFF
if chksum != data[7]:
print('wrong checksum')
return
type = data[6]
if type == 0xCA or type == 0xCE:
# weight
# CE = realtime
# CA = final
weight = (data[2] << 8) | data[3]
weight = weight / 10.0
weight_desc = 'final' if type == 0xCA else 'realtime'
print(f'WEIGHT: {weight:.2f} kg ({weight_desc})')
bmi = weight / (HEIGHT / 100.0)**2
print(f' bmi = {bmi}')
report['weight'] = weight
report['bmi'] = bmi
return
if type == 0xCB:
# body fat
subtype = data[2]
if subtype == 0xFD:
# ADC
subsubtype = data[3]
if subsubtype == 0xFF:
pass
elif subsubtype == 0x00:
algo = (data[4] << 8) | data[5]
print(f'ALGORITHM: {algo}')
return
elif subsubtype == 0x01:
adc = (data[4] << 8) | data[5]
print(f'ADC: {adc}')
bmi = report['bmi']
bfr = calc_bfr(AGE, SEX, bmi, adc)
print(f' bfr = {bfr}')
weight = report['weight']
bom = calc_rom(weight, HEIGHT, SEX, AGE, adc)
print(f' bom = {bom:0.1f}')
report['adc'] = adc
return
elif subtype == 0xFE:
# body fat
subsubtype = data[3]
value = (data[4] << 8) | data[5]
if subsubtype == 0:
weight = value
print(f'WEIGHT: {weight}')
return
elif subsubtype == 1:
bmi = value / 10.0
print(f'BMI: {bmi:0.2f}')
return
elif subsubtype == 2:
bfr = value / 10.0
print(f'BFR: {bfr:0.2f}')
return
elif subsubtype == 3:
sfr = value / 10.0
print(f'SFR: {sfr:0.2f}')
return
elif subsubtype == 4:
uvi = value
print(f'UVI: {uvi}')
return
elif subsubtype == 5:
rom = value / 10.0
print(f'ROM: {rom:0.2f}')
return
elif subsubtype == 6:
bmr = value
print(f'BMR: {bmr}')
return
elif subsubtype == 7:
bm = value / 10.0
print(f'BM: {bm:0.2f}')
return
elif subsubtype == 8:
vwc = value / 10.0
print(f'VWC: {vwc:0.2f}')
return
elif subsubtype == 9:
body_age = value
print(f'BODY_AGE: {body_age}')
return
elif subsubtype == 10:
pp = value / 10.0
print(f'PP: {pp:0.2f}')
return
print('UNK:', len(data), data)
if __name__ == '__main__':
# adapter = pygatt.BGAPIBackend()
adapter = pygatt.backends.GATTToolBackend()
try:
adapter.start()
device = adapter.connect('XX:XX:XX:XX:XX:XX')
# TODO: should I really loop? too lazy to look up the internals
while True:
device.subscribe('0000ffb2-0000-1000-8000-00805f9b34fb', callback=handle_data)
import time; time.sleep(60)
finally:
adapter.stop()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment