From e3b5f12614c7b36a7d913e80aa5b72b4bad7fd39 Mon Sep 17 00:00:00 2001 From: lolouk44 Date: Tue, 8 Sep 2020 21:57:22 +0100 Subject: [PATCH] 0.1.8 release --- mi-scale/CHANGELOG.md | 17 ++++++++ mi-scale/README.md | 18 +++++--- mi-scale/config.json | 2 +- mi-scale/src/Xiaomi_Scale.py | 50 ++++++++++++++--------- mi-scale/src/Xiaomi_Scale_Body_Metrics.py | 14 +++---- 5 files changed, 68 insertions(+), 33 deletions(-) diff --git a/mi-scale/CHANGELOG.md b/mi-scale/CHANGELOG.md index 54eb288..ade818c 100644 --- a/mi-scale/CHANGELOG.md +++ b/mi-scale/CHANGELOG.md @@ -1,3 +1,20 @@ +## [0.1.8] - 2020-09-08 +### Breaking Changes +- Attributes are now snake_case (fixes https://github.com/lolouk44/xiaomi_mi_scale/issues/24) + +### Changed +- Fixed default MQTT Prefix in config.json typo (fixes https://github.com/lolouk44/hassio-addons/issues/6) +- Fixed MQTT Discovery value check to discover +- Changed timestamp to default python format +- Changes the bluetooth reset from reset to down-wait-up (fixes https://github.com/lolouk44/hassio-addons/issues/13) +- Fixed hard coded hci0 to provided hci interface when performing a reset +- Fixed weight in Lbs not detected on Scale V1 (XMTZCO1HM) (fixes https://github.com/lolouk44/xiaomi_mi_scale/issues/28) +- Fixed body calculations for non kg weights +- Updated README + +### Added +- Added unit to attributes + ## [0.1.7] - 2020-07-06 ### Added - repository.json to make it a real add-on repo (fixes https://github.com/lolouk44/hassio-addons/issues/4) diff --git a/mi-scale/README.md b/mi-scale/README.md index 16fc93f..c94a23e 100644 --- a/mi-scale/README.md +++ b/mi-scale/README.md @@ -40,14 +40,21 @@ MQTT_DISCOVERY_PREFIX | string | No | MQTT Discovery Prefix for Home Assistant. Auto-gender selection/config -- This is used to create the calculations such as BMI, Water/Bone Mass etc... Up to 3 users possible as long as weights do not overlap! +Here is the logic used to assign a measured weight to a user: +``` +if [measured value in kg] is greater than USER1_GT, assign it to USER1 +else if [measured value in kg] is less than USER2_LT, assign it to USER2 +else assign it to USER3 (e.g. USER2_LT < [measured value in kg] < USER1_GT) +``` + Option | Type | Required | Description --- | --- | --- | --- -USER1_GT | int | Yes | If the weight is greater than this number, we'll assume that we're weighing User #1 +USER1_GT | int | Yes | If the weight (in kg) is greater than this number, we'll assume that we're weighing User #1 USER1_SEX | string | Yes | male / female USER1_NAME | string | Yes | Name of the user USER1_HEIGHT | int | Yes | Height (in cm) of the user USER1_DOB | string | Yes | DOB (in yyyy-mm-dd format) -USER2_LT | int | No | If the weight is less than this number, we'll assume that we're weighing User #2. Defaults to USER1_GT Value +USER2_LT | int | No | If the weight (in kg) is less than this number, we'll assume that we're weighing User #2. Defaults to USER1_GT Value USER2_SEX | string | No | male / female. Defaults to female USER2_NAME | string | No | Name of the user. Defaults to Serena USER2_HEIGHT | int | No |Height (in cm) of the user. Defaults to 95 @@ -67,17 +74,18 @@ Under the `sensor` block, enter as many blocks as users configured in your envir ```yaml - platform: mqtt name: "Example Name Weight" - state_topic: "miScale/USER_NAME/weight" + state_topic: "miscale/USER_NAME/weight" value_template: "{{ value_json['Weight'] }}" unit_of_measurement: "kg" - json_attributes_topic: "miScale/USER_NAME/weight" + json_attributes_topic: "miscale/USER_NAME/weight" icon: mdi:scale-bathroom - platform: mqtt name: "Example Name BMI" - state_topic: "miScale/USER_NAME/weight" + state_topic: "miscale/USER_NAME/weight" value_template: "{{ value_json['BMI'] }}" icon: mdi:human-pregnant + unit_of_measurement: "kg/m2" ``` diff --git a/mi-scale/config.json b/mi-scale/config.json index 637c17d..e04c468 100644 --- a/mi-scale/config.json +++ b/mi-scale/config.json @@ -1,6 +1,6 @@ { "name": "Xiaomi Mi Scale", - "version": "0.1.7", + "version": "0.1.8", "slug": "xiaomi_mi_scale", "description": "Read weight measurements from Xiamomi scale via BLE", "url": "https://github.com/lolouk44/xiaomi_mi_scale_ha_add_on", diff --git a/mi-scale/src/Xiaomi_Scale.py b/mi-scale/src/Xiaomi_Scale.py index f4e3494..3fc8df9 100644 --- a/mi-scale/src/Xiaomi_Scale.py +++ b/mi-scale/src/Xiaomi_Scale.py @@ -218,9 +218,11 @@ class ScanProcessor(): ### Xiaomi V1 Scale ### if data.startswith('1d18') and sdid == 22: measunit = data[4:6] + sys.stdout.write(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')} - Measuring Unit: {measunit}\n") measured = int((data[8:10] + data[6:8]), 16) * 0.01 + sys.stdout.write(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')} - Measured Raw Weight: {measured}\n") unit = '' - if measunit.startswith(('03', 'b3')): unit = 'lbs' + if measunit.startswith(('03', 'a3')): unit = 'lbs' if measunit.startswith(('12', 'b2')): unit = 'jin' if measunit.startswith(('22', 'a2')): unit = 'kg' ; measured = measured / 2 if unit: @@ -249,12 +251,15 @@ class ScanProcessor(): def _publish(self, weight, unit, mitdatetime, hasImpedance, miimpedance): - if int(weight) > USER1_GT: + if unit == "lbs": calcweight = round(weight * 0.4536, 2) + if unit == "jin": calcweight = round(weight * 0.5, 2) + if unit == "kg": calcweight = weight + if int(calcweight) > USER1_GT: user = USER1_NAME height = USER1_HEIGHT age = self.GetAge(USER1_DOB) sex = USER1_SEX - elif int(weight) < USER2_LT: + elif int(calcweight) < USER2_LT: user = USER2_NAME height = USER2_HEIGHT age = self.GetAge(USER2_DOB) @@ -264,26 +269,28 @@ class ScanProcessor(): height = USER3_HEIGHT age = self.GetAge(USER3_DOB) sex = USER3_SEX - lib = Xiaomi_Scale_Body_Metrics.bodyMetrics(weight, height, age, sex, 0) + + lib = Xiaomi_Scale_Body_Metrics.bodyMetrics(calcweight, height, age, sex, 0) message = '{' - message += '"Weight":"' + "{:.2f}".format(weight) + '"' - message += ',"BMI":"' + "{:.2f}".format(lib.getBMI()) + '"' - message += ',"Basal Metabolism":"' + "{:.2f}".format(lib.getBMR()) + '"' - message += ',"Visceral Fat":"' + "{:.2f}".format(lib.getVisceralFat()) + '"' + message += '"weight":"' + "{:.2f}".format(weight) + '"' + message += ',"weight_unit":"' + str(unit) + '"' + message += ',"bmi":"' + "{:.2f}".format(lib.getBMI()) + '"' + message += ',"basal_metabolism":"' + "{:.2f}".format(lib.getBMR()) + '"' + message += ',"visceral_fat":"' + "{:.2f}".format(lib.getVisceralFat()) + '"' if hasImpedance: - lib = Xiaomi_Scale_Body_Metrics.bodyMetrics(weight, height, age, sex, int(miimpedance)) + lib = Xiaomi_Scale_Body_Metrics.bodyMetrics(calcweight, height, age, sex, int(miimpedance)) bodyscale = ['Obese', 'Overweight', 'Thick-set', 'Lack-exerscise', 'Balanced', 'Balanced-muscular', 'Skinny', 'Balanced-skinny', 'Skinny-muscular'] - message += ',"Lean Body Mass":"' + "{:.2f}".format(lib.getLBMCoefficient()) + '"' - message += ',"Body Fat":"' + "{:.2f}".format(lib.getFatPercentage()) + '"' - message += ',"Water":"' + "{:.2f}".format(lib.getWaterPercentage()) + '"' - message += ',"Bone Mass":"' + "{:.2f}".format(lib.getBoneMass()) + '"' - message += ',"Muscle Mass":"' + "{:.2f}".format(lib.getMuscleMass()) + '"' - message += ',"Protein":"' + "{:.2f}".format(lib.getProteinPercentage()) + '"' - message += ',"Body Type":"' + str(bodyscale[lib.getBodyType()]) + '"' - message += ',"Metabolic Age":"' + "{:.0f}".format(lib.getMetabolicAge()) + '"' + message += ',"lean_body_mass":"' + "{:.2f}".format(lib.getLBMCoefficient()) + '"' + message += ',"body_fat":"' + "{:.2f}".format(lib.getFatPercentage()) + '"' + message += ',"water":"' + "{:.2f}".format(lib.getWaterPercentage()) + '"' + message += ',"bone_mass":"' + "{:.2f}".format(lib.getBoneMass()) + '"' + message += ',"muscle_mass":"' + "{:.2f}".format(lib.getMuscleMass()) + '"' + message += ',"protein":"' + "{:.2f}".format(lib.getProteinPercentage()) + '"' + message += ',"body_type":"' + str(bodyscale[lib.getBodyType()]) + '"' + message += ',"metabolic_age":"' + "{:.0f}".format(lib.getMetabolicAge()) + '"' - message += ',"TimeStamp":"' + mitdatetime + '"' + message += ',"timestamp":"' + mitdatetime + '"' message += '}' try: sys.stdout.write(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')} - Publishing data to topic {MQTT_PREFIX + '/' + user + '/weight'}: {message}\n") @@ -302,7 +309,7 @@ class ScanProcessor(): raise def main(): - if MQTT_DISCOVERY: + if MQTT_DISCOVERY.lower() in ['true', '1', 'y', 'yes']: discovery() BluetoothFailCounter = 0 while True: @@ -316,7 +323,10 @@ def main(): sys.stderr.write(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')} - Bluetooth connection error: {error}\n") if BluetoothFailCounter >= 4: sys.stderr.write(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')} - 5+ Bluetooth connection errors. Resetting Bluetooth...\n") - cmd = 'hciconfig hci0 reset' + cmd = 'hciconfig hci' + HCI_DEV + ' down' + ps = subprocess.Popen(cmd, shell=True) + time.sleep(1) + cmd = 'hciconfig hci' + HCI_DEV + ' up' ps = subprocess.Popen(cmd, shell=True) time.sleep(30) BluetoothFailCounter = 0 diff --git a/mi-scale/src/Xiaomi_Scale_Body_Metrics.py b/mi-scale/src/Xiaomi_Scale_Body_Metrics.py index 059e1ee..420c22a 100644 --- a/mi-scale/src/Xiaomi_Scale_Body_Metrics.py +++ b/mi-scale/src/Xiaomi_Scale_Body_Metrics.py @@ -14,19 +14,19 @@ class bodyMetrics: # Check for potential out of boundaries if self.height > 220: print("Height is too high (limit: >220cm) or scale is sleeping") - sys.stderr.write('Height is over 220cm or scale is sleeping\n') + sys.stderr.write('Height is over 220cm\n') exit() elif weight < 10 or weight > 200: - print("Weight is either too low or too high (limits: <10kg and >200kg) or scale is sleeping") - sys.stderr.write('Weight is above 10kg or below 200kg or scale is sleeping\n') + print("Weight is either too low or too high (limits: <10kg and >200kg)") + sys.stderr.write('Weight is below 10kg or above 200kg\n') exit() elif age > 99: - print("Age is too high (limit >99 years) or scale is sleeping") - sys.stderr.write('Age is above 99 years or scale is sleeping\n') + print("Age is too high (limit >99 years)") + sys.stderr.write('Age is above 99 years\n') exit() elif impedance > 3000: - print("Impedance is above 3000ohm or scale is sleeping") - sys.stderr.write('Impedance is above 3000ohm or scale is sleeping\n') + print("Impedance is above 3000 Ohm") + sys.stderr.write('Impedance is above 3000 Ohm\n') exit() # Set the value to a boundary if it overflows