Created
March 28, 2020 19:10
-
-
Save thebabush/7c0c4582880114bfa0edadef0cd281fe to your computer and use it in GitHub Desktop.
Vigorun Python Example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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