0.1.8 release

This commit is contained in:
lolouk44 2020-09-08 21:57:22 +01:00
parent ed308f8f84
commit e3b5f12614
5 changed files with 68 additions and 33 deletions

View File

@ -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 ## [0.1.7] - 2020-07-06
### Added ### Added
- repository.json to make it a real add-on repo (fixes https://github.com/lolouk44/hassio-addons/issues/4) - repository.json to make it a real add-on repo (fixes https://github.com/lolouk44/hassio-addons/issues/4)

View File

@ -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... 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! 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 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_SEX | string | Yes | male / female
USER1_NAME | string | Yes | Name of the user USER1_NAME | string | Yes | Name of the user
USER1_HEIGHT | int | Yes | Height (in cm) of the user USER1_HEIGHT | int | Yes | Height (in cm) of the user
USER1_DOB | string | Yes | DOB (in yyyy-mm-dd format) 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_SEX | string | No | male / female. Defaults to female
USER2_NAME | string | No | Name of the user. Defaults to Serena USER2_NAME | string | No | Name of the user. Defaults to Serena
USER2_HEIGHT | int | No |Height (in cm) of the user. Defaults to 95 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 ```yaml
- platform: mqtt - platform: mqtt
name: "Example Name Weight" name: "Example Name Weight"
state_topic: "miScale/USER_NAME/weight" state_topic: "miscale/USER_NAME/weight"
value_template: "{{ value_json['Weight'] }}" value_template: "{{ value_json['Weight'] }}"
unit_of_measurement: "kg" unit_of_measurement: "kg"
json_attributes_topic: "miScale/USER_NAME/weight" json_attributes_topic: "miscale/USER_NAME/weight"
icon: mdi:scale-bathroom icon: mdi:scale-bathroom
- platform: mqtt - platform: mqtt
name: "Example Name BMI" name: "Example Name BMI"
state_topic: "miScale/USER_NAME/weight" state_topic: "miscale/USER_NAME/weight"
value_template: "{{ value_json['BMI'] }}" value_template: "{{ value_json['BMI'] }}"
icon: mdi:human-pregnant icon: mdi:human-pregnant
unit_of_measurement: "kg/m2"
``` ```

View File

@ -1,6 +1,6 @@
{ {
"name": "Xiaomi Mi Scale", "name": "Xiaomi Mi Scale",
"version": "0.1.7", "version": "0.1.8",
"slug": "xiaomi_mi_scale", "slug": "xiaomi_mi_scale",
"description": "Read weight measurements from Xiamomi scale via BLE", "description": "Read weight measurements from Xiamomi scale via BLE",
"url": "https://github.com/lolouk44/xiaomi_mi_scale_ha_add_on", "url": "https://github.com/lolouk44/xiaomi_mi_scale_ha_add_on",

View File

@ -218,9 +218,11 @@ class ScanProcessor():
### Xiaomi V1 Scale ### ### Xiaomi V1 Scale ###
if data.startswith('1d18') and sdid == 22: if data.startswith('1d18') and sdid == 22:
measunit = data[4:6] 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 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 = '' 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(('12', 'b2')): unit = 'jin'
if measunit.startswith(('22', 'a2')): unit = 'kg' ; measured = measured / 2 if measunit.startswith(('22', 'a2')): unit = 'kg' ; measured = measured / 2
if unit: if unit:
@ -249,12 +251,15 @@ class ScanProcessor():
def _publish(self, weight, unit, mitdatetime, hasImpedance, miimpedance): 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 user = USER1_NAME
height = USER1_HEIGHT height = USER1_HEIGHT
age = self.GetAge(USER1_DOB) age = self.GetAge(USER1_DOB)
sex = USER1_SEX sex = USER1_SEX
elif int(weight) < USER2_LT: elif int(calcweight) < USER2_LT:
user = USER2_NAME user = USER2_NAME
height = USER2_HEIGHT height = USER2_HEIGHT
age = self.GetAge(USER2_DOB) age = self.GetAge(USER2_DOB)
@ -264,26 +269,28 @@ class ScanProcessor():
height = USER3_HEIGHT height = USER3_HEIGHT
age = self.GetAge(USER3_DOB) age = self.GetAge(USER3_DOB)
sex = USER3_SEX 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 = '{'
message += '"Weight":"' + "{:.2f}".format(weight) + '"' message += '"weight":"' + "{:.2f}".format(weight) + '"'
message += ',"BMI":"' + "{:.2f}".format(lib.getBMI()) + '"' message += ',"weight_unit":"' + str(unit) + '"'
message += ',"Basal Metabolism":"' + "{:.2f}".format(lib.getBMR()) + '"' message += ',"bmi":"' + "{:.2f}".format(lib.getBMI()) + '"'
message += ',"Visceral Fat":"' + "{:.2f}".format(lib.getVisceralFat()) + '"' message += ',"basal_metabolism":"' + "{:.2f}".format(lib.getBMR()) + '"'
message += ',"visceral_fat":"' + "{:.2f}".format(lib.getVisceralFat()) + '"'
if hasImpedance: 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'] bodyscale = ['Obese', 'Overweight', 'Thick-set', 'Lack-exerscise', 'Balanced', 'Balanced-muscular', 'Skinny', 'Balanced-skinny', 'Skinny-muscular']
message += ',"Lean Body Mass":"' + "{:.2f}".format(lib.getLBMCoefficient()) + '"' message += ',"lean_body_mass":"' + "{:.2f}".format(lib.getLBMCoefficient()) + '"'
message += ',"Body Fat":"' + "{:.2f}".format(lib.getFatPercentage()) + '"' message += ',"body_fat":"' + "{:.2f}".format(lib.getFatPercentage()) + '"'
message += ',"Water":"' + "{:.2f}".format(lib.getWaterPercentage()) + '"' message += ',"water":"' + "{:.2f}".format(lib.getWaterPercentage()) + '"'
message += ',"Bone Mass":"' + "{:.2f}".format(lib.getBoneMass()) + '"' message += ',"bone_mass":"' + "{:.2f}".format(lib.getBoneMass()) + '"'
message += ',"Muscle Mass":"' + "{:.2f}".format(lib.getMuscleMass()) + '"' message += ',"muscle_mass":"' + "{:.2f}".format(lib.getMuscleMass()) + '"'
message += ',"Protein":"' + "{:.2f}".format(lib.getProteinPercentage()) + '"' message += ',"protein":"' + "{:.2f}".format(lib.getProteinPercentage()) + '"'
message += ',"Body Type":"' + str(bodyscale[lib.getBodyType()]) + '"' message += ',"body_type":"' + str(bodyscale[lib.getBodyType()]) + '"'
message += ',"Metabolic Age":"' + "{:.0f}".format(lib.getMetabolicAge()) + '"' message += ',"metabolic_age":"' + "{:.0f}".format(lib.getMetabolicAge()) + '"'
message += ',"TimeStamp":"' + mitdatetime + '"' message += ',"timestamp":"' + mitdatetime + '"'
message += '}' message += '}'
try: try:
sys.stdout.write(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')} - Publishing data to topic {MQTT_PREFIX + '/' + user + '/weight'}: {message}\n") 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 raise
def main(): def main():
if MQTT_DISCOVERY: if MQTT_DISCOVERY.lower() in ['true', '1', 'y', 'yes']:
discovery() discovery()
BluetoothFailCounter = 0 BluetoothFailCounter = 0
while True: 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") sys.stderr.write(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')} - Bluetooth connection error: {error}\n")
if BluetoothFailCounter >= 4: if BluetoothFailCounter >= 4:
sys.stderr.write(f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')} - 5+ Bluetooth connection errors. Resetting Bluetooth...\n") 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) ps = subprocess.Popen(cmd, shell=True)
time.sleep(30) time.sleep(30)
BluetoothFailCounter = 0 BluetoothFailCounter = 0

View File

@ -14,19 +14,19 @@ class bodyMetrics:
# Check for potential out of boundaries # Check for potential out of boundaries
if self.height > 220: if self.height > 220:
print("Height is too high (limit: >220cm) or scale is sleeping") 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() exit()
elif weight < 10 or weight > 200: elif weight < 10 or weight > 200:
print("Weight is either too low or too high (limits: <10kg and >200kg) or scale is sleeping") print("Weight is either too low or too high (limits: <10kg and >200kg)")
sys.stderr.write('Weight is above 10kg or below 200kg or scale is sleeping\n') sys.stderr.write('Weight is below 10kg or above 200kg\n')
exit() exit()
elif age > 99: elif age > 99:
print("Age is too high (limit >99 years) or scale is sleeping") print("Age is too high (limit >99 years)")
sys.stderr.write('Age is above 99 years or scale is sleeping\n') sys.stderr.write('Age is above 99 years\n')
exit() exit()
elif impedance > 3000: elif impedance > 3000:
print("Impedance is above 3000ohm or scale is sleeping") print("Impedance is above 3000 Ohm")
sys.stderr.write('Impedance is above 3000ohm or scale is sleeping\n') sys.stderr.write('Impedance is above 3000 Ohm\n')
exit() exit()
# Set the value to a boundary if it overflows # Set the value to a boundary if it overflows